Merge head 'drm-3264' of master.kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6
authorLinus Torvalds <torvalds@g5.osdl.org>
Sat, 9 Jul 2005 16:58:47 +0000 (09:58 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sat, 9 Jul 2005 16:58:47 +0000 (09:58 -0700)
451 files changed:
Documentation/dvb/README.dvb-usb
Documentation/dvb/bt8xx.txt
Documentation/feature-removal-schedule.txt
Documentation/infiniband/user_verbs.txt [new file with mode: 0644]
Documentation/power/video.txt
MAINTAINERS
Makefile
arch/frv/defconfig [new file with mode: 0644]
arch/i386/kernel/cpu/common.c
arch/i386/kernel/cpu/intel.c
arch/i386/kernel/cpu/mtrr/generic.c
arch/i386/kernel/cpu/mtrr/main.c
arch/i386/kernel/cpu/mtrr/mtrr.h
arch/i386/kernel/smpboot.c
arch/i386/kernel/time.c
arch/i386/kernel/timers/timer_hpet.c
arch/i386/kernel/vmlinux.lds.S
arch/i386/mm/ioremap.c
arch/i386/power/cpu.c
arch/ia64/kernel/Makefile
arch/ia64/kernel/acpi.c
arch/ia64/kernel/numa.c [new file with mode: 0644]
arch/ia64/kernel/signal.c
arch/ia64/kernel/smpboot.c
arch/ia64/kernel/traps.c
arch/ia64/mm/discontig.c
arch/ia64/mm/init.c
arch/ia64/sn/include/pci/pcibr_provider.h [deleted file]
arch/ia64/sn/include/pci/pic.h [deleted file]
arch/ia64/sn/include/pci/tiocp.h [deleted file]
arch/ia64/sn/include/xtalk/hubdev.h
arch/ia64/sn/kernel/io_init.c
arch/ia64/sn/kernel/irq.c
arch/ia64/sn/kernel/setup.c
arch/ia64/sn/kernel/tiocx.c
arch/ia64/sn/pci/pci_dma.c
arch/ia64/sn/pci/pcibr/pcibr_ate.c
arch/ia64/sn/pci/pcibr/pcibr_dma.c
arch/ia64/sn/pci/pcibr/pcibr_provider.c
arch/ia64/sn/pci/pcibr/pcibr_reg.c
arch/ia64/sn/pci/tioca_provider.c
arch/m32r/kernel/setup_m32700ut.c
arch/m32r/kernel/setup_mappi.c
arch/m32r/kernel/setup_mappi2.c
arch/m32r/kernel/setup_mappi3.c
arch/m32r/kernel/setup_oaks32r.c
arch/m32r/kernel/setup_opsput.c
arch/ppc/platforms/pmac_cpufreq.c
arch/ppc64/kernel/cputable.c
arch/ppc64/kernel/head.S
arch/ppc64/kernel/hvconsole.c
arch/ppc64/kernel/iSeries_setup.c
arch/ppc64/kernel/idle.c
arch/ppc64/kernel/maple_setup.c
arch/ppc64/kernel/misc.S
arch/ppc64/kernel/pSeries_setup.c
arch/ppc64/kernel/pmac_setup.c
arch/ppc64/kernel/setup.c
arch/ppc64/kernel/sys_ppc32.c
arch/ppc64/kernel/sysfs.c
arch/ppc64/kernel/vdso32/vdso32.lds.S
arch/sparc64/Kconfig
arch/sparc64/kernel/dtlb_backend.S
arch/um/Kconfig
arch/um/Kconfig_i386
arch/um/Kconfig_x86_64
arch/um/Makefile-i386
arch/um/Makefile-x86_64
arch/um/defconfig
arch/um/drivers/line.c
arch/um/include/mem.h
arch/um/include/registers.h
arch/um/include/sysdep-i386/ptrace_user.h
arch/um/include/sysdep-i386/stub.h [new file with mode: 0644]
arch/um/include/sysdep-x86_64/ptrace_user.h
arch/um/include/sysdep-x86_64/stub.h [new file with mode: 0644]
arch/um/include/time_user.h
arch/um/include/tlb.h
arch/um/kernel/dyn.lds.S
arch/um/kernel/physmem.c
arch/um/kernel/process.c
arch/um/kernel/skas/Makefile
arch/um/kernel/skas/clone.c [new file with mode: 0644]
arch/um/kernel/skas/exec_kern.c
arch/um/kernel/skas/include/mm_id.h [new file with mode: 0644]
arch/um/kernel/skas/include/mmu-skas.h
arch/um/kernel/skas/include/skas.h
arch/um/kernel/skas/include/stub-data.h [new file with mode: 0644]
arch/um/kernel/skas/mem.c
arch/um/kernel/skas/mem_user.c
arch/um/kernel/skas/mmu.c
arch/um/kernel/skas/process.c
arch/um/kernel/skas/process_kern.c
arch/um/kernel/skas/tlb.c
arch/um/kernel/time.c
arch/um/kernel/tlb.c
arch/um/kernel/tt/tlb.c
arch/um/kernel/uml.lds.S
arch/um/os-Linux/sys-i386/registers.c
arch/um/os-Linux/sys-x86_64/registers.c
arch/um/scripts/Makefile.rules
arch/um/sys-i386/Makefile
arch/um/sys-i386/stub.S [new file with mode: 0644]
arch/um/sys-i386/stub_segv.c [new file with mode: 0644]
arch/um/sys-x86_64/Makefile
arch/um/sys-x86_64/stub.S [new file with mode: 0644]
arch/um/sys-x86_64/stub_segv.c [new file with mode: 0644]
arch/x86_64/kernel/setup.c
arch/x86_64/kernel/suspend.c
arch/x86_64/kernel/vmlinux.lds.S
arch/xtensa/kernel/syscalls.c
arch/xtensa/kernel/syscalls.h
drivers/bluetooth/bluecard_cs.c
drivers/bluetooth/bt3c_cs.c
drivers/bluetooth/btuart_cs.c
drivers/bluetooth/dtl1_cs.c
drivers/bluetooth/hci_vhci.c
drivers/char/Makefile
drivers/char/drm/Kconfig
drivers/char/drm/Makefile
drivers/char/drm/drm_pciids.h
drivers/char/drm/via_3d_reg.h [new file with mode: 0644]
drivers/char/drm/via_dma.c [new file with mode: 0644]
drivers/char/drm/via_drm.h [new file with mode: 0644]
drivers/char/drm/via_drv.c [new file with mode: 0644]
drivers/char/drm/via_drv.h [new file with mode: 0644]
drivers/char/drm/via_ds.c [new file with mode: 0644]
drivers/char/drm/via_ds.h [new file with mode: 0644]
drivers/char/drm/via_irq.c [new file with mode: 0644]
drivers/char/drm/via_map.c [new file with mode: 0644]
drivers/char/drm/via_mm.c [new file with mode: 0644]
drivers/char/drm/via_mm.h [new file with mode: 0644]
drivers/char/drm/via_verifier.c [new file with mode: 0644]
drivers/char/drm/via_verifier.h [new file with mode: 0644]
drivers/char/drm/via_video.c [new file with mode: 0644]
drivers/char/hvc_console.c
drivers/char/hvc_vio.c [new file with mode: 0644]
drivers/char/hvsi.c
drivers/char/n_tty.c
drivers/char/pcmcia/synclink_cs.c
drivers/char/random.c
drivers/char/sysrq.c
drivers/cpufreq/cpufreq.c
drivers/ide/legacy/ide-cs.c
drivers/infiniband/Kconfig
drivers/infiniband/core/Makefile
drivers/infiniband/core/uverbs.h [new file with mode: 0644]
drivers/infiniband/core/uverbs_cmd.c [new file with mode: 0644]
drivers/infiniband/core/uverbs_main.c [new file with mode: 0644]
drivers/infiniband/core/uverbs_mem.c [new file with mode: 0644]
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/mthca/mthca_cq.c
drivers/infiniband/hw/mthca/mthca_dev.h
drivers/infiniband/hw/mthca/mthca_main.c
drivers/infiniband/hw/mthca/mthca_memfree.c
drivers/infiniband/hw/mthca/mthca_memfree.h
drivers/infiniband/hw/mthca/mthca_pd.c
drivers/infiniband/hw/mthca/mthca_provider.c
drivers/infiniband/hw/mthca/mthca_provider.h
drivers/infiniband/hw/mthca/mthca_qp.c
drivers/infiniband/hw/mthca/mthca_user.h [new file with mode: 0644]
drivers/infiniband/include/ib_user_verbs.h [new file with mode: 0644]
drivers/infiniband/include/ib_verbs.h
drivers/isdn/hardware/avm/avm_cs.c
drivers/isdn/hisax/avma1_cs.c
drivers/isdn/hisax/elsa_cs.c
drivers/isdn/hisax/isdnl1.c
drivers/isdn/hisax/isdnl2.c
drivers/isdn/hisax/isdnl3.c
drivers/isdn/hisax/sedlbauer_cs.c
drivers/isdn/hisax/teles_cs.c
drivers/isdn/i4l/isdn_tty.c
drivers/isdn/icn/icn.c
drivers/md/dm-raid1.c
drivers/media/common/saa7146_core.c
drivers/media/dvb/Kconfig
drivers/media/dvb/Makefile
drivers/media/dvb/b2c2/Kconfig
drivers/media/dvb/b2c2/Makefile
drivers/media/dvb/b2c2/flexcop-common.h
drivers/media/dvb/b2c2/flexcop-dma.c
drivers/media/dvb/b2c2/flexcop-hw-filter.c
drivers/media/dvb/b2c2/flexcop-misc.c
drivers/media/dvb/b2c2/flexcop-pci.c
drivers/media/dvb/b2c2/flexcop-reg.h
drivers/media/dvb/b2c2/flexcop-usb.c
drivers/media/dvb/b2c2/flexcop.c
drivers/media/dvb/b2c2/flexcop.h
drivers/media/dvb/b2c2/flexcop_ibi_value_be.h [new file with mode: 0644]
drivers/media/dvb/b2c2/flexcop_ibi_value_le.h [new file with mode: 0644]
drivers/media/dvb/b2c2/skystar2.c [deleted file]
drivers/media/dvb/bt8xx/dst.c
drivers/media/dvb/bt8xx/dst_ca.c
drivers/media/dvb/bt8xx/dst_common.h
drivers/media/dvb/cinergyT2/cinergyT2.c
drivers/media/dvb/dvb-core/dmxdev.c
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvb_frontend.h
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/Makefile
drivers/media/dvb/dvb-usb/a800.c
drivers/media/dvb/dvb-usb/cxusb.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/cxusb.h [new file with mode: 0644]
drivers/media/dvb/dvb-usb/dibusb-mb.c
drivers/media/dvb/dvb-usb/dibusb-mc.c
drivers/media/dvb/dvb-usb/digitv.c
drivers/media/dvb/dvb-usb/dtt200u-fe.c
drivers/media/dvb/dvb-usb/dtt200u.c
drivers/media/dvb/dvb-usb/dtt200u.h
drivers/media/dvb/dvb-usb/dvb-usb-common.h
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/dvb-usb/dvb-usb-init.c
drivers/media/dvb/dvb-usb/dvb-usb-remote.c
drivers/media/dvb/dvb-usb/dvb-usb-urb.c
drivers/media/dvb/dvb-usb/dvb-usb.h
drivers/media/dvb/dvb-usb/nova-t-usb2.c
drivers/media/dvb/dvb-usb/umt-010.c
drivers/media/dvb/dvb-usb/vp7045.c
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/cx22702.c
drivers/media/dvb/frontends/cx22702.h
drivers/media/dvb/frontends/dvb-pll.c
drivers/media/dvb/frontends/dvb-pll.h
drivers/media/dvb/frontends/l64781.c
drivers/media/dvb/frontends/lgdt3302.c [new file with mode: 0644]
drivers/media/dvb/frontends/lgdt3302.h [new file with mode: 0644]
drivers/media/dvb/frontends/lgdt3302_priv.h [new file with mode: 0644]
drivers/media/dvb/frontends/s5h1420.c [new file with mode: 0644]
drivers/media/dvb/frontends/s5h1420.h [new file with mode: 0644]
drivers/media/dvb/frontends/stv0297.c
drivers/media/dvb/frontends/tda1004x.c
drivers/media/dvb/frontends/tda1004x.h
drivers/media/dvb/pluto2/Kconfig [new file with mode: 0644]
drivers/media/dvb/pluto2/Makefile [new file with mode: 0644]
drivers/media/dvb/pluto2/pluto2.c [new file with mode: 0644]
drivers/media/dvb/ttpci/Kconfig
drivers/media/dvb/ttpci/av7110.c
drivers/media/dvb/ttpci/av7110.h
drivers/media/dvb/ttpci/av7110_av.c
drivers/media/dvb/ttpci/av7110_av.h
drivers/media/dvb/ttpci/av7110_hw.c
drivers/media/dvb/ttpci/av7110_hw.h
drivers/media/dvb/ttpci/av7110_ipack.c
drivers/media/dvb/ttpci/budget-av.c
drivers/media/dvb/ttpci/budget-ci.c
drivers/media/dvb/ttpci/budget.c
drivers/media/dvb/ttusb-budget/Kconfig
drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
drivers/media/dvb/ttusb-dec/ttusb_dec.c
drivers/media/dvb/ttusb-dec/ttusbdecfe.c
drivers/media/video/Kconfig
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-core.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/cx88/cx88-i2c.c
drivers/media/video/cx88/cx88-input.c
drivers/media/video/cx88/cx88-mpeg.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/cx88/cx88.h
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptscsih.h
drivers/message/i2o/config-osm.c
drivers/mtd/maps/pcmciamtd.c
drivers/net/hamradio/scc.c
drivers/net/pcmcia/3c574_cs.c
drivers/net/pcmcia/3c589_cs.c
drivers/net/pcmcia/axnet_cs.c
drivers/net/pcmcia/com20020_cs.c
drivers/net/pcmcia/fmvj18x_cs.c
drivers/net/pcmcia/ibmtr_cs.c
drivers/net/pcmcia/nmclan_cs.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/pcmcia/smc91c92_cs.c
drivers/net/pcmcia/xirc2ps_cs.c
drivers/net/ppp_async.c
drivers/net/ppp_generic.c
drivers/net/ppp_synctty.c
drivers/net/skge.c
drivers/net/sungem.c
drivers/net/sungem_phy.c
drivers/net/sungem_phy.h
drivers/net/tun.c
drivers/net/typhoon.c
drivers/net/wireless/airo.c
drivers/net/wireless/airo_cs.c
drivers/net/wireless/atmel_cs.c
drivers/net/wireless/netwave_cs.c
drivers/net/wireless/orinoco_cs.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/wavelan_cs.c
drivers/net/wireless/wavelan_cs.p.h
drivers/net/wireless/wl3501_cs.c
drivers/parport/parport_cs.c
drivers/pci/hotplug/Kconfig
drivers/pci/hotplug/Makefile
drivers/pci/hotplug/sgi_hotplug.c [new file with mode: 0644]
drivers/pci/pcie/portdrv_core.c
drivers/pci/search.c
drivers/pcmcia/Kconfig
drivers/pcmcia/au1000_generic.h
drivers/pcmcia/au1000_pb1x00.c
drivers/pcmcia/au1000_xxs1500.c
drivers/pcmcia/cardbus.c
drivers/pcmcia/cs.c
drivers/pcmcia/cs_internal.h
drivers/pcmcia/ds.c
drivers/pcmcia/hd64465_ss.c
drivers/pcmcia/i82365.c
drivers/pcmcia/m32r_cfc.c
drivers/pcmcia/m32r_pcc.c
drivers/pcmcia/pcmcia_compat.c
drivers/pcmcia/pcmcia_ioctl.c
drivers/pcmcia/pcmcia_resource.c
drivers/pcmcia/sa1100_generic.c
drivers/pcmcia/soc_common.h
drivers/pcmcia/socket_sysfs.c
drivers/pcmcia/tcic.c
drivers/pcmcia/ti113x.h
drivers/pcmcia/yenta_socket.c
drivers/s390/net/claw.c
drivers/s390/net/ctctty.c
drivers/scsi/pcmcia/aha152x_stub.c
drivers/scsi/pcmcia/fdomain_stub.c
drivers/scsi/pcmcia/nsp_cs.c
drivers/scsi/pcmcia/qlogic_stub.c
drivers/scsi/pcmcia/sym53c500_cs.c
drivers/serial/serial_cs.c
drivers/telephony/ixj_pcmcia.c
drivers/usb/host/sl811_cs.c
drivers/usb/net/usbnet.c
drivers/video/fbsysfs.c
drivers/video/logo/Kconfig
drivers/video/logo/Makefile
drivers/video/logo/logo.c
drivers/video/logo/logo_m32r_clut224.ppm [new file with mode: 0644]
drivers/video/s1d13xxxfb.c
drivers/video/savage/savagefb_driver.c
fs/Kconfig
fs/autofs4/waitq.c
fs/bio.c
fs/buffer.c
fs/dcookies.c
fs/ext3/inode.c
fs/hppfs/hppfs_kern.c
fs/inode.c
fs/ioprio.c
fs/locks.c
fs/namei.c
fs/namespace.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4recover.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/vfs.c
fs/super.c
include/asm-alpha/pgtable.h
include/asm-i386/mmzone.h
include/asm-i386/processor.h
include/asm-ia64/sn/arch.h
include/asm-ia64/sn/intr.h
include/asm-ia64/sn/pcibr_provider.h [new file with mode: 0644]
include/asm-ia64/sn/pcidev.h
include/asm-ia64/sn/pic.h [new file with mode: 0644]
include/asm-ia64/sn/sn_cpuid.h
include/asm-ia64/sn/sn_sal.h
include/asm-ia64/sn/tiocp.h [new file with mode: 0644]
include/asm-m32r/s1d13806.h [new file with mode: 0644]
include/asm-ppc/unistd.h
include/asm-ppc64/cputable.h
include/asm-ppc64/hvconsole.h
include/asm-ppc64/machdep.h
include/asm-ppc64/processor.h
include/asm-ppc64/unistd.h
include/asm-sparc64/param.h
include/asm-um/mmu_context.h
include/asm-x86_64/proto.h
include/asm-xtensa/unistd.h
include/linux/buffer_head.h
include/linux/cache.h
include/linux/cpufreq.h
include/linux/fs.h
include/linux/gfp.h
include/linux/igmp.h
include/linux/ioprio.h
include/linux/mount.h
include/linux/namespace.h
include/linux/nfsd/nfsd.h
include/linux/nfsd/state.h
include/linux/skbuff.h
include/linux/slab.h
include/linux/string.h
include/linux/swap.h
include/linux/syscalls.h
include/net/irda/irda_device.h
include/net/sctp/structs.h
include/net/sock.h
include/net/tcp.h
include/pcmcia/cs.h
include/pcmcia/cs_types.h
include/pcmcia/ds.h
include/pcmcia/version.h
ipc/compat.c
kernel/power/disk.c
kernel/power/process.c
kernel/power/swsusp.c
kernel/profile.c
kernel/sched.c
lib/radix-tree.c
mm/mempool.c
mm/oom_kill.c
mm/page_alloc.c
mm/slab.c
net/bluetooth/cmtp/core.c
net/bluetooth/hidp/core.c
net/bluetooth/rfcomm/sock.c
net/bluetooth/rfcomm/tty.c
net/core/dev.c
net/core/skbuff.c
net/core/sock.c
net/decnet/af_decnet.c
net/decnet/dn_nsp_out.c
net/ipv4/icmp.c
net/ipv4/igmp.c
net/ipv4/ip_sockglue.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/ipv4/tcp_timer.c
net/ipv6/mcast.c
net/irda/irlap.c
net/irda/irlap_event.c
net/irda/irlap_frame.c
net/irda/irttp.c
net/llc/llc_c_ev.c
net/netlink/af_netlink.c
net/sched/sch_red.c
net/sctp/associola.c
net/sctp/input.c
net/sctp/inqueue.c
net/sctp/output.c
net/sctp/outqueue.c
net/sctp/sm_make_chunk.c
net/sctp/socket.c
net/sunrpc/xprt.c
net/unix/af_unix.c
security/keys/keyring.c
sound/oss/cs46xx.c
sound/pcmcia/pdaudiocf/pdaudiocf.c
sound/pcmcia/vx/vx_entry.c
sound/pcmcia/vx/vxpocket.c

index c7ed01b9f8f400b28767b349303b0a533a0ca937..ac0797ea646c6f2c725fe4cf8c064ee38532d654 100644 (file)
@@ -13,14 +13,17 @@ different way: With the help of a dvb-usb-framework.
 The framework provides generic functions (mostly kernel API calls), such as:
 
 - Transport Stream URB handling in conjunction with dvb-demux-feed-control
-  (bulk and isoc (TODO) are supported)
+  (bulk and isoc are supported)
 - registering the device for the DVB-API
 - registering an I2C-adapter if applicable
 - remote-control/input-device handling
 - firmware requesting and loading (currently just for the Cypress USB
-  controller)
+  controllers)
 - other functions/methods which can be shared by several drivers (such as
   functions for bulk-control-commands)
+- TODO: a I2C-chunker. It creates device-specific chunks of register-accesses
+  depending on length of a register and the number of values that can be
+  multi-written and multi-read.
 
 The source code of the particular DVB USB devices does just the communication
 with the device via the bus. The connection between the DVB-API-functionality
@@ -36,93 +39,18 @@ the dvb-usb-lib.
 TODO: dynamic enabling and disabling of the pid-filter in regard to number of
 feeds requested.
 
-Supported devices USB1.1
+Supported devices
 ========================
 
-Produced and reselled by Twinhan:
----------------------------------
-- TwinhanDTV USB-Ter DVB-T Device (VP7041)
-       http://www.twinhan.com/product_terrestrial_3.asp
+See the LinuxTV DVB Wiki at www.linuxtv.org for a complete list of
+cards/drivers/firmwares:
 
-- TwinhanDTV Magic Box (VP7041e)
-       http://www.twinhan.com/product_terrestrial_4.asp
-
-- HAMA DVB-T USB device
-       http://www.hama.de/portal/articleId*110620/action*2598
-
-- CTS Portable (Chinese Television System) (2)
-       http://www.2cts.tv/ctsportable/
-
-- Unknown USB DVB-T device with vendor ID Hyper-Paltek
-
-
-Produced and reselled by KWorld:
---------------------------------
-- KWorld V-Stream XPERT DTV DVB-T USB
-       http://www.kworld.com.tw/en/product/DVBT-USB/DVBT-USB.html
-
-- JetWay DTV DVB-T USB
-       http://www.jetway.com.tw/evisn/product/lcd-tv/DVT-USB/dtv-usb.htm
-
-- ADSTech Instant TV DVB-T USB
-       http://www.adstech.com/products/PTV-333/intro/PTV-333_intro.asp?pid=PTV-333
-
-
-Others:
--------
-- Ultima Electronic/Artec T1 USB TVBOX (AN2135, AN2235, AN2235 with Panasonic Tuner)
-       http://82.161.246.249/products-tvbox.html
-
-- Compro Videomate DVB-U2000 - DVB-T USB (2)
-       http://www.comprousa.com/products/vmu2000.htm
-
-- Grandtec USB DVB-T
-       http://www.grand.com.tw/
-
-- AVerMedia AverTV DVBT USB
-       http://www.avermedia.com/
-
-- DiBcom USB DVB-T reference device (non-public)
-
-
-Supported devices USB2.0-only
-=============================
-- Twinhan MagicBox II
-       http://www.twinhan.com/product_terrestrial_7.asp
-
-- TwinhanDTV Alpha
-       http://www.twinhan.com/product_terrestrial_8.asp
-
-- DigitalNow TinyUSB 2 DVB-t Receiver
-       http://www.digitalnow.com.au/DigitalNow%20tinyUSB2%20Specifications.html
-
-- Hanftek UMT-010
-       http://www.globalsources.com/si/6008819757082/ProductDetail/Digital-TV/product_id-100046529
-
-
-Supported devices USB2.0 and USB1.1
-=============================
-- Typhoon/Yakumo/HAMA/Yuan DVB-T mobile USB2.0
-       http://www.yakumo.de/produkte/index.php?pid=1&ag=DVB-T
-       http://www.yuan.com.tw/en/products/vdo_ub300.html
-       http://www.hama.de/portal/articleId*114663/action*2563
-       http://www.anubisline.com/english/articlec.asp?id=50502&catid=002
-
-- Artec T1 USB TVBOX (FX2) (2)
-
-- Hauppauge WinTV NOVA-T USB2
-       http://www.hauppauge.com/
-
-- KWorld/ADSTech Instant DVB-T USB2.0 (DiB3000M-B)
-
-- DiBcom USB2.0 DVB-T reference device (non-public)
-
-- AVerMedia AverTV A800 DVB-T USB2.0
-
-1) It is working almost - work-in-progress.
-2) No test reports received yet.
+http://www.linuxtv.org/wiki/index.php/DVB_USB
 
 0. History & News:
+  2005-06-30 - added support for WideView WT-220U (Thanks to Steve Chang)
+  2005-05-30 - added basic isochronous support to the dvb-usb-framework
+               added support for Conexant Hybrid reference design and Nebula DigiTV USB
   2005-04-17 - all dibusb devices ported to make use of the dvb-usb-framework
   2005-04-02 - re-enabled and improved remote control code.
   2005-03-31 - ported the Yakumo/Hama/Typhoon DVB-T USB2.0 device to dvb-usb.
@@ -137,7 +65,7 @@ Supported devices USB2.0 and USB1.1
   2005-01-31 - distorted streaming is gone for USB1.1 devices
   2005-01-13 - moved the mirrored pid_filter_table back to dvb-dibusb
              - first almost working version for HanfTek UMT-010
-             - found out, that Yakumo/HAMA/Typhoon are predessors of the HanfTek UMT-010
+             - found out, that Yakumo/HAMA/Typhoon are predecessors of the HanfTek UMT-010
   2005-01-10 - refactoring completed, now everything is very delightful
              - tuner quirks for some weird devices (Artec T1 AN2235 device has sometimes a
                Panasonic Tuner assembled). Tunerprobing implemented. Thanks a lot to Gunnar Wittich.
@@ -187,25 +115,13 @@ Supported devices USB2.0 and USB1.1
 1. How to use?
 1.1. Firmware
 
-Most of the USB drivers need to download a firmware to start working.
-
-for USB1.1 (AN2135) you need: dvb-usb-dibusb-5.0.0.11.fw
-for USB2.0 HanfTek: dvb-usb-umt-010-02.fw
-for USB2.0 DiBcom: dvb-usb-dibusb-6.0.0.8.fw
-for USB2.0 AVerMedia AverTV DVB-T USB2: dvb-usb-avertv-a800-01.fw
-for USB2.0 TwinhanDTV Alpha/MagicBox II: dvb-usb-vp7045-01.fw
-
-The files can be found on http://www.linuxtv.org/download/firmware/ .
+Most of the USB drivers need to download a firmware to the device before start
+working.
 
-We do not have the permission (yet) to publish the following firmware-files.
-You'll need to extract them from the windows drivers.
+Have a look at the Wikipage for the DVB-USB-drivers to find out, which firmware
+you need for your device:
 
-You should be able to use "get_dvb_firmware dvb-usb" to get the firmware:
-
-for USB1.1 (AN2235) (a few Artec T1 devices): dvb-usb-dibusb-an2235-01.fw
-for USB2.0 Hauppauge: dvb-usb-nova-t-usb2-01.fw
-for USB2.0 ADSTech/Kworld USB2.0: dvb-usb-adstech-usb2-01.fw
-for USB2.0 Yakumo/Typhoon/Hama: dvb-usb-dtt200u-01.fw
+http://www.linuxtv.org/wiki/index.php/DVB_USB
 
 1.2. Compiling
 
@@ -289,6 +205,9 @@ Patches, comments and suggestions are very very welcome.
    Gunnar Wittich and Joachim von Caron for their trust for providing
     root-shells on their machines to implement support for new devices.
 
+   Allan Third and Michael Hutchinson for their help to write the Nebula
+    digitv-driver.
+
    Glen Harris for bringing up, that there is a new dibusb-device and Jiun-Kuei
     Jung from AVerMedia who kindly provided a special firmware to get the device
     up and running in Linux.
@@ -296,7 +215,12 @@ Patches, comments and suggestions are very very welcome.
    Jennifer Chen, Jeff and Jack from Twinhan for kindly supporting by
        writing the vp7045-driver.
 
-   Some guys on the linux-dvb mailing list for encouraging me
+   Steve Chang from WideView for providing information for new devices and
+       firmware files.
+
+   Michael Paxton for submitting remote control keymaps.
+
+   Some guys on the linux-dvb mailing list for encouraging me.
 
    Peter Schildmann >peter.schildmann-nospam-at-web.de< for his
     user-level firmware loader, which saves a lot of time
@@ -305,4 +229,4 @@ Patches, comments and suggestions are very very welcome.
    Ulf Hermenau for helping me out with traditional chinese.
 
    André Smoktun and Christian Frömmel for supporting me with
-    hardware and listening to my problems very patient.
+    hardware and listening to my problems very patiently.
index 3a326079475864fa8637ab7e998fbbec89fd9416..e6b8d05bc08d1b3d95c213a29023fbdd73802ff7 100644 (file)
@@ -1,66 +1,55 @@
-How to get the Nebula, PCTV and Twinhan DST cards working
-=========================================================
+How to get the Nebula Electronics DigiTV, Pinnacle PCTV Sat, Twinhan DST + clones working
+=========================================================================================
 
-This class of cards has a bt878a as the PCI interface, and
-require the bttv driver.
+1) General information
+======================
 
-Please pay close attention to the warning about the bttv module
-options below for the DST card.
+This class of cards has a bt878a chip as the PCI interface.
+The different card drivers require the bttv driver to provide the means
+to access the i2c bus and the gpio pins of the bt8xx chipset.
 
-1) General informations
-=======================
+2) Compilation rules for Kernel >= 2.6.12
+=========================================
 
-These drivers require the bttv driver to provide the means to access
-the i2c bus and the gpio pins of the bt8xx chipset.
+Enable the following options:
 
-Because of this, you need to enable
 "Device drivers" => "Multimedia devices"
-  => "Video For Linux" => "BT848 Video For Linux"
-
-Furthermore you need to enable
+ => "Video For Linux" => "BT848 Video For Linux"
 "Device drivers" => "Multimedia devices" => "Digital Video Broadcasting Devices"
 => "DVB for Linux" "DVB Core Support" "Nebula/Pinnacle PCTV/TwinHan PCI Cards"
+ => "DVB for Linux" "DVB Core Support" "Nebula/Pinnacle PCTV/TwinHan PCI Cards"
 
-2) Loading Modules
-==================
+3) Loading Modules, described by two approaches
+===============================================
 
 In general you need to load the bttv driver, which will handle the gpio and
-i2c communication for us, plus the common dvb-bt8xx device driver.
-The frontends for Nebula (nxt6000), Pinnacle PCTV (cx24110) and
-TwinHan (dst) are loaded automatically by the dvb-bt8xx device driver.
+i2c communication for us, plus the common dvb-bt8xx device driver,
+which is called the backend.
+The frontends for Nebula DigiTV (nxt6000), Pinnacle PCTV Sat (cx24110),
+TwinHan DST + clones (dst and dst-ca) are loaded automatically by the backend.
+For further details about TwinHan DST + clones see /Documentation/dvb/ci.txt.
 
-3a) Nebula / Pinnacle PCTV
---------------------------
+3a) The manual approach
+-----------------------
 
-   $ modprobe bttv (normally bttv is being loaded automatically by kmod)
-   $ modprobe dvb-bt8xx (or just place dvb-bt8xx in /etc/modules for automatic loading)
+Loading modules:
+modprobe bttv
+modprobe dvb-bt8xx
 
+Unloading modules:
+modprobe -r dvb-bt8xx
+modprobe -r bttv
 
-3b) TwinHan and Clones
+3b) The automatic approach
 --------------------------
 
-   $ modprobe bttv i2c_hw=1 card=0x71
-   $ modprobe dvb-bt8xx
-   $ modprobe dst
-
-The value 0x71 will override the PCI type detection for dvb-bt8xx,
-which is necessary for TwinHan cards.
-
-If you're having an older card (blue color circuit) and card=0x71 locks
-your machine, try using 0x68, too. If that does not work, ask on the
-mailing list.
-
-The DST module takes a couple of useful parameters:
+If not already done by installation, place a line either in
+/etc/modules.conf or in /etc/modprobe.conf containing this text:
+alias char-major-81    bttv
 
-a. verbose takes values 0 to 5. These values control the verbosity level.
-b. debug takes values 0 and 1. You can either disable or enable debugging.
-c. dst_addons takes values 0 and 0x20:
-- A value of 0 means it is a FTA card.
-- A value of 0x20 means it has a Conditional Access slot.
+Then place a line in /etc/modules containing this text:
+dvb-bt8xx
 
-The autodetected values are determined by the "response string"
-of the card, which you can see in your logs:
-e.g.: dst_get_device_id: Recognize [DSTMCI]
+Reboot your system and have fun!
 
 --
 Authors: Richard Walker, Jamie Honan, Michael Hunold, Manu Abraham, Uwe Bugla
index 1d227ee3792a1f704c7b505486e50985cf7fd8b5..12dde43fe6577a2b7d58e2b751438cf33833d379 100644 (file)
@@ -119,3 +119,19 @@ Why:       Match the other drivers' name for the same function, duplicate names
        will be available until removal of old names.
 Who:   Grant Coady <gcoady@gmail.com>
 
+---------------------------
+
+What:  PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl])
+When:  November 2005
+Files: drivers/pcmcia/: pcmcia_ioctl.c
+Why:   With the 16-bit PCMCIA subsystem now behaving (almost) like a
+       normal hotpluggable bus, and with it using the default kernel
+       infrastructure (hotplug, driver core, sysfs) keeping the PCMCIA
+       control ioctl needed by cardmgr and cardctl from pcmcia-cs is
+       unnecessary, and makes further cleanups and integration of the
+       PCMCIA subsystem into the Linux kernel device driver model more
+       difficult. The features provided by cardmgr and cardctl are either
+       handled by the kernel itself now or are available in the new
+       pcmciautils package available at
+       http://kernel.org/pub/linux/utils/kernel/pcmcia/
+Who:   Dominik Brodowski <linux@brodo.de>
diff --git a/Documentation/infiniband/user_verbs.txt b/Documentation/infiniband/user_verbs.txt
new file mode 100644 (file)
index 0000000..f847501
--- /dev/null
@@ -0,0 +1,69 @@
+USERSPACE VERBS ACCESS
+
+  The ib_uverbs module, built by enabling CONFIG_INFINIBAND_USER_VERBS,
+  enables direct userspace access to IB hardware via "verbs," as
+  described in chapter 11 of the InfiniBand Architecture Specification.
+
+  To use the verbs, the libibverbs library, available from
+  <http://openib.org/>, is required.  libibverbs contains a
+  device-independent API for using the ib_uverbs interface.
+  libibverbs also requires appropriate device-dependent kernel and
+  userspace driver for your InfiniBand hardware.  For example, to use
+  a Mellanox HCA, you will need the ib_mthca kernel module and the
+  libmthca userspace driver be installed.
+
+User-kernel communication
+
+  Userspace communicates with the kernel for slow path, resource
+  management operations via the /dev/infiniband/uverbsN character
+  devices.  Fast path operations are typically performed by writing
+  directly to hardware registers mmap()ed into userspace, with no
+  system call or context switch into the kernel.
+
+  Commands are sent to the kernel via write()s on these device files.
+  The ABI is defined in drivers/infiniband/include/ib_user_verbs.h.
+  The structs for commands that require a response from the kernel
+  contain a 64-bit field used to pass a pointer to an output buffer.
+  Status is returned to userspace as the return value of the write()
+  system call.
+
+Resource management
+
+  Since creation and destruction of all IB resources is done by
+  commands passed through a file descriptor, the kernel can keep track
+  of which resources are attached to a given userspace context.  The
+  ib_uverbs module maintains idr tables that are used to translate
+  between kernel pointers and opaque userspace handles, so that kernel
+  pointers are never exposed to userspace and userspace cannot trick
+  the kernel into following a bogus pointer.
+
+  This also allows the kernel to clean up when a process exits and
+  prevent one process from touching another process's resources.
+
+Memory pinning
+
+  Direct userspace I/O requires that memory regions that are potential
+  I/O targets be kept resident at the same physical address.  The
+  ib_uverbs module manages pinning and unpinning memory regions via
+  get_user_pages() and put_page() calls.  It also accounts for the
+  amount of memory pinned in the process's locked_vm, and checks that
+  unprivileged processes do not exceed their RLIMIT_MEMLOCK limit.
+
+  Pages that are pinned multiple times are counted each time they are
+  pinned, so the value of locked_vm may be an overestimate of the
+  number of pages pinned by a process.
+
+/dev files
+
+  To create the appropriate character device files automatically with
+  udev, a rule like
+
+    KERNEL="uverbs*", NAME="infiniband/%k"
+
+  can be used.  This will create device nodes named
+
+    /dev/infiniband/uverbs0
+
+  and so on.  Since the InfiniBand userspace verbs should be safe for
+  use by non-privileged processes, it may be useful to add an
+  appropriate MODE or GROUP to the udev rule.
index 881a37e3eeb0a8cd36194453c3c728c9e3720fc1..7a4a5036d123515d0aced385ab21b427a3de3089 100644 (file)
@@ -117,6 +117,7 @@ IBM Thinkpad X40 Type 2371-7JG  s3_bios,s3_mode (4)
 Medion MD4220                  ??? (*)
 Samsung P35                    vbetool needed (6)
 Sharp PC-AR10 (ATI rage)       none (1)
+Sony Vaio PCG-C1VRX/K          s3_bios (2)
 Sony Vaio PCG-F403             ??? (*)
 Sony Vaio PCG-N505SN           ??? (*)
 Sony Vaio vgn-s260             X or boot-radeon can init it (5)
index 302b319600085c61ef5ea756acb7c6c49f58cd63..37fb1e2ec6873fae46815c3afa9a7a4ef70af8b9 100644 (file)
@@ -370,6 +370,10 @@ W: http://www.thekelleys.org.uk/atmel
 W:     http://atmelwlandriver.sourceforge.net/
 S:     Maintained
 
+AUDIT SUBSYSTEM
+L:     linux-audit@redhat.com (subscribers-only)
+S:     Maintained
+
 AX.25 NETWORK LAYER
 P:     Ralf Baechle
 M:     ralf@linux-mips.org
@@ -1803,8 +1807,9 @@ M:        greg@kroah.com
 S:     Maintained
 
 PCMCIA SUBSYSTEM
+P:     Linux PCMCIA Team
 L:     http://lists.infradead.org/mailman/listinfo/linux-pcmcia
-S:     Unmaintained
+S:     Maintained
 
 PCNET32 NETWORK DRIVER
 P:     Thomas Bogendörfer
index 278d50992c71642a09c04ef2475f2a63585d62a9..9cf07e7b9f88dc43da8c06dde1b949f50b479aac 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -792,6 +792,9 @@ export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
        $(Q)$(MAKE) $(build)=$(@D) $@
 %.o: %.c scripts FORCE
        $(Q)$(MAKE) $(build)=$(@D) $@
+%.ko: scripts FORCE
+       $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) $(build)=$(@D) $(@:.ko=.o)
+       $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
 %/:      scripts prepare FORCE
        $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) $(build)=$(@D)
 %.lst: %.c scripts FORCE
@@ -1033,6 +1036,7 @@ help:
        @echo  '  modules_install - Install all modules'
        @echo  '  dir/            - Build all files in dir and below'
        @echo  '  dir/file.[ois]  - Build specified target only'
+       @echo  '  dir/file.ko     - Build module including final link'
        @echo  '  rpm             - Build a kernel as an RPM package'
        @echo  '  tags/TAGS       - Generate tags file for editors'
        @echo  '  cscope          - Generate cscope index'
@@ -1149,7 +1153,7 @@ endif # KBUILD_EXTMOD
 #(which is the most common case IMHO) to avoid unneeded clutter in the big tags file.
 #Adding $(srctree) adds about 20M on i386 to the size of the output file!
 
-ifeq ($(KBUILD_OUTPUT),)
+ifeq ($(src),$(obj))
 __srctree =
 else
 __srctree = $(srctree)/
diff --git a/arch/frv/defconfig b/arch/frv/defconfig
new file mode 100644 (file)
index 0000000..b6e4ca5
--- /dev/null
@@ -0,0 +1,627 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11.8
+# Fri May 13 17:16:03 2005
+#
+CONFIG_FRV=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_GENERIC_CALIBRATE_DELAY is not set
+# CONFIG_GENERIC_HARDIRQS is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_KOBJECT_UEVENT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Fujitsu FR-V system setup
+#
+CONFIG_MMU=y
+CONFIG_FRV_OUTOFLINE_ATOMIC_OPS=y
+CONFIG_HIGHMEM=y
+CONFIG_HIGHPTE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_FRV_DEFL_CACHE_WBACK is not set
+# CONFIG_FRV_DEFL_CACHE_WBEHIND is not set
+CONFIG_FRV_DEFL_CACHE_WTHRU=y
+# CONFIG_FRV_DEFL_CACHE_DISABLED is not set
+
+#
+# CPU core support
+#
+CONFIG_CPU_FR451=y
+CONFIG_CPU_FR451_COMPILE=y
+CONFIG_FRV_L1_CACHE_SHIFT=5
+CONFIG_MB93091_VDK=y
+# CONFIG_MB93093_PDK is not set
+CONFIG_MB93090_MB00=y
+# CONFIG_MB93091_NO_MB is not set
+# CONFIG_GPREL_DATA_8 is not set
+CONFIG_GPREL_DATA_4=y
+# CONFIG_GPREL_DATA_NONE is not set
+CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Executable formats
+#
+# CONFIG_BINFMT_ELF is not set
+CONFIG_BINFMT_ELF_FDPIC=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+# CONFIG_FORK_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_KGDBOE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+CONFIG_NE2K_PCI=y
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_MULTIPORT is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISER4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_EARLY_PRINTK is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_GDBSTUB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
index 2203a9d2021251a59776109064d10d558b898574..4553ffd94b1f9f2a645e75ba6982e80c40543cd0 100644 (file)
@@ -435,6 +435,11 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c)
        if (c == &boot_cpu_data)
                sysenter_setup();
        enable_sep_cpu();
+
+       if (c == &boot_cpu_data)
+               mtrr_bp_init();
+       else
+               mtrr_ap_init();
 }
 
 #ifdef CONFIG_X86_HT
index 96a75d0458350c67a4dc1f57d4414a5ffe227790..a2c33c1a46c5c9a620c3d33c5372ead800120a44 100644 (file)
@@ -25,7 +25,7 @@ extern int trap_init_f00f_bug(void);
 /*
  * Alignment at which movsl is preferred for bulk memory copies.
  */
-struct movsl_mask movsl_mask;
+struct movsl_mask movsl_mask __read_mostly;
 #endif
 
 void __devinit early_intel_workaround(struct cpuinfo_x86 *c)
index 64d91f73a0a46210db764b885de72fe5d65378c9..169ac8e0db689e069cc5b02b044458c1142468b7 100644 (file)
@@ -67,13 +67,6 @@ void __init get_mtrr_state(void)
        mtrr_state.enabled = (lo & 0xc00) >> 10;
 }
 
-/*  Free resources associated with a struct mtrr_state  */
-void __init finalize_mtrr_state(void)
-{
-       kfree(mtrr_state.var_ranges);
-       mtrr_state.var_ranges = NULL;
-}
-
 /*  Some BIOS's are fucked and don't set all MTRRs the same!  */
 void __init mtrr_state_warn(void)
 {
@@ -334,6 +327,9 @@ static void generic_set_mtrr(unsigned int reg, unsigned long base,
 */
 {
        unsigned long flags;
+       struct mtrr_var_range *vr;
+
+       vr = &mtrr_state.var_ranges[reg];
 
        local_irq_save(flags);
        prepare_set();
@@ -342,11 +338,15 @@ static void generic_set_mtrr(unsigned int reg, unsigned long base,
                /* The invalid bit is kept in the mask, so we simply clear the
                   relevant mask register to disable a range. */
                mtrr_wrmsr(MTRRphysMask_MSR(reg), 0, 0);
+               memset(vr, 0, sizeof(struct mtrr_var_range));
        } else {
-               mtrr_wrmsr(MTRRphysBase_MSR(reg), base << PAGE_SHIFT | type,
-                     (base & size_and_mask) >> (32 - PAGE_SHIFT));
-               mtrr_wrmsr(MTRRphysMask_MSR(reg), -size << PAGE_SHIFT | 0x800,
-                     (-size & size_and_mask) >> (32 - PAGE_SHIFT));
+               vr->base_lo = base << PAGE_SHIFT | type;
+               vr->base_hi = (base & size_and_mask) >> (32 - PAGE_SHIFT);
+               vr->mask_lo = -size << PAGE_SHIFT | 0x800;
+               vr->mask_hi = (-size & size_and_mask) >> (32 - PAGE_SHIFT);
+
+               mtrr_wrmsr(MTRRphysBase_MSR(reg), vr->base_lo, vr->base_hi);
+               mtrr_wrmsr(MTRRphysMask_MSR(reg), vr->mask_lo, vr->mask_hi);
        }
 
        post_set();
index d66b09e0c820e149f5f94d94078b943fb83b09c4..764cac64e21191310d198e3bd590564e6939d76f 100644 (file)
@@ -332,6 +332,8 @@ int mtrr_add_page(unsigned long base, unsigned long size,
 
        error = -EINVAL;
 
+       /* No CPU hotplug when we change MTRR entries */
+       lock_cpu_hotplug();
        /*  Search for existing MTRR  */
        down(&main_lock);
        for (i = 0; i < num_var_ranges; ++i) {
@@ -372,6 +374,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
        error = i;
  out:
        up(&main_lock);
+       unlock_cpu_hotplug();
        return error;
 }
 
@@ -461,6 +464,8 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
                return -ENXIO;
 
        max = num_var_ranges;
+       /* No CPU hotplug when we change MTRR entries */
+       lock_cpu_hotplug();
        down(&main_lock);
        if (reg < 0) {
                /*  Search for existing MTRR  */
@@ -501,6 +506,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
        error = reg;
  out:
        up(&main_lock);
+       unlock_cpu_hotplug();
        return error;
 }
 /**
@@ -544,21 +550,9 @@ static void __init init_ifs(void)
        centaur_init_mtrr();
 }
 
-static void __init init_other_cpus(void)
-{
-       if (use_intel())
-               get_mtrr_state();
-
-       /* bring up the other processors */
-       set_mtrr(~0U,0,0,0);
-
-       if (use_intel()) {
-               finalize_mtrr_state();
-               mtrr_state_warn();
-       }
-}
-
-
+/* The suspend/resume methods are only for CPU without MTRR. CPU using generic
+ * MTRR driver doesn't require this
+ */
 struct mtrr_value {
        mtrr_type       ltype;
        unsigned long   lbase;
@@ -611,13 +605,13 @@ static struct sysdev_driver mtrr_sysdev_driver = {
 
 
 /**
- * mtrr_init - initialize mtrrs on the boot CPU
+ * mtrr_bp_init - initialize mtrrs on the boot CPU
  *
  * This needs to be called early; before any of the other CPUs are 
  * initialized (i.e. before smp_init()).
  * 
  */
-static int __init mtrr_init(void)
+void __init mtrr_bp_init(void)
 {
        init_ifs();
 
@@ -674,12 +668,48 @@ static int __init mtrr_init(void)
        if (mtrr_if) {
                set_num_var_ranges();
                init_table();
-               init_other_cpus();
-
-               return sysdev_driver_register(&cpu_sysdev_class,
-                                             &mtrr_sysdev_driver);
+               if (use_intel())
+                       get_mtrr_state();
        }
-       return -ENXIO;
 }
 
-subsys_initcall(mtrr_init);
+void mtrr_ap_init(void)
+{
+       unsigned long flags;
+
+       if (!mtrr_if || !use_intel())
+               return;
+       /*
+        * Ideally we should hold main_lock here to avoid mtrr entries changed,
+        * but this routine will be called in cpu boot time, holding the lock
+        * breaks it. This routine is called in two cases: 1.very earily time
+        * of software resume, when there absolutely isn't mtrr entry changes;
+        * 2.cpu hotadd time. We let mtrr_add/del_page hold cpuhotplug lock to
+        * prevent mtrr entry changes
+        */
+       local_irq_save(flags);
+
+       mtrr_if->set_all();
+
+       local_irq_restore(flags);
+}
+
+static int __init mtrr_init_finialize(void)
+{
+       if (!mtrr_if)
+               return 0;
+       if (use_intel())
+               mtrr_state_warn();
+       else {
+               /* The CPUs haven't MTRR and seemes not support SMP. They have
+                * specific drivers, we use a tricky method to support
+                * suspend/resume for them.
+                * TBD: is there any system with such CPU which supports
+                * suspend/resume?  if no, we should remove the code.
+                */
+               sysdev_driver_register(&cpu_sysdev_class,
+                       &mtrr_sysdev_driver);
+       }
+       return 0;
+}
+subsys_initcall(mtrr_init_finialize);
index de1351245599e5e5a62ddeba47674fc84f6e1283..99c9f2682041fad9faafa11a6b63d87b319df9f4 100644 (file)
@@ -91,7 +91,6 @@ extern struct mtrr_ops * mtrr_if;
 
 extern unsigned int num_var_ranges;
 
-void finalize_mtrr_state(void);
 void mtrr_state_warn(void);
 char *mtrr_attrib_to_str(int x);
 void mtrr_wrmsr(unsigned, unsigned, unsigned);
index d66bf489a2e90782044a09e2562fb84d06d893a0..8ac8e9fd5614fa10237dc58fa6620d52cff8e5e3 100644 (file)
@@ -68,21 +68,21 @@ EXPORT_SYMBOL(smp_num_siblings);
 #endif
 
 /* Package ID of each logical CPU */
-int phys_proc_id[NR_CPUS] = {[0 ... NR_CPUS-1] = BAD_APICID};
+int phys_proc_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID};
 EXPORT_SYMBOL(phys_proc_id);
 
 /* Core ID of each logical CPU */
-int cpu_core_id[NR_CPUS] = {[0 ... NR_CPUS-1] = BAD_APICID};
+int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID};
 EXPORT_SYMBOL(cpu_core_id);
 
-cpumask_t cpu_sibling_map[NR_CPUS];
+cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
 EXPORT_SYMBOL(cpu_sibling_map);
 
-cpumask_t cpu_core_map[NR_CPUS];
+cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
 EXPORT_SYMBOL(cpu_core_map);
 
 /* bitmap of online cpus */
-cpumask_t cpu_online_map;
+cpumask_t cpu_online_map __read_mostly;
 EXPORT_SYMBOL(cpu_online_map);
 
 cpumask_t cpu_callin_map;
@@ -100,7 +100,7 @@ static int __devinitdata tsc_sync_disabled;
 struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
 EXPORT_SYMBOL(cpu_data);
 
-u8 x86_cpu_to_apicid[NR_CPUS] =
+u8 x86_cpu_to_apicid[NR_CPUS] __read_mostly =
                        { [0 ... NR_CPUS-1] = 0xff };
 EXPORT_SYMBOL(x86_cpu_to_apicid);
 
@@ -550,10 +550,10 @@ extern struct {
 #ifdef CONFIG_NUMA
 
 /* which logical CPUs are on which nodes */
-cpumask_t node_2_cpu_mask[MAX_NUMNODES] =
+cpumask_t node_2_cpu_mask[MAX_NUMNODES] __read_mostly =
                                { [0 ... MAX_NUMNODES-1] = CPU_MASK_NONE };
 /* which node each logical CPU is on */
-int cpu_2_node[NR_CPUS] = { [0 ... NR_CPUS-1] = 0 };
+int cpu_2_node[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = 0 };
 EXPORT_SYMBOL(cpu_2_node);
 
 /* set up a mapping between cpu and node. */
@@ -581,7 +581,7 @@ static inline void unmap_cpu_to_node(int cpu)
 
 #endif /* CONFIG_NUMA */
 
-u8 cpu_2_logical_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
 
 static void map_cpu_to_logical_apicid(void)
 {
index 2854c357377f18c8d98447e296dd63e3d877fb21..0ee9dee8af06280c85ba403208cacc237da08b43 100644 (file)
@@ -91,7 +91,7 @@ EXPORT_SYMBOL(rtc_lock);
 DEFINE_SPINLOCK(i8253_lock);
 EXPORT_SYMBOL(i8253_lock);
 
-struct timer_opts *cur_timer = &timer_none;
+struct timer_opts *cur_timer __read_mostly = &timer_none;
 
 /*
  * This is a special lock that is owned by the CPU and holds the index
index d766e0963ac13599db7707368ba833b331bcafeb..ef8dac5dd33b103bbc5f8c6f5c9b7ce52bfe4582 100644 (file)
@@ -18,7 +18,7 @@
 #include "mach_timer.h"
 #include <asm/hpet.h>
 
-static unsigned long hpet_usec_quotient;       /* convert hpet clks to usec */
+static unsigned long __read_mostly hpet_usec_quotient; /* convert hpet clks to usec */
 static unsigned long tsc_hpet_quotient;                /* convert tsc to hpet clks */
 static unsigned long hpet_last;        /* hpet counter value at last tick*/
 static unsigned long last_tsc_low;     /* lsb 32 bits of Time Stamp Counter */
@@ -180,7 +180,7 @@ static int __init init_hpet(char* override)
 /************************************************************/
 
 /* tsc timer_opts struct */
-static struct timer_opts timer_hpet = {
+static struct timer_opts timer_hpet __read_mostly = {
        .name =                 "hpet",
        .mark_offset =          mark_offset_hpet,
        .get_offset =           get_offset_hpet,
index 7e01a528a83a168f86214907103d7bbe1f2e964d..761972f8cb6c86dadf1ed297d2ea12a6ae234977 100644 (file)
@@ -57,6 +57,9 @@ SECTIONS
        *(.data.cacheline_aligned)
   }
 
+  /* rarely changed data like cpu maps */
+  . = ALIGN(32);
+  .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { *(.data.read_mostly) }
   _edata = .;                  /* End of data section */
 
   . = ALIGN(THREAD_SIZE);      /* init_task */
index 6b25afc933b605b0f515372d900cdc272ffc2e71..f379b8d675585eac6e6884887fc1a1a9b5230624 100644 (file)
@@ -228,7 +228,8 @@ EXPORT_SYMBOL(ioremap_nocache);
 void iounmap(volatile void __iomem *addr)
 {
        struct vm_struct *p;
-       if ((void __force *) addr <= high_memory) 
+
+       if ((void __force *)addr <= high_memory)
                return;
 
        /*
@@ -241,9 +242,10 @@ void iounmap(volatile void __iomem *addr)
                return;
 
        write_lock(&vmlist_lock);
-       p = __remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
+       p = __remove_vm_area((void *)(PAGE_MASK & (unsigned long __force)addr));
        if (!p) { 
                printk(KERN_WARNING "iounmap: bad address %p\n", addr);
+               dump_stack();
                goto out_unlock;
        }
 
index 0e6b45b612514669d9dbaf8df092b56a4b0d6fb9..c547c1af6fa1a86ea8e25f4dd62332c3f3302faa 100644 (file)
@@ -137,6 +137,7 @@ void __restore_processor_state(struct saved_context *ctxt)
 
        fix_processor_context();
        do_fpu_end();
+       mtrr_ap_init();
 }
 
 void restore_processor_state(void)
index b2e2f6509eb0c4510d13fd5a31928fe598f3b341..e1fb68ddec26328f5ea7f19ce099628fea81b664 100644 (file)
@@ -17,6 +17,7 @@ obj-$(CONFIG_IA64_PALINFO)    += palinfo.o
 obj-$(CONFIG_IOSAPIC)          += iosapic.o
 obj-$(CONFIG_MODULES)          += module.o
 obj-$(CONFIG_SMP)              += smp.o smpboot.o domain.o
+obj-$(CONFIG_NUMA)             += numa.o
 obj-$(CONFIG_PERFMON)          += perfmon_default_smpl.o
 obj-$(CONFIG_IA64_CYCLONE)     += cyclone.o
 obj-$(CONFIG_IA64_MCA_RECOVERY)        += mca_recovery.o
index cda06f88c66eb9ae28c79973f4882deda9545205..542256e98e604fca899160d7f659ce65db11d85e 100644 (file)
@@ -640,8 +640,10 @@ acpi_boot_init (void)
                        if (smp_boot_data.cpu_phys_id[cpu] != hard_smp_processor_id())
                                node_cpuid[i++].phys_id = smp_boot_data.cpu_phys_id[cpu];
        }
-       build_cpu_to_node_map();
 # endif
+#endif
+#ifdef CONFIG_ACPI_NUMA
+       build_cpu_to_node_map();
 #endif
        /* Make boot-up look pretty */
        printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus, total_cpus);
diff --git a/arch/ia64/kernel/numa.c b/arch/ia64/kernel/numa.c
new file mode 100644 (file)
index 0000000..a68ce66
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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
+ *
+ * ia64 kernel NUMA specific stuff
+ *
+ * Copyright (C) 2002 Erich Focht <efocht@ess.nec.de>
+ * Copyright (C) 2004 Silicon Graphics, Inc.
+ *   Jesse Barnes <jbarnes@sgi.com>
+ */
+#include <linux/config.h>
+#include <linux/topology.h>
+#include <linux/module.h>
+#include <asm/processor.h>
+#include <asm/smp.h>
+
+u8 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
+EXPORT_SYMBOL(cpu_to_node_map);
+
+cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
+
+/**
+ * build_cpu_to_node_map - setup cpu to node and node to cpumask arrays
+ *
+ * Build cpu to node mapping and initialize the per node cpu masks using
+ * info from the node_cpuid array handed to us by ACPI.
+ */
+void __init build_cpu_to_node_map(void)
+{
+       int cpu, i, node;
+
+       for(node=0; node < MAX_NUMNODES; node++)
+               cpus_clear(node_to_cpu_mask[node]);
+
+       for(cpu = 0; cpu < NR_CPUS; ++cpu) {
+               node = -1;
+               for (i = 0; i < NR_CPUS; ++i)
+                       if (cpu_physical_id(cpu) == node_cpuid[i].phys_id) {
+                               node = node_cpuid[i].nid;
+                               break;
+                       }
+               cpu_to_node_map[cpu] = (node >= 0) ? node : 0;
+               if (node >= 0)
+                       cpu_set(cpu, node_to_cpu_mask[node]);
+       }
+}
index edd9f07860b227a230ab981d1a8691a68bd01a7a..b8a0a7d257a9b3f427561faadb6d98eaf7b4648f 100644 (file)
@@ -143,6 +143,7 @@ restore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr)
 
                __copy_from_user(current->thread.fph, &sc->sc_fr[32], 96*16);
                psr->mfh = 0;   /* drop signal handler's fph contents... */
+               preempt_disable();
                if (psr->dfh)
                        ia64_drop_fpu(current);
                else {
@@ -150,6 +151,7 @@ restore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr)
                        __ia64_load_fpu(current->thread.fph);
                        ia64_set_local_fpu_owner(current);
                }
+               preempt_enable();
        }
        return err;
 }
index 623b0a54670973039d65b5c4ad38b7488d2314d4..7d72c0d872b312ad4c5e4406dca78cb5e24b616b 100644 (file)
@@ -525,47 +525,6 @@ smp_build_cpu_map (void)
        }
 }
 
-#ifdef CONFIG_NUMA
-
-/* on which node is each logical CPU (one cacheline even for 64 CPUs) */
-u8 cpu_to_node_map[NR_CPUS] __cacheline_aligned;
-EXPORT_SYMBOL(cpu_to_node_map);
-/* which logical CPUs are on which nodes */
-cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned;
-
-/*
- * Build cpu to node mapping and initialize the per node cpu masks.
- */
-void __init
-build_cpu_to_node_map (void)
-{
-       int cpu, i, node;
-
-       for(node=0; node<MAX_NUMNODES; node++)
-               cpus_clear(node_to_cpu_mask[node]);
-       for(cpu = 0; cpu < NR_CPUS; ++cpu) {
-               /*
-                * All Itanium NUMA platforms I know use ACPI, so maybe we
-                * can drop this ifdef completely.                    [EF]
-                */
-#ifdef CONFIG_ACPI_NUMA
-               node = -1;
-               for (i = 0; i < NR_CPUS; ++i)
-                       if (cpu_physical_id(cpu) == node_cpuid[i].phys_id) {
-                               node = node_cpuid[i].nid;
-                               break;
-                       }
-#else
-#              error Fixme: Dunno how to build CPU-to-node map.
-#endif
-               cpu_to_node_map[cpu] = (node >= 0) ? node : 0;
-               if (node >= 0)
-                       cpu_set(cpu, node_to_cpu_mask[node]);
-       }
-}
-
-#endif /* CONFIG_NUMA */
-
 /*
  * Cycle through the APs sending Wakeup IPIs to boot each.
  */
index e7e520d90f038831c1daf4ccd13bc763818498fd..4440c8343fa4303df0dbc658954d9d3cebc1ab8d 100644 (file)
@@ -90,14 +90,16 @@ die (const char *str, struct pt_regs *regs, long err)
                .lock_owner_depth =     0
        };
        static int die_counter;
+       int cpu = get_cpu();
 
-       if (die.lock_owner != smp_processor_id()) {
+       if (die.lock_owner != cpu) {
                console_verbose();
                spin_lock_irq(&die.lock);
-               die.lock_owner = smp_processor_id();
+               die.lock_owner = cpu;
                die.lock_owner_depth = 0;
                bust_spinlocks(1);
        }
+       put_cpu();
 
        if (++die.lock_owner_depth < 3) {
                printk("%s[%d]: %s %ld [%d]\n",
index f3fd528ead3b6ceb3d9a22e62e75c06b59707c43..b5c90e54819542691785b8cc64e250a39d93f260 100644 (file)
@@ -44,150 +44,7 @@ struct early_node_data {
 };
 
 static struct early_node_data mem_data[MAX_NUMNODES] __initdata;
-
-/**
- * reassign_cpu_only_nodes - called from find_memory to move CPU-only nodes to a memory node
- *
- * This function will move nodes with only CPUs (no memory)
- * to a node with memory which is at the minimum numa_slit distance.
- * Any reassigments will result in the compression of the nodes
- * and renumbering the nid values where appropriate.
- * The static declarations below are to avoid large stack size which
- * makes the code not re-entrant.
- */
-static void __init reassign_cpu_only_nodes(void)
-{
-       struct node_memblk_s *p;
-       int i, j, k, nnode, nid, cpu, cpunid, pxm;
-       u8 cslit, slit;
-       static DECLARE_BITMAP(nodes_with_mem, MAX_NUMNODES) __initdata;
-       static u8 numa_slit_fix[MAX_NUMNODES * MAX_NUMNODES] __initdata;
-       static int node_flip[MAX_NUMNODES] __initdata;
-       static int old_nid_map[NR_CPUS] __initdata;
-
-       for (nnode = 0, p = &node_memblk[0]; p < &node_memblk[num_node_memblks]; p++)
-               if (!test_bit(p->nid, (void *) nodes_with_mem)) {
-                       set_bit(p->nid, (void *) nodes_with_mem);
-                       nnode++;
-               }
-
-       /*
-        * All nids with memory.
-        */
-       if (nnode == num_online_nodes())
-               return;
-
-       /*
-        * Change nids and attempt to migrate CPU-only nodes
-        * to the best numa_slit (closest neighbor) possible.
-        * For reassigned CPU nodes a nid can't be arrived at
-        * until after this loop because the target nid's new
-        * identity might not have been established yet. So
-        * new nid values are fabricated above num_online_nodes() and
-        * mapped back later to their true value.
-        */
-       /* MCD - This code is a bit complicated, but may be unnecessary now.
-        * We can now handle much more interesting node-numbering.
-        * The old requirement that 0 <= nid <= numnodes <= MAX_NUMNODES
-        * and that there be no holes in the numbering 0..numnodes
-        * has become simply 0 <= nid <= MAX_NUMNODES.
-        */
-       nid = 0;
-       for_each_online_node(i)  {
-               if (test_bit(i, (void *) nodes_with_mem)) {
-                       /*
-                        * Save original nid value for numa_slit
-                        * fixup and node_cpuid reassignments.
-                        */
-                       node_flip[nid] = i;
-
-                       if (i == nid) {
-                               nid++;
-                               continue;
-                       }
-
-                       for (p = &node_memblk[0]; p < &node_memblk[num_node_memblks]; p++)
-                               if (p->nid == i)
-                                       p->nid = nid;
-
-                       cpunid = nid;
-                       nid++;
-               } else
-                       cpunid = MAX_NUMNODES;
-
-               for (cpu = 0; cpu < NR_CPUS; cpu++)
-                       if (node_cpuid[cpu].nid == i) {
-                               /*
-                                * For nodes not being reassigned just
-                                * fix the cpu's nid and reverse pxm map
-                                */
-                               if (cpunid < MAX_NUMNODES) {
-                                       pxm = nid_to_pxm_map[i];
-                                       pxm_to_nid_map[pxm] =
-                                                 node_cpuid[cpu].nid = cpunid;
-                                       continue;
-                               }
-
-                               /*
-                                * For nodes being reassigned, find best node by
-                                * numa_slit information and then make a temporary
-                                * nid value based on current nid and num_online_nodes().
-                                */
-                               slit = 0xff;
-                               k = 2*num_online_nodes();
-                               for_each_online_node(j) {
-                                       if (i == j)
-                                               continue;
-                                       else if (test_bit(j, (void *) nodes_with_mem)) {
-                                               cslit = numa_slit[i * num_online_nodes() + j];
-                                               if (cslit < slit) {
-                                                       k = num_online_nodes() + j;
-                                                       slit = cslit;
-                                               }
-                                       }
-                               }
-
-                               /* save old nid map so we can update the pxm */
-                               old_nid_map[cpu] = node_cpuid[cpu].nid;
-                               node_cpuid[cpu].nid = k;
-                       }
-       }
-
-       /*
-        * Fixup temporary nid values for CPU-only nodes.
-        */
-       for (cpu = 0; cpu < NR_CPUS; cpu++)
-               if (node_cpuid[cpu].nid == (2*num_online_nodes())) {
-                       pxm = nid_to_pxm_map[old_nid_map[cpu]];
-                       pxm_to_nid_map[pxm] = node_cpuid[cpu].nid = nnode - 1;
-               } else {
-                       for (i = 0; i < nnode; i++) {
-                               if (node_flip[i] != (node_cpuid[cpu].nid - num_online_nodes()))
-                                       continue;
-
-                               pxm = nid_to_pxm_map[old_nid_map[cpu]];
-                               pxm_to_nid_map[pxm] = node_cpuid[cpu].nid = i;
-                               break;
-                       }
-               }
-
-       /*
-        * Fix numa_slit by compressing from larger
-        * nid array to reduced nid array.
-        */
-       for (i = 0; i < nnode; i++)
-               for (j = 0; j < nnode; j++)
-                       numa_slit_fix[i * nnode + j] =
-                               numa_slit[node_flip[i] * num_online_nodes() + node_flip[j]];
-
-       memcpy(numa_slit, numa_slit_fix, sizeof (numa_slit));
-
-       nodes_clear(node_online_map);
-       for (i = 0; i < nnode; i++)
-               node_set_online(i);
-
-       return;
-}
+static nodemask_t memory_less_mask __initdata;
 
 /*
  * To prevent cache aliasing effects, align per-node structures so that they
@@ -233,44 +90,101 @@ static int __init build_node_maps(unsigned long start, unsigned long len,
 }
 
 /**
- * early_nr_phys_cpus_node - return number of physical cpus on a given node
+ * early_nr_cpus_node - return number of cpus on a given node
  * @node: node to check
  *
- * Count the number of physical cpus on @node.  These are cpus that actually
- * exist.  We can't use nr_cpus_node() yet because
+ * Count the number of cpus on @node.  We can't use nr_cpus_node() yet because
  * acpi_boot_init() (which builds the node_to_cpu_mask array) hasn't been
- * called yet.
+ * called yet.  Note that node 0 will also count all non-existent cpus.
  */
-static int early_nr_phys_cpus_node(int node)
+static int __init early_nr_cpus_node(int node)
 {
        int cpu, n = 0;
 
        for (cpu = 0; cpu < NR_CPUS; cpu++)
                if (node == node_cpuid[cpu].nid)
-                       if ((cpu == 0) || node_cpuid[cpu].phys_id)
-                               n++;
+                       n++;
 
        return n;
 }
 
+/**
+ * compute_pernodesize - compute size of pernode data
+ * @node: the node id.
+ */
+static unsigned long __init compute_pernodesize(int node)
+{
+       unsigned long pernodesize = 0, cpus;
+
+       cpus = early_nr_cpus_node(node);
+       pernodesize += PERCPU_PAGE_SIZE * cpus;
+       pernodesize += node * L1_CACHE_BYTES;
+       pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t));
+       pernodesize += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
+       pernodesize = PAGE_ALIGN(pernodesize);
+       return pernodesize;
+}
 
 /**
- * early_nr_cpus_node - return number of cpus on a given node
- * @node: node to check
+ * per_cpu_node_setup - setup per-cpu areas on each node
+ * @cpu_data: per-cpu area on this node
+ * @node: node to setup
  *
- * Count the number of cpus on @node.  We can't use nr_cpus_node() yet because
- * acpi_boot_init() (which builds the node_to_cpu_mask array) hasn't been
- * called yet.  Note that node 0 will also count all non-existent cpus.
+ * Copy the static per-cpu data into the region we just set aside and then
+ * setup __per_cpu_offset for each CPU on this node.  Return a pointer to
+ * the end of the area.
  */
-static int early_nr_cpus_node(int node)
+static void *per_cpu_node_setup(void *cpu_data, int node)
 {
-       int cpu, n = 0;
+#ifdef CONFIG_SMP
+       int cpu;
 
-       for (cpu = 0; cpu < NR_CPUS; cpu++)
-               if (node == node_cpuid[cpu].nid)
-                       n++;
+       for (cpu = 0; cpu < NR_CPUS; cpu++) {
+               if (node == node_cpuid[cpu].nid) {
+                       memcpy(__va(cpu_data), __phys_per_cpu_start,
+                              __per_cpu_end - __per_cpu_start);
+                       __per_cpu_offset[cpu] = (char*)__va(cpu_data) -
+                               __per_cpu_start;
+                       cpu_data += PERCPU_PAGE_SIZE;
+               }
+       }
+#endif
+       return cpu_data;
+}
 
-       return n;
+/**
+ * fill_pernode - initialize pernode data.
+ * @node: the node id.
+ * @pernode: physical address of pernode data
+ * @pernodesize: size of the pernode data
+ */
+static void __init fill_pernode(int node, unsigned long pernode,
+       unsigned long pernodesize)
+{
+       void *cpu_data;
+       int cpus = early_nr_cpus_node(node);
+       struct bootmem_data *bdp = &mem_data[node].bootmem_data;
+
+       mem_data[node].pernode_addr = pernode;
+       mem_data[node].pernode_size = pernodesize;
+       memset(__va(pernode), 0, pernodesize);
+
+       cpu_data = (void *)pernode;
+       pernode += PERCPU_PAGE_SIZE * cpus;
+       pernode += node * L1_CACHE_BYTES;
+
+       mem_data[node].pgdat = __va(pernode);
+       pernode += L1_CACHE_ALIGN(sizeof(pg_data_t));
+
+       mem_data[node].node_data = __va(pernode);
+       pernode += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
+
+       mem_data[node].pgdat->bdata = bdp;
+       pernode += L1_CACHE_ALIGN(sizeof(pg_data_t));
+
+       cpu_data = per_cpu_node_setup(cpu_data, node);
+
+       return;
 }
 
 /**
@@ -304,9 +218,8 @@ static int early_nr_cpus_node(int node)
 static int __init find_pernode_space(unsigned long start, unsigned long len,
                                     int node)
 {
-       unsigned long epfn, cpu, cpus, phys_cpus;
+       unsigned long epfn;
        unsigned long pernodesize = 0, pernode, pages, mapsize;
-       void *cpu_data;
        struct bootmem_data *bdp = &mem_data[node].bootmem_data;
 
        epfn = (start + len) >> PAGE_SHIFT;
@@ -329,49 +242,12 @@ static int __init find_pernode_space(unsigned long start, unsigned long len,
         * Calculate total size needed, incl. what's necessary
         * for good alignment and alias prevention.
         */
-       cpus = early_nr_cpus_node(node);
-       phys_cpus = early_nr_phys_cpus_node(node);
-       pernodesize += PERCPU_PAGE_SIZE * cpus;
-       pernodesize += node * L1_CACHE_BYTES;
-       pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t));
-       pernodesize += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
-       pernodesize = PAGE_ALIGN(pernodesize);
+       pernodesize = compute_pernodesize(node);
        pernode = NODEDATA_ALIGN(start, node);
 
        /* Is this range big enough for what we want to store here? */
-       if (start + len > (pernode + pernodesize + mapsize)) {
-               mem_data[node].pernode_addr = pernode;
-               mem_data[node].pernode_size = pernodesize;
-               memset(__va(pernode), 0, pernodesize);
-
-               cpu_data = (void *)pernode;
-               pernode += PERCPU_PAGE_SIZE * cpus;
-               pernode += node * L1_CACHE_BYTES;
-
-               mem_data[node].pgdat = __va(pernode);
-               pernode += L1_CACHE_ALIGN(sizeof(pg_data_t));
-
-               mem_data[node].node_data = __va(pernode);
-               pernode += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
-
-               mem_data[node].pgdat->bdata = bdp;
-               pernode += L1_CACHE_ALIGN(sizeof(pg_data_t));
-
-               /*
-                * Copy the static per-cpu data into the region we
-                * just set aside and then setup __per_cpu_offset
-                * for each CPU on this node.
-                */
-               for (cpu = 0; cpu < NR_CPUS; cpu++) {
-                       if (node == node_cpuid[cpu].nid) {
-                               memcpy(__va(cpu_data), __phys_per_cpu_start,
-                                      __per_cpu_end - __per_cpu_start);
-                               __per_cpu_offset[cpu] = (char*)__va(cpu_data) -
-                                       __per_cpu_start;
-                               cpu_data += PERCPU_PAGE_SIZE;
-                       }
-               }
-       }
+       if (start + len > (pernode + pernodesize + mapsize))
+               fill_pernode(node, pernode, pernodesize);
 
        return 0;
 }
@@ -411,6 +287,9 @@ static void __init reserve_pernode_space(void)
        for_each_online_node(node) {
                pg_data_t *pdp = mem_data[node].pgdat;
 
+               if (node_isset(node, memory_less_mask))
+                       continue;
+
                bdp = pdp->bdata;
 
                /* First the bootmem_map itself */
@@ -436,8 +315,8 @@ static void __init reserve_pernode_space(void)
  */
 static void __init initialize_pernode_data(void)
 {
-       int cpu, node;
        pg_data_t *pgdat_list[MAX_NUMNODES];
+       int cpu, node;
 
        for_each_online_node(node)
                pgdat_list[node] = mem_data[node].pgdat;
@@ -447,12 +326,99 @@ static void __init initialize_pernode_data(void)
                memcpy(mem_data[node].node_data->pg_data_ptrs, pgdat_list,
                       sizeof(pgdat_list));
        }
-
+#ifdef CONFIG_SMP
        /* Set the node_data pointer for each per-cpu struct */
        for (cpu = 0; cpu < NR_CPUS; cpu++) {
                node = node_cpuid[cpu].nid;
                per_cpu(cpu_info, cpu).node_data = mem_data[node].node_data;
        }
+#else
+       {
+               struct cpuinfo_ia64 *cpu0_cpu_info;
+               cpu = 0;
+               node = node_cpuid[cpu].nid;
+               cpu0_cpu_info = (struct cpuinfo_ia64 *)(__phys_per_cpu_start +
+                       ((char *)&per_cpu__cpu_info - __per_cpu_start));
+               cpu0_cpu_info->node_data = mem_data[node].node_data;
+       }
+#endif /* CONFIG_SMP */
+}
+
+/**
+ * memory_less_node_alloc - * attempt to allocate memory on the best NUMA slit
+ *     node but fall back to any other node when __alloc_bootmem_node fails
+ *     for best.
+ * @nid: node id
+ * @pernodesize: size of this node's pernode data
+ * @align: alignment to use for this node's pernode data
+ */
+static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize,
+       unsigned long align)
+{
+       void *ptr = NULL;
+       u8 best = 0xff;
+       int bestnode = -1, node;
+
+       for_each_online_node(node) {
+               if (node_isset(node, memory_less_mask))
+                       continue;
+               else if (node_distance(nid, node) < best) {
+                       best = node_distance(nid, node);
+                       bestnode = node;
+               }
+       }
+
+       ptr = __alloc_bootmem_node(mem_data[bestnode].pgdat,
+               pernodesize, align, __pa(MAX_DMA_ADDRESS));
+
+       if (!ptr)
+               panic("NO memory for memory less node\n");
+       return ptr;
+}
+
+/**
+ * pgdat_insert - insert the pgdat into global pgdat_list
+ * @pgdat: the pgdat for a node.
+ */
+static void __init pgdat_insert(pg_data_t *pgdat)
+{
+       pg_data_t *prev = NULL, *next;
+
+       for_each_pgdat(next)
+               if (pgdat->node_id < next->node_id)
+                       break;
+               else
+                       prev = next;
+
+       if (prev) {
+               prev->pgdat_next = pgdat;
+               pgdat->pgdat_next = next;
+       } else {
+               pgdat->pgdat_next = pgdat_list;
+               pgdat_list = pgdat;
+       }
+
+       return;
+}
+
+/**
+ * memory_less_nodes - allocate and initialize CPU only nodes pernode
+ *     information.
+ */
+static void __init memory_less_nodes(void)
+{
+       unsigned long pernodesize;
+       void *pernode;
+       int node;
+
+       for_each_node_mask(node, memory_less_mask) {
+               pernodesize = compute_pernodesize(node);
+               pernode = memory_less_node_alloc(node, pernodesize,
+                       (node) ? (node * PERCPU_PAGE_SIZE) : (1024*1024));
+               fill_pernode(node, __pa(pernode), pernodesize);
+       }
+
+       return;
 }
 
 /**
@@ -472,16 +438,19 @@ void __init find_memory(void)
                node_set_online(0);
        }
 
+       nodes_or(memory_less_mask, memory_less_mask, node_online_map);
        min_low_pfn = -1;
        max_low_pfn = 0;
 
-       if (num_online_nodes() > 1)
-               reassign_cpu_only_nodes();
-
        /* These actually end up getting called by call_pernode_memory() */
        efi_memmap_walk(filter_rsvd_memory, build_node_maps);
        efi_memmap_walk(filter_rsvd_memory, find_pernode_space);
 
+       for_each_online_node(node)
+               if (mem_data[node].bootmem_data.node_low_pfn) {
+                       node_clear(node, memory_less_mask);
+                       mem_data[node].min_pfn = ~0UL;
+               }
        /*
         * Initialize the boot memory maps in reverse order since that's
         * what the bootmem allocator expects
@@ -492,17 +461,14 @@ void __init find_memory(void)
 
                if (!node_online(node))
                        continue;
+               else if (node_isset(node, memory_less_mask))
+                       continue;
 
                bdp = &mem_data[node].bootmem_data;
                pernode = mem_data[node].pernode_addr;
                pernodesize = mem_data[node].pernode_size;
                map = pernode + pernodesize;
 
-               /* Sanity check... */
-               if (!pernode)
-                       panic("pernode space for node %d "
-                             "could not be allocated!", node);
-
                init_bootmem_node(mem_data[node].pgdat,
                                  map>>PAGE_SHIFT,
                                  bdp->node_boot_start>>PAGE_SHIFT,
@@ -512,6 +478,7 @@ void __init find_memory(void)
        efi_memmap_walk(filter_rsvd_memory, free_node_bootmem);
 
        reserve_pernode_space();
+       memory_less_nodes();
        initialize_pernode_data();
 
        max_pfn = max_low_pfn;
@@ -519,6 +486,7 @@ void __init find_memory(void)
        find_initrd();
 }
 
+#ifdef CONFIG_SMP
 /**
  * per_cpu_init - setup per-cpu variables
  *
@@ -529,15 +497,15 @@ void *per_cpu_init(void)
 {
        int cpu;
 
-       if (smp_processor_id() == 0) {
-               for (cpu = 0; cpu < NR_CPUS; cpu++) {
-                       per_cpu(local_per_cpu_offset, cpu) =
-                               __per_cpu_offset[cpu];
-               }
-       }
+       if (smp_processor_id() != 0)
+               return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
+
+       for (cpu = 0; cpu < NR_CPUS; cpu++)
+               per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
 
        return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
 }
+#endif /* CONFIG_SMP */
 
 /**
  * show_mem - give short summary of memory stats
@@ -680,12 +648,13 @@ void __init paging_init(void)
 
        max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 
-       /* so min() will work in count_node_pages */
-       for_each_online_node(node)
-               mem_data[node].min_pfn = ~0UL;
-
        efi_memmap_walk(filter_rsvd_memory, count_node_pages);
 
+       vmalloc_end -= PAGE_ALIGN(max_low_pfn * sizeof(struct page));
+       vmem_map = (struct page *) vmalloc_end;
+       efi_memmap_walk(create_mem_map_page_table, NULL);
+       printk("Virtual mem_map starts at 0x%p\n", vmem_map);
+
        for_each_online_node(node) {
                memset(zones_size, 0, sizeof(zones_size));
                memset(zholes_size, 0, sizeof(zholes_size));
@@ -719,15 +688,6 @@ void __init paging_init(void)
                                 mem_data[node].num_dma_physpages);
                }
 
-               if (node == 0) {
-                       vmalloc_end -=
-                               PAGE_ALIGN(max_low_pfn * sizeof(struct page));
-                       vmem_map = (struct page *) vmalloc_end;
-
-                       efi_memmap_walk(create_mem_map_page_table, NULL);
-                       printk("Virtual mem_map starts at 0x%p\n", vmem_map);
-               }
-
                pfn_offset = mem_data[node].min_pfn;
 
                NODE_DATA(node)->node_mem_map = vmem_map + pfn_offset;
@@ -735,5 +695,11 @@ void __init paging_init(void)
                                    pfn_offset, zholes_size);
        }
 
+       /*
+        * Make memory less nodes become a member of the known nodes.
+        */
+       for_each_node_mask(node, memory_less_mask)
+               pgdat_insert(mem_data[node].pgdat);
+
        zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
 }
index 4eb2f52b87a16b436007740a56abaf79574d51fa..65f9958db9f03347a2a49c3b69a564c536459529 100644 (file)
@@ -597,7 +597,8 @@ mem_init (void)
        kclist_add(&kcore_kernel, _stext, _end - _stext);
 
        for_each_pgdat(pgdat)
-               totalram_pages += free_all_bootmem_node(pgdat);
+               if (pgdat->bdata->node_bootmem_map)
+                       totalram_pages += free_all_bootmem_node(pgdat);
 
        reserved_pages = 0;
        efi_memmap_walk(count_reserved_pages, &reserved_pages);
diff --git a/arch/ia64/sn/include/pci/pcibr_provider.h b/arch/ia64/sn/include/pci/pcibr_provider.h
deleted file mode 100644 (file)
index 1cd291d..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1992-1997,2000-2004 Silicon Graphics, Inc. All rights reserved.
- */
-#ifndef _ASM_IA64_SN_PCI_PCIBR_PROVIDER_H
-#define _ASM_IA64_SN_PCI_PCIBR_PROVIDER_H
-
-/* Workarounds */
-#define PV907516 (1 << 1) /* TIOCP: Don't write the write buffer flush reg */
-
-#define BUSTYPE_MASK                    0x1
-
-/* Macros given a pcibus structure */
-#define IS_PCIX(ps)     ((ps)->pbi_bridge_mode & BUSTYPE_MASK)
-#define IS_PCI_BRIDGE_ASIC(asic) (asic == PCIIO_ASIC_TYPE_PIC || \
-                asic == PCIIO_ASIC_TYPE_TIOCP)
-#define IS_PIC_SOFT(ps)     (ps->pbi_bridge_type == PCIBR_BRIDGETYPE_PIC)
-
-
-/* 
- * The different PCI Bridge types supported on the SGI Altix platforms
- */
-#define PCIBR_BRIDGETYPE_UNKNOWN       -1
-#define PCIBR_BRIDGETYPE_PIC            2
-#define PCIBR_BRIDGETYPE_TIOCP          3
-
-/*
- * Bridge 64bit Direct Map Attributes
- */
-#define PCI64_ATTR_PREF                 (1ull << 59)
-#define PCI64_ATTR_PREC                 (1ull << 58)
-#define PCI64_ATTR_VIRTUAL              (1ull << 57)
-#define PCI64_ATTR_BAR                  (1ull << 56)
-#define PCI64_ATTR_SWAP                 (1ull << 55)
-#define PCI64_ATTR_VIRTUAL1             (1ull << 54)
-
-#define PCI32_LOCAL_BASE                0
-#define PCI32_MAPPED_BASE               0x40000000
-#define PCI32_DIRECT_BASE               0x80000000
-
-#define IS_PCI32_MAPPED(x)              ((uint64_t)(x) < PCI32_DIRECT_BASE && \
-                                         (uint64_t)(x) >= PCI32_MAPPED_BASE)
-#define IS_PCI32_DIRECT(x)              ((uint64_t)(x) >= PCI32_MAPPED_BASE)
-
-
-/*
- * Bridge PMU Address Transaltion Entry Attibutes
- */
-#define PCI32_ATE_V                     (0x1 << 0)
-#define PCI32_ATE_CO                    (0x1 << 1)
-#define PCI32_ATE_PREC                  (0x1 << 2)
-#define PCI32_ATE_PREF                  (0x1 << 3)
-#define PCI32_ATE_BAR                   (0x1 << 4)
-#define PCI32_ATE_ADDR_SHFT             12
-
-#define MINIMAL_ATES_REQUIRED(addr, size) \
-       (IOPG(IOPGOFF(addr) + (size) - 1) == IOPG((size) - 1))
-
-#define MINIMAL_ATE_FLAG(addr, size) \
-       (MINIMAL_ATES_REQUIRED((uint64_t)addr, size) ? 1 : 0)
-
-/* bit 29 of the pci address is the SWAP bit */
-#define ATE_SWAPSHIFT                   29
-#define ATE_SWAP_ON(x)                  ((x) |= (1 << ATE_SWAPSHIFT))
-#define ATE_SWAP_OFF(x)                 ((x) &= ~(1 << ATE_SWAPSHIFT))
-
-/*
- * I/O page size
- */
-#if PAGE_SIZE < 16384
-#define IOPFNSHIFT                      12      /* 4K per mapped page */
-#else
-#define IOPFNSHIFT                      14      /* 16K per mapped page */
-#endif
-
-#define IOPGSIZE                        (1 << IOPFNSHIFT)
-#define IOPG(x)                         ((x) >> IOPFNSHIFT)
-#define IOPGOFF(x)                      ((x) & (IOPGSIZE-1))
-
-#define PCIBR_DEV_SWAP_DIR              (1ull << 19)
-#define PCIBR_CTRL_PAGE_SIZE            (0x1 << 21)
-
-/*
- * PMU resources.
- */
-struct ate_resource{
-       uint64_t *ate;
-       uint64_t num_ate;
-       uint64_t lowest_free_index;
-};
-
-struct pcibus_info {
-       struct pcibus_bussoft   pbi_buscommon;   /* common header */
-       uint32_t                pbi_moduleid;
-       short                   pbi_bridge_type;
-       short                   pbi_bridge_mode;
-
-       struct ate_resource     pbi_int_ate_resource;
-       uint64_t                pbi_int_ate_size;
-       
-       uint64_t                pbi_dir_xbase;
-       char                    pbi_hub_xid;
-
-       uint64_t                pbi_devreg[8];
-       spinlock_t              pbi_lock;
-
-       uint32_t                pbi_valid_devices;
-       uint32_t                pbi_enabled_devices;
-};
-
-/*
- * pcibus_info structure locking macros
- */
-inline static unsigned long
-pcibr_lock(struct pcibus_info *pcibus_info)
-{
-       unsigned long flag;
-       spin_lock_irqsave(&pcibus_info->pbi_lock, flag);
-       return(flag);
-}
-#define pcibr_unlock(pcibus_info, flag)  spin_unlock_irqrestore(&pcibus_info->pbi_lock, flag)
-
-extern int  pcibr_init_provider(void);
-extern void *pcibr_bus_fixup(struct pcibus_bussoft *);
-extern dma_addr_t pcibr_dma_map(struct pci_dev *, unsigned long, size_t);
-extern dma_addr_t pcibr_dma_map_consistent(struct pci_dev *, unsigned long, size_t);
-extern void pcibr_dma_unmap(struct pci_dev *, dma_addr_t, int);
-
-/*
- * prototypes for the bridge asic register access routines in pcibr_reg.c
- */
-extern void             pcireg_control_bit_clr(struct pcibus_info *, uint64_t);
-extern void             pcireg_control_bit_set(struct pcibus_info *, uint64_t);
-extern uint64_t         pcireg_tflush_get(struct pcibus_info *);
-extern uint64_t         pcireg_intr_status_get(struct pcibus_info *);
-extern void             pcireg_intr_enable_bit_clr(struct pcibus_info *, uint64_t);
-extern void             pcireg_intr_enable_bit_set(struct pcibus_info *, uint64_t);
-extern void             pcireg_intr_addr_addr_set(struct pcibus_info *, int, uint64_t);
-extern void             pcireg_force_intr_set(struct pcibus_info *, int);
-extern uint64_t         pcireg_wrb_flush_get(struct pcibus_info *, int);
-extern void             pcireg_int_ate_set(struct pcibus_info *, int, uint64_t);
-extern uint64_t *      pcireg_int_ate_addr(struct pcibus_info *, int);
-extern void            pcibr_force_interrupt(struct sn_irq_info *sn_irq_info);
-extern void            pcibr_change_devices_irq(struct sn_irq_info *sn_irq_info);
-extern int             pcibr_ate_alloc(struct pcibus_info *, int);
-extern void            pcibr_ate_free(struct pcibus_info *, int);
-extern void            ate_write(struct pcibus_info *, int, int, uint64_t);
-#endif
diff --git a/arch/ia64/sn/include/pci/pic.h b/arch/ia64/sn/include/pci/pic.h
deleted file mode 100644 (file)
index fd18ace..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
- */
-#ifndef _ASM_IA64_SN_PCI_PIC_H
-#define _ASM_IA64_SN_PCI_PIC_H
-
-/*
- * PIC AS DEVICE ZERO
- * ------------------
- *
- * PIC handles PCI/X busses.  PCI/X requires that the 'bridge' (i.e. PIC)
- * be designated as 'device 0'.   That is a departure from earlier SGI
- * PCI bridges.  Because of that we use config space 1 to access the
- * config space of the first actual PCI device on the bus. 
- * Here's what the PIC manual says:
- *
- *     The current PCI-X bus specification now defines that the parent
- *     hosts bus bridge (PIC for example) must be device 0 on bus 0. PIC
- *     reduced the total number of devices from 8 to 4 and removed the
- *     device registers and windows, now only supporting devices 0,1,2, and
- *     3. PIC did leave all 8 configuration space windows. The reason was
- *     there was nothing to gain by removing them. Here in lies the problem.
- *     The device numbering we do using 0 through 3 is unrelated to the device
- *     numbering which PCI-X requires in configuration space. In the past we
- *     correlated Configs pace and our device space 0 <-> 0, 1 <-> 1, etc.
- *     PCI-X requires we start a 1, not 0 and currently the PX brick
- *     does associate our:
- * 
- *         device 0 with configuration space window 1,
- *         device 1 with configuration space window 2, 
- *         device 2 with configuration space window 3,
- *         device 3 with configuration space window 4.
- *
- * The net effect is that all config space access are off-by-one with 
- * relation to other per-slot accesses on the PIC.   
- * Here is a table that shows some of that:
- *
- *                               Internal Slot#
- *           |
- *           |     0         1        2         3
- * ----------|---------------------------------------
- * config    |  0x21000   0x22000  0x23000   0x24000
- *           |
- * even rrb  |  0[0]      n/a      1[0]      n/a       [] == implied even/odd
- *           |
- * odd rrb   |  n/a       0[1]     n/a       1[1]
- *           |
- * int dev   |  00       01        10        11
- *           |
- * ext slot# |  1        2         3         4
- * ----------|---------------------------------------
- */
-
-#define PIC_ATE_TARGETID_SHFT           8
-#define PIC_HOST_INTR_ADDR              0x0000FFFFFFFFFFFFUL
-#define PIC_PCI64_ATTR_TARG_SHFT        60
-
-
-/*****************************************************************************
- *********************** PIC MMR structure mapping ***************************
- *****************************************************************************/
-
-/* NOTE: PIC WAR. PV#854697.  PIC does not allow writes just to [31:0]
- * of a 64-bit register.  When writing PIC registers, always write the 
- * entire 64 bits.
- */
-
-struct pic {
-
-    /* 0x000000-0x00FFFF -- Local Registers */
-
-    /* 0x000000-0x000057 -- Standard Widget Configuration */
-    uint64_t           p_wid_id;                       /* 0x000000 */
-    uint64_t           p_wid_stat;                     /* 0x000008 */
-    uint64_t           p_wid_err_upper;                /* 0x000010 */
-    uint64_t           p_wid_err_lower;                /* 0x000018 */
-    #define p_wid_err p_wid_err_lower
-    uint64_t           p_wid_control;                  /* 0x000020 */
-    uint64_t           p_wid_req_timeout;              /* 0x000028 */
-    uint64_t           p_wid_int_upper;                /* 0x000030 */
-    uint64_t           p_wid_int_lower;                /* 0x000038 */
-    #define p_wid_int p_wid_int_lower
-    uint64_t           p_wid_err_cmdword;              /* 0x000040 */
-    uint64_t           p_wid_llp;                      /* 0x000048 */
-    uint64_t           p_wid_tflush;                   /* 0x000050 */
-
-    /* 0x000058-0x00007F -- Bridge-specific Widget Configuration */
-    uint64_t           p_wid_aux_err;                  /* 0x000058 */
-    uint64_t           p_wid_resp_upper;               /* 0x000060 */
-    uint64_t           p_wid_resp_lower;               /* 0x000068 */
-    #define p_wid_resp p_wid_resp_lower
-    uint64_t           p_wid_tst_pin_ctrl;             /* 0x000070 */
-    uint64_t           p_wid_addr_lkerr;               /* 0x000078 */
-
-    /* 0x000080-0x00008F -- PMU & MAP */
-    uint64_t           p_dir_map;                      /* 0x000080 */
-    uint64_t           _pad_000088;                    /* 0x000088 */
-
-    /* 0x000090-0x00009F -- SSRAM */
-    uint64_t           p_map_fault;                    /* 0x000090 */
-    uint64_t           _pad_000098;                    /* 0x000098 */
-
-    /* 0x0000A0-0x0000AF -- Arbitration */
-    uint64_t           p_arb;                          /* 0x0000A0 */
-    uint64_t           _pad_0000A8;                    /* 0x0000A8 */
-
-    /* 0x0000B0-0x0000BF -- Number In A Can or ATE Parity Error */
-    uint64_t           p_ate_parity_err;               /* 0x0000B0 */
-    uint64_t           _pad_0000B8;                    /* 0x0000B8 */
-
-    /* 0x0000C0-0x0000FF -- PCI/GIO */
-    uint64_t           p_bus_timeout;                  /* 0x0000C0 */
-    uint64_t           p_pci_cfg;                      /* 0x0000C8 */
-    uint64_t           p_pci_err_upper;                /* 0x0000D0 */
-    uint64_t           p_pci_err_lower;                /* 0x0000D8 */
-    #define p_pci_err p_pci_err_lower
-    uint64_t           _pad_0000E0[4];                 /* 0x0000{E0..F8} */
-
-    /* 0x000100-0x0001FF -- Interrupt */
-    uint64_t           p_int_status;                   /* 0x000100 */
-    uint64_t           p_int_enable;                   /* 0x000108 */
-    uint64_t           p_int_rst_stat;                 /* 0x000110 */
-    uint64_t           p_int_mode;                     /* 0x000118 */
-    uint64_t           p_int_device;                   /* 0x000120 */
-    uint64_t           p_int_host_err;                 /* 0x000128 */
-    uint64_t           p_int_addr[8];                  /* 0x0001{30,,,68} */
-    uint64_t           p_err_int_view;                 /* 0x000170 */
-    uint64_t           p_mult_int;                     /* 0x000178 */
-    uint64_t           p_force_always[8];              /* 0x0001{80,,,B8} */
-    uint64_t           p_force_pin[8];                 /* 0x0001{C0,,,F8} */
-
-    /* 0x000200-0x000298 -- Device */
-    uint64_t           p_device[4];                    /* 0x0002{00,,,18} */
-    uint64_t           _pad_000220[4];                 /* 0x0002{20,,,38} */
-    uint64_t           p_wr_req_buf[4];                /* 0x0002{40,,,58} */
-    uint64_t           _pad_000260[4];                 /* 0x0002{60,,,78} */
-    uint64_t           p_rrb_map[2];                   /* 0x0002{80,,,88} */
-    #define p_even_resp p_rrb_map[0]                   /* 0x000280 */
-    #define p_odd_resp  p_rrb_map[1]                   /* 0x000288 */
-    uint64_t           p_resp_status;                  /* 0x000290 */
-    uint64_t           p_resp_clear;                   /* 0x000298 */
-
-    uint64_t           _pad_0002A0[12];                /* 0x0002{A0..F8} */
-
-    /* 0x000300-0x0003F8 -- Buffer Address Match Registers */
-    struct {
-       uint64_t        upper;                          /* 0x0003{00,,,F0} */
-       uint64_t        lower;                          /* 0x0003{08,,,F8} */
-    } p_buf_addr_match[16];
-
-    /* 0x000400-0x0005FF -- Performance Monitor Registers (even only) */
-    struct {
-       uint64_t        flush_w_touch;                  /* 0x000{400,,,5C0} */
-       uint64_t        flush_wo_touch;                 /* 0x000{408,,,5C8} */
-       uint64_t        inflight;                       /* 0x000{410,,,5D0} */
-       uint64_t        prefetch;                       /* 0x000{418,,,5D8} */
-       uint64_t        total_pci_retry;                /* 0x000{420,,,5E0} */
-       uint64_t        max_pci_retry;                  /* 0x000{428,,,5E8} */
-       uint64_t        max_latency;                    /* 0x000{430,,,5F0} */
-       uint64_t        clear_all;                      /* 0x000{438,,,5F8} */
-    } p_buf_count[8];
-
-    
-    /* 0x000600-0x0009FF -- PCI/X registers */
-    uint64_t           p_pcix_bus_err_addr;            /* 0x000600 */
-    uint64_t           p_pcix_bus_err_attr;            /* 0x000608 */
-    uint64_t           p_pcix_bus_err_data;            /* 0x000610 */
-    uint64_t           p_pcix_pio_split_addr;          /* 0x000618 */
-    uint64_t           p_pcix_pio_split_attr;          /* 0x000620 */
-    uint64_t           p_pcix_dma_req_err_attr;        /* 0x000628 */
-    uint64_t           p_pcix_dma_req_err_addr;        /* 0x000630 */
-    uint64_t           p_pcix_timeout;                 /* 0x000638 */
-
-    uint64_t           _pad_000640[120];               /* 0x000{640,,,9F8} */
-
-    /* 0x000A00-0x000BFF -- PCI/X Read&Write Buffer */
-    struct {
-       uint64_t        p_buf_addr;                     /* 0x000{A00,,,AF0} */
-       uint64_t        p_buf_attr;                     /* 0X000{A08,,,AF8} */
-    } p_pcix_read_buf_64[16];
-
-    struct {
-       uint64_t        p_buf_addr;                     /* 0x000{B00,,,BE0} */
-       uint64_t        p_buf_attr;                     /* 0x000{B08,,,BE8} */
-       uint64_t        p_buf_valid;                    /* 0x000{B10,,,BF0} */
-       uint64_t        __pad1;                         /* 0x000{B18,,,BF8} */
-    } p_pcix_write_buf_64[8];
-
-    /* End of Local Registers -- Start of Address Map space */
-
-    char               _pad_000c00[0x010000 - 0x000c00];
-
-    /* 0x010000-0x011fff -- Internal ATE RAM (Auto Parity Generation) */
-    uint64_t           p_int_ate_ram[1024];            /* 0x010000-0x011fff */
-
-    /* 0x012000-0x013fff -- Internal ATE RAM (Manual Parity Generation) */
-    uint64_t           p_int_ate_ram_mp[1024];         /* 0x012000-0x013fff */
-
-    char               _pad_014000[0x18000 - 0x014000];
-
-    /* 0x18000-0x197F8 -- PIC Write Request Ram */
-    uint64_t           p_wr_req_lower[256];            /* 0x18000 - 0x187F8 */
-    uint64_t           p_wr_req_upper[256];            /* 0x18800 - 0x18FF8 */
-    uint64_t           p_wr_req_parity[256];           /* 0x19000 - 0x197F8 */
-
-    char               _pad_019800[0x20000 - 0x019800];
-
-    /* 0x020000-0x027FFF -- PCI Device Configuration Spaces */
-    union {
-       uint8_t         c[0x1000 / 1];                  /* 0x02{0000,,,7FFF} */
-       uint16_t        s[0x1000 / 2];                  /* 0x02{0000,,,7FFF} */
-       uint32_t        l[0x1000 / 4];                  /* 0x02{0000,,,7FFF} */
-       uint64_t        d[0x1000 / 8];                  /* 0x02{0000,,,7FFF} */
-       union {
-           uint8_t     c[0x100 / 1];
-           uint16_t    s[0x100 / 2];
-           uint32_t    l[0x100 / 4];
-           uint64_t    d[0x100 / 8];
-       } f[8];
-    } p_type0_cfg_dev[8];                              /* 0x02{0000,,,7FFF} */
-
-    /* 0x028000-0x028FFF -- PCI Type 1 Configuration Space */
-    union {
-       uint8_t         c[0x1000 / 1];                  /* 0x028000-0x029000 */
-       uint16_t        s[0x1000 / 2];                  /* 0x028000-0x029000 */
-       uint32_t        l[0x1000 / 4];                  /* 0x028000-0x029000 */
-       uint64_t        d[0x1000 / 8];                  /* 0x028000-0x029000 */
-       union {
-           uint8_t     c[0x100 / 1];
-           uint16_t    s[0x100 / 2];
-           uint32_t    l[0x100 / 4];
-           uint64_t    d[0x100 / 8];
-       } f[8];
-    } p_type1_cfg;                                     /* 0x028000-0x029000 */
-
-    char               _pad_029000[0x030000-0x029000];
-
-    /* 0x030000-0x030007 -- PCI Interrupt Acknowledge Cycle */
-    union {
-       uint8_t         c[8 / 1];
-       uint16_t        s[8 / 2];
-       uint32_t        l[8 / 4];
-       uint64_t        d[8 / 8];
-    } p_pci_iack;                                      /* 0x030000-0x030007 */
-
-    char               _pad_030007[0x040000-0x030008];
-
-    /* 0x040000-0x030007 -- PCIX Special Cycle */
-    union {
-       uint8_t         c[8 / 1];
-       uint16_t        s[8 / 2];
-       uint32_t        l[8 / 4];
-       uint64_t        d[8 / 8];
-    } p_pcix_cycle;                                    /* 0x040000-0x040007 */
-};
-
-#endif                          /* _ASM_IA64_SN_PCI_PIC_H */
diff --git a/arch/ia64/sn/include/pci/tiocp.h b/arch/ia64/sn/include/pci/tiocp.h
deleted file mode 100644 (file)
index f07c83b..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003-2004 Silicon Graphics, Inc. All rights reserved.
- */
-#ifndef _ASM_IA64_SN_PCI_TIOCP_H
-#define _ASM_IA64_SN_PCI_TIOCP_H
-
-#define TIOCP_HOST_INTR_ADDR            0x003FFFFFFFFFFFFFUL
-#define TIOCP_PCI64_CMDTYPE_MEM         (0x1ull << 60)
-
-
-/*****************************************************************************
- *********************** TIOCP MMR structure mapping ***************************
- *****************************************************************************/
-
-struct tiocp{
-
-    /* 0x000000-0x00FFFF -- Local Registers */
-
-    /* 0x000000-0x000057 -- (Legacy Widget Space) Configuration */
-    uint64_t           cp_id;                          /* 0x000000 */
-    uint64_t           cp_stat;                        /* 0x000008 */
-    uint64_t           cp_err_upper;                   /* 0x000010 */
-    uint64_t           cp_err_lower;                   /* 0x000018 */
-    #define cp_err cp_err_lower
-    uint64_t           cp_control;                     /* 0x000020 */
-    uint64_t           cp_req_timeout;                 /* 0x000028 */
-    uint64_t           cp_intr_upper;                  /* 0x000030 */
-    uint64_t           cp_intr_lower;                  /* 0x000038 */
-    #define cp_intr cp_intr_lower
-    uint64_t           cp_err_cmdword;                 /* 0x000040 */
-    uint64_t           _pad_000048;                    /* 0x000048 */
-    uint64_t           cp_tflush;                      /* 0x000050 */
-
-    /* 0x000058-0x00007F -- Bridge-specific Configuration */
-    uint64_t           cp_aux_err;                     /* 0x000058 */
-    uint64_t           cp_resp_upper;                  /* 0x000060 */
-    uint64_t           cp_resp_lower;                  /* 0x000068 */
-    #define cp_resp cp_resp_lower
-    uint64_t           cp_tst_pin_ctrl;                /* 0x000070 */
-    uint64_t           cp_addr_lkerr;                  /* 0x000078 */
-
-    /* 0x000080-0x00008F -- PMU & MAP */
-    uint64_t           cp_dir_map;                     /* 0x000080 */
-    uint64_t           _pad_000088;                    /* 0x000088 */
-
-    /* 0x000090-0x00009F -- SSRAM */
-    uint64_t           cp_map_fault;                   /* 0x000090 */
-    uint64_t           _pad_000098;                    /* 0x000098 */
-
-    /* 0x0000A0-0x0000AF -- Arbitration */
-    uint64_t           cp_arb;                         /* 0x0000A0 */
-    uint64_t           _pad_0000A8;                    /* 0x0000A8 */
-
-    /* 0x0000B0-0x0000BF -- Number In A Can or ATE Parity Error */
-    uint64_t           cp_ate_parity_err;              /* 0x0000B0 */
-    uint64_t           _pad_0000B8;                    /* 0x0000B8 */
-
-    /* 0x0000C0-0x0000FF -- PCI/GIO */
-    uint64_t           cp_bus_timeout;                 /* 0x0000C0 */
-    uint64_t           cp_pci_cfg;                     /* 0x0000C8 */
-    uint64_t           cp_pci_err_upper;               /* 0x0000D0 */
-    uint64_t           cp_pci_err_lower;               /* 0x0000D8 */
-    #define cp_pci_err cp_pci_err_lower
-    uint64_t           _pad_0000E0[4];                 /* 0x0000{E0..F8} */
-
-    /* 0x000100-0x0001FF -- Interrupt */
-    uint64_t           cp_int_status;                  /* 0x000100 */
-    uint64_t           cp_int_enable;                  /* 0x000108 */
-    uint64_t           cp_int_rst_stat;                /* 0x000110 */
-    uint64_t           cp_int_mode;                    /* 0x000118 */
-    uint64_t           cp_int_device;                  /* 0x000120 */
-    uint64_t           cp_int_host_err;                /* 0x000128 */
-    uint64_t           cp_int_addr[8];                 /* 0x0001{30,,,68} */
-    uint64_t           cp_err_int_view;                /* 0x000170 */
-    uint64_t           cp_mult_int;                    /* 0x000178 */
-    uint64_t           cp_force_always[8];             /* 0x0001{80,,,B8} */
-    uint64_t           cp_force_pin[8];                /* 0x0001{C0,,,F8} */
-
-    /* 0x000200-0x000298 -- Device */
-    uint64_t           cp_device[4];                   /* 0x0002{00,,,18} */
-    uint64_t           _pad_000220[4];                 /* 0x0002{20,,,38} */
-    uint64_t           cp_wr_req_buf[4];               /* 0x0002{40,,,58} */
-    uint64_t           _pad_000260[4];                 /* 0x0002{60,,,78} */
-    uint64_t           cp_rrb_map[2];                  /* 0x0002{80,,,88} */
-    #define cp_even_resp cp_rrb_map[0]                 /* 0x000280 */
-    #define cp_odd_resp  cp_rrb_map[1]                 /* 0x000288 */
-    uint64_t           cp_resp_status;                 /* 0x000290 */
-    uint64_t           cp_resp_clear;                  /* 0x000298 */
-
-    uint64_t           _pad_0002A0[12];                /* 0x0002{A0..F8} */
-
-    /* 0x000300-0x0003F8 -- Buffer Address Match Registers */
-    struct {
-       uint64_t        upper;                          /* 0x0003{00,,,F0} */
-       uint64_t        lower;                          /* 0x0003{08,,,F8} */
-    } cp_buf_addr_match[16];
-
-    /* 0x000400-0x0005FF -- Performance Monitor Registers (even only) */
-    struct {
-       uint64_t        flush_w_touch;                  /* 0x000{400,,,5C0} */
-       uint64_t        flush_wo_touch;                 /* 0x000{408,,,5C8} */
-       uint64_t        inflight;                       /* 0x000{410,,,5D0} */
-       uint64_t        prefetch;                       /* 0x000{418,,,5D8} */
-       uint64_t        total_pci_retry;                /* 0x000{420,,,5E0} */
-       uint64_t        max_pci_retry;                  /* 0x000{428,,,5E8} */
-       uint64_t        max_latency;                    /* 0x000{430,,,5F0} */
-       uint64_t        clear_all;                      /* 0x000{438,,,5F8} */
-    } cp_buf_count[8];
-
-    
-    /* 0x000600-0x0009FF -- PCI/X registers */
-    uint64_t           cp_pcix_bus_err_addr;           /* 0x000600 */
-    uint64_t           cp_pcix_bus_err_attr;           /* 0x000608 */
-    uint64_t           cp_pcix_bus_err_data;           /* 0x000610 */
-    uint64_t           cp_pcix_pio_split_addr;         /* 0x000618 */
-    uint64_t           cp_pcix_pio_split_attr;         /* 0x000620 */
-    uint64_t           cp_pcix_dma_req_err_attr;       /* 0x000628 */
-    uint64_t           cp_pcix_dma_req_err_addr;       /* 0x000630 */
-    uint64_t           cp_pcix_timeout;                /* 0x000638 */
-
-    uint64_t           _pad_000640[24];                /* 0x000{640,,,6F8} */
-
-    /* 0x000700-0x000737 -- Debug Registers */
-    uint64_t           cp_ct_debug_ctl;                /* 0x000700 */
-    uint64_t           cp_br_debug_ctl;                /* 0x000708 */
-    uint64_t           cp_mux3_debug_ctl;              /* 0x000710 */
-    uint64_t           cp_mux4_debug_ctl;              /* 0x000718 */
-    uint64_t           cp_mux5_debug_ctl;              /* 0x000720 */
-    uint64_t           cp_mux6_debug_ctl;              /* 0x000728 */
-    uint64_t           cp_mux7_debug_ctl;              /* 0x000730 */
-
-    uint64_t           _pad_000738[89];                /* 0x000{738,,,9F8} */
-
-    /* 0x000A00-0x000BFF -- PCI/X Read&Write Buffer */
-    struct {
-       uint64_t        cp_buf_addr;                    /* 0x000{A00,,,AF0} */
-       uint64_t        cp_buf_attr;                    /* 0X000{A08,,,AF8} */
-    } cp_pcix_read_buf_64[16];
-
-    struct {
-       uint64_t        cp_buf_addr;                    /* 0x000{B00,,,BE0} */
-       uint64_t        cp_buf_attr;                    /* 0x000{B08,,,BE8} */
-       uint64_t        cp_buf_valid;                   /* 0x000{B10,,,BF0} */
-       uint64_t        __pad1;                         /* 0x000{B18,,,BF8} */
-    } cp_pcix_write_buf_64[8];
-
-    /* End of Local Registers -- Start of Address Map space */
-
-    char               _pad_000c00[0x010000 - 0x000c00];
-
-    /* 0x010000-0x011FF8 -- Internal ATE RAM (Auto Parity Generation) */
-    uint64_t           cp_int_ate_ram[1024];           /* 0x010000-0x011FF8 */
-
-    char               _pad_012000[0x14000 - 0x012000];
-
-    /* 0x014000-0x015FF8 -- Internal ATE RAM (Manual Parity Generation) */
-    uint64_t           cp_int_ate_ram_mp[1024];        /* 0x014000-0x015FF8 */
-
-    char               _pad_016000[0x18000 - 0x016000];
-
-    /* 0x18000-0x197F8 -- TIOCP Write Request Ram */
-    uint64_t           cp_wr_req_lower[256];           /* 0x18000 - 0x187F8 */
-    uint64_t           cp_wr_req_upper[256];           /* 0x18800 - 0x18FF8 */
-    uint64_t           cp_wr_req_parity[256];          /* 0x19000 - 0x197F8 */
-
-    char               _pad_019800[0x1C000 - 0x019800];
-
-    /* 0x1C000-0x1EFF8 -- TIOCP Read Response Ram */
-    uint64_t           cp_rd_resp_lower[512];          /* 0x1C000 - 0x1CFF8 */
-    uint64_t           cp_rd_resp_upper[512];          /* 0x1D000 - 0x1DFF8 */
-    uint64_t           cp_rd_resp_parity[512];         /* 0x1E000 - 0x1EFF8 */
-
-    char               _pad_01F000[0x20000 - 0x01F000];
-
-    /* 0x020000-0x021FFF -- Host Device (CP) Configuration Space (not used)  */
-    char               _pad_020000[0x021000 - 0x20000];
-
-    /* 0x021000-0x027FFF -- PCI Device Configuration Spaces */
-    union {
-       uint8_t         c[0x1000 / 1];                  /* 0x02{0000,,,7FFF} */
-       uint16_t        s[0x1000 / 2];                  /* 0x02{0000,,,7FFF} */
-       uint32_t        l[0x1000 / 4];                  /* 0x02{0000,,,7FFF} */
-       uint64_t        d[0x1000 / 8];                  /* 0x02{0000,,,7FFF} */
-       union {
-           uint8_t     c[0x100 / 1];
-           uint16_t    s[0x100 / 2];
-           uint32_t    l[0x100 / 4];
-           uint64_t    d[0x100 / 8];
-       } f[8];
-    } cp_type0_cfg_dev[7];                             /* 0x02{1000,,,7FFF} */
-
-    /* 0x028000-0x028FFF -- PCI Type 1 Configuration Space */
-    union {
-       uint8_t         c[0x1000 / 1];                  /* 0x028000-0x029000 */
-       uint16_t        s[0x1000 / 2];                  /* 0x028000-0x029000 */
-       uint32_t        l[0x1000 / 4];                  /* 0x028000-0x029000 */
-       uint64_t        d[0x1000 / 8];                  /* 0x028000-0x029000 */
-       union {
-           uint8_t     c[0x100 / 1];
-           uint16_t    s[0x100 / 2];
-           uint32_t    l[0x100 / 4];
-           uint64_t    d[0x100 / 8];
-       } f[8];
-    } cp_type1_cfg;                                    /* 0x028000-0x029000 */
-
-    char               _pad_029000[0x030000-0x029000];
-
-    /* 0x030000-0x030007 -- PCI Interrupt Acknowledge Cycle */
-    union {
-       uint8_t         c[8 / 1];
-       uint16_t        s[8 / 2];
-       uint32_t        l[8 / 4];
-       uint64_t        d[8 / 8];
-    } cp_pci_iack;                                     /* 0x030000-0x030007 */
-
-    char               _pad_030007[0x040000-0x030008];
-
-    /* 0x040000-0x040007 -- PCIX Special Cycle */
-    union {
-       uint8_t         c[8 / 1];
-       uint16_t        s[8 / 2];
-       uint32_t        l[8 / 4];
-       uint64_t        d[8 / 8];
-    } cp_pcix_cycle;                                   /* 0x040000-0x040007 */
-
-    char               _pad_040007[0x200000-0x040008];
-
-    /* 0x200000-0x7FFFFF -- PCI/GIO Device Spaces */
-    union {
-       uint8_t         c[0x100000 / 1];
-       uint16_t        s[0x100000 / 2];
-       uint32_t        l[0x100000 / 4];
-       uint64_t        d[0x100000 / 8];
-    } cp_devio_raw[6];                                 /* 0x200000-0x7FFFFF */
-
-    #define cp_devio(n)  cp_devio_raw[((n)<2)?(n*2):(n+2)]
-
-    char               _pad_800000[0xA00000-0x800000];
-
-    /* 0xA00000-0xBFFFFF -- PCI/GIO Device Spaces w/flush  */
-    union {
-       uint8_t         c[0x100000 / 1];
-       uint16_t        s[0x100000 / 2];
-       uint32_t        l[0x100000 / 4];
-       uint64_t        d[0x100000 / 8];
-    } cp_devio_raw_flush[6];                           /* 0xA00000-0xBFFFFF */
-
-    #define cp_devio_flush(n)  cp_devio_raw_flush[((n)<2)?(n*2):(n+2)]
-
-};
-
-#endif         /* _ASM_IA64_SN_PCI_TIOCP_H */
index 868e7ecae84b7494628c241a26954dcd83fabd48..580a1c0403a73c373c60cf34cc59f985bb5a16f0 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef _ASM_IA64_SN_XTALK_HUBDEV_H
 #define _ASM_IA64_SN_XTALK_HUBDEV_H
 
+#include "xtalk/xwidgetdev.h"
+
 #define HUB_WIDGET_ID_MAX 0xf
 #define DEV_PER_WIDGET (2*2*8)
 #define IIO_ITTE_WIDGET_BITS    4       /* size of widget field */
index 783eb4323847c26f40a27893e9c94c313c898d50..a67f39e448cb47a0d0aec8429bcbabbf0888d0bc 100644 (file)
@@ -9,21 +9,28 @@
 #include <linux/bootmem.h>
 #include <linux/nodemask.h>
 #include <asm/sn/types.h>
-#include <asm/sn/sn_sal.h>
 #include <asm/sn/addrs.h>
-#include <asm/sn/pcibus_provider_defs.h>
-#include <asm/sn/pcidev.h>
-#include "pci/pcibr_provider.h"
-#include "xtalk/xwidgetdev.h"
 #include <asm/sn/geo.h>
-#include "xtalk/hubdev.h"
 #include <asm/sn/io.h>
+#include <asm/sn/pcibr_provider.h>
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
 #include <asm/sn/simulator.h>
+#include <asm/sn/sn_sal.h>
 #include <asm/sn/tioca_provider.h>
+#include "xtalk/hubdev.h"
+#include "xtalk/xwidgetdev.h"
 
-char master_baseio_wid;
 nasid_t master_nasid = INVALID_NASID;  /* Partition Master */
 
+static struct list_head sn_sysdata_list;
+
+/* sysdata list struct */
+struct sysdata_el {
+       struct list_head entry;
+       void *sysdata;
+};
+
 struct slab_info {
        struct hubdev_info hubdev;
 };
@@ -137,23 +144,6 @@ sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
        return ret_stuff.v0;
 }
 
-/*
- * sn_alloc_pci_sysdata() - This routine allocates a pci controller
- *     which is expected as the pci_dev and pci_bus sysdata by the Linux
- *     PCI infrastructure.
- */
-static inline struct pci_controller *sn_alloc_pci_sysdata(void)
-{
-       struct pci_controller *pci_sysdata;
-
-       pci_sysdata = kmalloc(sizeof(*pci_sysdata), GFP_KERNEL);
-       if (!pci_sysdata)
-               BUG();
-
-       memset(pci_sysdata, 0, sizeof(*pci_sysdata));
-       return pci_sysdata;
-}
-
 /*
  * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for 
  *     each node in the system.
@@ -221,22 +211,34 @@ static void sn_fixup_ionodes(void)
 
 }
 
+void sn_pci_unfixup_slot(struct pci_dev *dev)
+{
+       struct pci_dev *host_pci_dev = SN_PCIDEV_INFO(dev)->host_pci_dev;
+
+       sn_irq_unfixup(dev);
+       pci_dev_put(host_pci_dev);
+       pci_dev_put(dev);
+}
+
 /*
  * sn_pci_fixup_slot() - This routine sets up a slot's resources
  * consistent with the Linux PCI abstraction layer.  Resources acquired
  * from our PCI provider include PIO maps to BAR space and interrupt
  * objects.
  */
-static void sn_pci_fixup_slot(struct pci_dev *dev)
+void sn_pci_fixup_slot(struct pci_dev *dev)
 {
        int idx;
        int segment = 0;
-       uint64_t size;
-       struct sn_irq_info *sn_irq_info;
-       struct pci_dev *host_pci_dev;
        int status = 0;
        struct pcibus_bussoft *bs;
+       struct pci_bus *host_pci_bus;
+       struct pci_dev *host_pci_dev;
+       struct sn_irq_info *sn_irq_info;
+       unsigned long size;
+       unsigned int bus_no, devfn;
 
+       pci_dev_get(dev); /* for the sysdata pointer */
        dev->sysdata = kmalloc(sizeof(struct pcidev_info), GFP_KERNEL);
        if (SN_PCIDEV_INFO(dev) <= 0)
                BUG();          /* Cannot afford to run out of memory */
@@ -253,7 +255,7 @@ static void sn_pci_fixup_slot(struct pci_dev *dev)
                                     (u64) __pa(SN_PCIDEV_INFO(dev)),
                                     (u64) __pa(sn_irq_info));
        if (status)
-               BUG();          /* Cannot get platform pci device information information */
+               BUG(); /* Cannot get platform pci device information */
 
        /* Copy over PIO Mapped Addresses */
        for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) {
@@ -275,15 +277,21 @@ static void sn_pci_fixup_slot(struct pci_dev *dev)
                        dev->resource[idx].parent = &iomem_resource;
        }
 
-       /* set up host bus linkages */
-       bs = SN_PCIBUS_BUSSOFT(dev->bus);
-       host_pci_dev =
-           pci_find_slot(SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32,
-                         SN_PCIDEV_INFO(dev)->
-                         pdi_slot_host_handle & 0xffffffff);
+       /*
+        * Using the PROMs values for the PCI host bus, get the Linux
+        * PCI host_pci_dev struct and set up host bus linkages
+        */
+
+       bus_no = SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32;
+       devfn = SN_PCIDEV_INFO(dev)->pdi_slot_host_handle & 0xffffffff;
+       host_pci_bus = pci_find_bus(pci_domain_nr(dev->bus), bus_no);
+       host_pci_dev = pci_get_slot(host_pci_bus, devfn);
+
+       SN_PCIDEV_INFO(dev)->host_pci_dev = host_pci_dev;
        SN_PCIDEV_INFO(dev)->pdi_host_pcidev_info =
-           SN_PCIDEV_INFO(host_pci_dev);
+                                               SN_PCIDEV_INFO(host_pci_dev);
        SN_PCIDEV_INFO(dev)->pdi_linux_pcidev = dev;
+       bs = SN_PCIBUS_BUSSOFT(dev->bus);
        SN_PCIDEV_INFO(dev)->pdi_pcibus_info = bs;
 
        if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) {
@@ -297,6 +305,9 @@ static void sn_pci_fixup_slot(struct pci_dev *dev)
                SN_PCIDEV_INFO(dev)->pdi_sn_irq_info = sn_irq_info;
                dev->irq = SN_PCIDEV_INFO(dev)->pdi_sn_irq_info->irq_irq;
                sn_irq_fixup(dev, sn_irq_info);
+       } else {
+               SN_PCIDEV_INFO(dev)->pdi_sn_irq_info = NULL;
+               kfree(sn_irq_info);
        }
 }
 
@@ -304,55 +315,57 @@ static void sn_pci_fixup_slot(struct pci_dev *dev)
  * sn_pci_controller_fixup() - This routine sets up a bus's resources
  * consistent with the Linux PCI abstraction layer.
  */
-static void sn_pci_controller_fixup(int segment, int busnum)
+void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
 {
        int status = 0;
        int nasid, cnode;
-       struct pci_bus *bus;
        struct pci_controller *controller;
        struct pcibus_bussoft *prom_bussoft_ptr;
        struct hubdev_info *hubdev_info;
        void *provider_soft;
        struct sn_pcibus_provider *provider;
 
-       status =
-           sal_get_pcibus_info((u64) segment, (u64) busnum,
-                               (u64) ia64_tpa(&prom_bussoft_ptr));
-       if (status > 0) {
-               return;         /* bus # does not exist */
-       }
-
+       status = sal_get_pcibus_info((u64) segment, (u64) busnum,
+                                    (u64) ia64_tpa(&prom_bussoft_ptr));
+       if (status > 0)
+               return;         /*bus # does not exist */
        prom_bussoft_ptr = __va(prom_bussoft_ptr);
-       controller = sn_alloc_pci_sysdata();
-       /* controller non-zero is BUG'd in sn_alloc_pci_sysdata */
 
-       bus = pci_scan_bus(busnum, &pci_root_ops, controller);
+       controller = kcalloc(1,sizeof(struct pci_controller), GFP_KERNEL);
+       if (!controller)
+               BUG();
+
        if (bus == NULL) {
-               return;         /* error, or bus already scanned */
+               bus = pci_scan_bus(busnum, &pci_root_ops, controller);
+               if (bus == NULL)
+                       return; /* error, or bus already scanned */
+               bus->sysdata = NULL;
        }
 
+       if (bus->sysdata)
+               goto error_return; /* sysdata already alloc'd */
+
        /*
         * Per-provider fixup.  Copies the contents from prom to local
         * area and links SN_PCIBUS_BUSSOFT().
         */
 
-       if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES) {
+       if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES)
                return;         /* unsupported asic type */
-       }
+
+       if (prom_bussoft_ptr->bs_asic_type == PCIIO_ASIC_TYPE_PPB)
+               goto error_return; /* no further fixup necessary */
 
        provider = sn_pci_provider[prom_bussoft_ptr->bs_asic_type];
-       if (provider == NULL) {
+       if (provider == NULL)
                return;         /* no provider registerd for this asic */
-       }
 
        provider_soft = NULL;
-       if (provider->bus_fixup) {
+       if (provider->bus_fixup)
                provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr);
-       }
 
-       if (provider_soft == NULL) {
+       if (provider_soft == NULL)
                return;         /* fixup failed or not applicable */
-       }
 
        /*
         * Generic bus fixup goes here.  Don't reference prom_bussoft_ptr
@@ -361,12 +374,47 @@ static void sn_pci_controller_fixup(int segment, int busnum)
 
        bus->sysdata = controller;
        PCI_CONTROLLER(bus)->platform_data = provider_soft;
-
        nasid = NASID_GET(SN_PCIBUS_BUSSOFT(bus)->bs_base);
        cnode = nasid_to_cnodeid(nasid);
        hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo);
        SN_PCIBUS_BUSSOFT(bus)->bs_xwidget_info =
            &(hubdev_info->hdi_xwidget_info[SN_PCIBUS_BUSSOFT(bus)->bs_xid]);
+
+       return;
+
+error_return:
+
+       kfree(controller);
+       return;
+}
+
+void sn_bus_store_sysdata(struct pci_dev *dev)
+{
+       struct sysdata_el *element;
+
+       element = kcalloc(1, sizeof(struct sysdata_el), GFP_KERNEL);
+       if (!element) {
+               dev_dbg(dev, "%s: out of memory!\n", __FUNCTION__);
+               return;
+       }
+       element->sysdata = dev->sysdata;
+       list_add(&element->entry, &sn_sysdata_list);
+}
+
+void sn_bus_free_sysdata(void)
+{
+       struct sysdata_el *element;
+       struct list_head *list;
+
+sn_sysdata_free_start:
+       list_for_each(list, &sn_sysdata_list) {
+               element = list_entry(list, struct sysdata_el, entry);
+               list_del(&element->entry);
+               kfree(element->sysdata);
+               kfree(element);
+               goto sn_sysdata_free_start;
+       }
+       return;
 }
 
 /*
@@ -403,20 +451,17 @@ static int __init sn_pci_init(void)
         */
        ia64_max_iommu_merge_mask = ~PAGE_MASK;
        sn_fixup_ionodes();
-       sn_irq = kmalloc(sizeof(struct sn_irq_info *) * NR_IRQS, GFP_KERNEL);
-       if (sn_irq <= 0)
-               BUG();          /* Canno afford to run out of memory. */
-       memset(sn_irq, 0, sizeof(struct sn_irq_info *) * NR_IRQS);
-
+       sn_irq_lh_init();
+       INIT_LIST_HEAD(&sn_sysdata_list);
        sn_init_cpei_timer();
 
 #ifdef CONFIG_PROC_FS
        register_sn_procfs();
 #endif
 
-       for (i = 0; i < PCI_BUSES_TO_SCAN; i++) {
-               sn_pci_controller_fixup(0, i);
-       }
+       /* busses are not known yet ... */
+       for (i = 0; i < PCI_BUSES_TO_SCAN; i++)
+               sn_pci_controller_fixup(0, i, NULL);
 
        /*
         * Generic Linux PCI Layer has created the pci_bus and pci_dev 
@@ -425,9 +470,8 @@ static int __init sn_pci_init(void)
         */
 
        while ((pci_dev =
-               pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) != NULL) {
+               pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) != NULL)
                sn_pci_fixup_slot(pci_dev);
-       }
 
        sn_ioif_inited = 1;     /* sn I/O infrastructure now initialized */
 
@@ -469,3 +513,8 @@ cnodeid_get_geoid(cnodeid_t cnode)
 }
 
 subsys_initcall(sn_pci_init);
+EXPORT_SYMBOL(sn_pci_fixup_slot);
+EXPORT_SYMBOL(sn_pci_unfixup_slot);
+EXPORT_SYMBOL(sn_pci_controller_fixup);
+EXPORT_SYMBOL(sn_bus_store_sysdata);
+EXPORT_SYMBOL(sn_bus_free_sysdata);
index 0f4e8138658f2cb0ac1ce5757736906f8d7ba0b6..84d276a14ecb178d696d239f0758efaff251ee47 100644 (file)
@@ -9,13 +9,13 @@
  */
 
 #include <linux/irq.h>
-#include <asm/sn/intr.h>
+#include <linux/spinlock.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/arch.h>
-#include "xtalk/xwidgetdev.h"
+#include <asm/sn/intr.h>
+#include <asm/sn/pcibr_provider.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/pcidev.h>
-#include "pci/pcibr_provider.h"
 #include <asm/sn/shub_mmr.h>
 #include <asm/sn/sn_sal.h>
 
@@ -25,7 +25,8 @@ static void unregister_intr_pda(struct sn_irq_info *sn_irq_info);
 
 extern int sn_force_interrupt_flag;
 extern int sn_ioif_inited;
-struct sn_irq_info **sn_irq;
+static struct list_head **sn_irq_lh;
+static spinlock_t sn_irq_info_lock = SPIN_LOCK_UNLOCKED; /* non-IRQ lock */
 
 static inline uint64_t sn_intr_alloc(nasid_t local_nasid, int local_widget,
                                     u64 sn_irq_info,
@@ -101,7 +102,7 @@ static void sn_end_irq(unsigned int irq)
                nasid = get_nasid();
                event_occurred = HUB_L((uint64_t *) GLOBAL_MMR_ADDR
                                       (nasid, SH_EVENT_OCCURRED));
-               /* If the UART bit is set here, we may have received an 
+               /* If the UART bit is set here, we may have received an
                 * interrupt from the UART that the driver missed.  To
                 * make sure, we IPI ourselves to force us to look again.
                 */
@@ -115,82 +116,84 @@ static void sn_end_irq(unsigned int irq)
                force_interrupt(irq);
 }
 
+static void sn_irq_info_free(struct rcu_head *head);
+
 static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
 {
-       struct sn_irq_info *sn_irq_info = sn_irq[irq];
-       struct sn_irq_info *tmp_sn_irq_info;
+       struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
        int cpuid, cpuphys;
-       nasid_t t_nasid;        /* nasid to target */
-       int t_slice;            /* slice to target */
-
-       /* allocate a temp sn_irq_info struct to get new target info */
-       tmp_sn_irq_info = kmalloc(sizeof(*tmp_sn_irq_info), GFP_KERNEL);
-       if (!tmp_sn_irq_info)
-               return;
 
        cpuid = first_cpu(mask);
        cpuphys = cpu_physical_id(cpuid);
-       t_nasid = cpuid_to_nasid(cpuid);
-       t_slice = cpuid_to_slice(cpuid);
 
-       while (sn_irq_info) {
-               int status;
-               int local_widget;
-               uint64_t bridge = (uint64_t) sn_irq_info->irq_bridge;
-               nasid_t local_nasid = NASID_GET(bridge);
+       list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
+                                sn_irq_lh[irq], list) {
+               uint64_t bridge;
+               int local_widget, status;
+               nasid_t local_nasid;
+               struct sn_irq_info *new_irq_info;
+
+               new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
+               if (new_irq_info == NULL)
+                       break;
+               memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));
+
+               bridge = (uint64_t) new_irq_info->irq_bridge;
+               if (!bridge) {
+                       kfree(new_irq_info);
+                       break; /* irq is not a device interrupt */
+               }
 
-               if (!bridge)
-                       break;  /* irq is not a device interrupt */
+               local_nasid = NASID_GET(bridge);
 
                if (local_nasid & 1)
                        local_widget = TIO_SWIN_WIDGETNUM(bridge);
                else
                        local_widget = SWIN_WIDGETNUM(bridge);
 
-               /* Free the old PROM sn_irq_info structure */
-               sn_intr_free(local_nasid, local_widget, sn_irq_info);
+               /* Free the old PROM new_irq_info structure */
+               sn_intr_free(local_nasid, local_widget, new_irq_info);
+               /* Update kernels new_irq_info with new target info */
+               unregister_intr_pda(new_irq_info);
 
-               /* allocate a new PROM sn_irq_info struct */
+               /* allocate a new PROM new_irq_info struct */
                status = sn_intr_alloc(local_nasid, local_widget,
-                                      __pa(tmp_sn_irq_info), irq, t_nasid,
-                                      t_slice);
-
-               if (status == 0) {
-                       /* Update kernels sn_irq_info with new target info */
-                       unregister_intr_pda(sn_irq_info);
-                       sn_irq_info->irq_cpuid = cpuid;
-                       sn_irq_info->irq_nasid = t_nasid;
-                       sn_irq_info->irq_slice = t_slice;
-                       sn_irq_info->irq_xtalkaddr =
-                           tmp_sn_irq_info->irq_xtalkaddr;
-                       sn_irq_info->irq_cookie = tmp_sn_irq_info->irq_cookie;
-                       register_intr_pda(sn_irq_info);
-
-                       if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type)) {
-                               pcibr_change_devices_irq(sn_irq_info);
-                       }
+                                      __pa(new_irq_info), irq,
+                                      cpuid_to_nasid(cpuid),
+                                      cpuid_to_slice(cpuid));
+
+               /* SAL call failed */
+               if (status) {
+                       kfree(new_irq_info);
+                       break;
+               }
+
+               new_irq_info->irq_cpuid = cpuid;
+               register_intr_pda(new_irq_info);
+
+               if (IS_PCI_BRIDGE_ASIC(new_irq_info->irq_bridge_type))
+                       pcibr_change_devices_irq(new_irq_info);
 
-                       sn_irq_info = sn_irq_info->irq_next;
+               spin_lock(&sn_irq_info_lock);
+               list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
+               spin_unlock(&sn_irq_info_lock);
+               call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
 
 #ifdef CONFIG_SMP
-                       set_irq_affinity_info((irq & 0xff), cpuphys, 0);
+               set_irq_affinity_info((irq & 0xff), cpuphys, 0);
 #endif
-               } else {
-                       break;  /* snp_affinity failed the intr_alloc */
-               }
        }
-       kfree(tmp_sn_irq_info);
 }
 
 struct hw_interrupt_type irq_type_sn = {
-       "SN hub",
-       sn_startup_irq,
-       sn_shutdown_irq,
-       sn_enable_irq,
-       sn_disable_irq,
-       sn_ack_irq,
-       sn_end_irq,
-       sn_set_affinity_irq
+       .typename       = "SN hub",
+       .startup        = sn_startup_irq,
+       .shutdown       = sn_shutdown_irq,
+       .enable         = sn_enable_irq,
+       .disable        = sn_disable_irq,
+       .ack            = sn_ack_irq,
+       .end            = sn_end_irq,
+       .set_affinity   = sn_set_affinity_irq
 };
 
 unsigned int sn_local_vector_to_irq(u8 vector)
@@ -231,19 +234,18 @@ static void unregister_intr_pda(struct sn_irq_info *sn_irq_info)
        struct sn_irq_info *tmp_irq_info;
        int i, foundmatch;
 
+       rcu_read_lock();
        if (pdacpu(cpu)->sn_last_irq == irq) {
                foundmatch = 0;
-               for (i = pdacpu(cpu)->sn_last_irq - 1; i; i--) {
-                       tmp_irq_info = sn_irq[i];
-                       while (tmp_irq_info) {
+               for (i = pdacpu(cpu)->sn_last_irq - 1;
+                    i && !foundmatch; i--) {
+                       list_for_each_entry_rcu(tmp_irq_info,
+                                               sn_irq_lh[i],
+                                               list) {
                                if (tmp_irq_info->irq_cpuid == cpu) {
-                                       foundmatch++;
+                                       foundmatch = 1;
                                        break;
                                }
-                               tmp_irq_info = tmp_irq_info->irq_next;
-                       }
-                       if (foundmatch) {
-                               break;
                        }
                }
                pdacpu(cpu)->sn_last_irq = i;
@@ -251,60 +253,27 @@ static void unregister_intr_pda(struct sn_irq_info *sn_irq_info)
 
        if (pdacpu(cpu)->sn_first_irq == irq) {
                foundmatch = 0;
-               for (i = pdacpu(cpu)->sn_first_irq + 1; i < NR_IRQS; i++) {
-                       tmp_irq_info = sn_irq[i];
-                       while (tmp_irq_info) {
+               for (i = pdacpu(cpu)->sn_first_irq + 1;
+                    i < NR_IRQS && !foundmatch; i++) {
+                       list_for_each_entry_rcu(tmp_irq_info,
+                                               sn_irq_lh[i],
+                                               list) {
                                if (tmp_irq_info->irq_cpuid == cpu) {
-                                       foundmatch++;
+                                       foundmatch = 1;
                                        break;
                                }
-                               tmp_irq_info = tmp_irq_info->irq_next;
-                       }
-                       if (foundmatch) {
-                               break;
                        }
                }
                pdacpu(cpu)->sn_first_irq = ((i == NR_IRQS) ? 0 : i);
        }
+       rcu_read_unlock();
 }
 
-struct sn_irq_info *sn_irq_alloc(nasid_t local_nasid, int local_widget, int irq,
-                                nasid_t nasid, int slice)
+static void sn_irq_info_free(struct rcu_head *head)
 {
        struct sn_irq_info *sn_irq_info;
-       int status;
-
-       sn_irq_info = kmalloc(sizeof(*sn_irq_info), GFP_KERNEL);
-       if (sn_irq_info == NULL)
-               return NULL;
-
-       memset(sn_irq_info, 0x0, sizeof(*sn_irq_info));
-
-       status =
-           sn_intr_alloc(local_nasid, local_widget, __pa(sn_irq_info), irq,
-                         nasid, slice);
-
-       if (status) {
-               kfree(sn_irq_info);
-               return NULL;
-       } else {
-               return sn_irq_info;
-       }
-}
-
-void sn_irq_free(struct sn_irq_info *sn_irq_info)
-{
-       uint64_t bridge = (uint64_t) sn_irq_info->irq_bridge;
-       nasid_t local_nasid = NASID_GET(bridge);
-       int local_widget;
-
-       if (local_nasid & 1)    /* tio check */
-               local_widget = TIO_SWIN_WIDGETNUM(bridge);
-       else
-               local_widget = SWIN_WIDGETNUM(bridge);
-
-       sn_intr_free(local_nasid, local_widget, sn_irq_info);
 
+       sn_irq_info = container_of(head, struct sn_irq_info, rcu);
        kfree(sn_irq_info);
 }
 
@@ -314,30 +283,54 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
        int slice = sn_irq_info->irq_slice;
        int cpu = nasid_slice_to_cpuid(nasid, slice);
 
+       pci_dev_get(pci_dev);
        sn_irq_info->irq_cpuid = cpu;
        sn_irq_info->irq_pciioinfo = SN_PCIDEV_INFO(pci_dev);
 
        /* link it into the sn_irq[irq] list */
-       sn_irq_info->irq_next = sn_irq[sn_irq_info->irq_irq];
-       sn_irq[sn_irq_info->irq_irq] = sn_irq_info;
+       spin_lock(&sn_irq_info_lock);
+       list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]);
+       spin_unlock(&sn_irq_info_lock);
 
        (void)register_intr_pda(sn_irq_info);
 }
 
+void sn_irq_unfixup(struct pci_dev *pci_dev)
+{
+       struct sn_irq_info *sn_irq_info;
+
+       /* Only cleanup IRQ stuff if this device has a host bus context */
+       if (!SN_PCIDEV_BUSSOFT(pci_dev))
+               return;
+
+       sn_irq_info = SN_PCIDEV_INFO(pci_dev)->pdi_sn_irq_info;
+       if (!sn_irq_info || !sn_irq_info->irq_irq) {
+               kfree(sn_irq_info);
+               return;
+       }
+
+       unregister_intr_pda(sn_irq_info);
+       spin_lock(&sn_irq_info_lock);
+       list_del_rcu(&sn_irq_info->list);
+       spin_unlock(&sn_irq_info_lock);
+       call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
+       pci_dev_put(pci_dev);
+}
+
 static void force_interrupt(int irq)
 {
        struct sn_irq_info *sn_irq_info;
 
        if (!sn_ioif_inited)
                return;
-       sn_irq_info = sn_irq[irq];
-       while (sn_irq_info) {
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[irq], list) {
                if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) &&
-                   (sn_irq_info->irq_bridge != NULL)) {
+                   (sn_irq_info->irq_bridge != NULL))
                        pcibr_force_interrupt(sn_irq_info);
-               }
-               sn_irq_info = sn_irq_info->irq_next;
        }
+       rcu_read_unlock();
 }
 
 /*
@@ -402,19 +395,41 @@ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info)
 
 void sn_lb_int_war_check(void)
 {
+       struct sn_irq_info *sn_irq_info;
        int i;
 
        if (!sn_ioif_inited || pda->sn_first_irq == 0)
                return;
+
+       rcu_read_lock();
        for (i = pda->sn_first_irq; i <= pda->sn_last_irq; i++) {
-               struct sn_irq_info *sn_irq_info = sn_irq[i];
-               while (sn_irq_info) {
-                       /* Only call for PCI bridges that are fully initialized. */
+               list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[i], list) {
+                       /*
+                        * Only call for PCI bridges that are fully
+                        * initialized.
+                        */
                        if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) &&
-                           (sn_irq_info->irq_bridge != NULL)) {
+                           (sn_irq_info->irq_bridge != NULL))
                                sn_check_intr(i, sn_irq_info);
-                       }
-                       sn_irq_info = sn_irq_info->irq_next;
                }
        }
+       rcu_read_unlock();
+}
+
+void sn_irq_lh_init(void)
+{
+       int i;
+
+       sn_irq_lh = kmalloc(sizeof(struct list_head *) * NR_IRQS, GFP_KERNEL);
+       if (!sn_irq_lh)
+               panic("SN PCI INIT: Failed to allocate memory for PCI init\n");
+
+       for (i = 0; i < NR_IRQS; i++) {
+               sn_irq_lh[i] = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+               if (!sn_irq_lh[i])
+                       panic("SN PCI INIT: Failed IRQ memory allocation\n");
+
+               INIT_LIST_HEAD(sn_irq_lh[i]);
+       }
+
 }
index 22e10d282c7fc19744a8fa8defc080f1a3163260..7c7fe441d62371ec513365bd89814397e0888b2e 100644 (file)
@@ -270,7 +270,7 @@ void __init sn_setup(char **cmdline_p)
 {
        long status, ticks_per_sec, drift;
        int pxm;
-       int major = sn_sal_rev_major(), minor = sn_sal_rev_minor();
+       u32 version = sn_sal_rev();
        extern void sn_cpu_init(void);
 
        ia64_sn_plat_set_error_handling_features();
@@ -308,22 +308,21 @@ void __init sn_setup(char **cmdline_p)
         * support here so we don't have to listen to failed keyboard probe
         * messages.
         */
-       if ((major < 2 || (major == 2 && minor <= 9)) &&
-           acpi_kbd_controller_present) {
+       if (version <= 0x0209 && acpi_kbd_controller_present) {
                printk(KERN_INFO "Disabling legacy keyboard support as prom "
                       "is too old and doesn't provide FADT\n");
                acpi_kbd_controller_present = 0;
        }
 
-       printk("SGI SAL version %x.%02x\n", major, minor);
+       printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF);
 
        /*
         * Confirm the SAL we're running on is recent enough...
         */
-       if ((major < SN_SAL_MIN_MAJOR) || (major == SN_SAL_MIN_MAJOR &&
-                                          minor < SN_SAL_MIN_MINOR)) {
+       if (version < SN_SAL_MIN_VERSION) {
                printk(KERN_ERR "This kernel needs SGI SAL version >= "
-                      "%x.%02x\n", SN_SAL_MIN_MAJOR, SN_SAL_MIN_MINOR);
+                      "%x.%02x\n", SN_SAL_MIN_VERSION >> 8,
+                       SN_SAL_MIN_VERSION & 0x00FF);
                panic("PROM version too old\n");
        }
 
index 8716f4d5314b968f4b2e8df5cd5d7931db233426..c1cbcd1a1398de1db3b7ea02750b9aeca63b9060 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/proc_fs.h>
 #include <linux/device.h>
 #include <linux/delay.h>
+#include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/addrs.h>
@@ -481,6 +482,9 @@ static int __init tiocx_init(void)
        cnodeid_t cnodeid;
        int found_tiocx_device = 0;
 
+       if (!ia64_platform_is("sn2"))
+               return -ENODEV;
+
        bus_register(&tiocx_bus_type);
 
        for (cnodeid = 0; cnodeid < MAX_COMPACT_NODES; cnodeid++) {
index 5da9bdbde7cb829dbef14774cf5bf2c9d568f8d5..a2f7a88aefbb0bd925647668acc641438ac73b5c 100644 (file)
 
 #include <linux/module.h>
 #include <asm/dma.h>
-#include <asm/sn/sn_sal.h>
+#include <asm/sn/pcibr_provider.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/pcidev.h>
+#include <asm/sn/sn_sal.h>
 
 #define SG_ENT_VIRT_ADDRESS(sg)        (page_address((sg)->page) + (sg)->offset)
 #define SG_ENT_PHYS_ADDRESS(SG)        virt_to_phys(SG_ENT_VIRT_ADDRESS(SG))
index 0e47bce85f2da0e1494ff5f705c8fa91b59ae161..d1647b863e6106a3d17219c4b9748633dc165630 100644 (file)
@@ -8,9 +8,9 @@
 
 #include <linux/types.h>
 #include <asm/sn/sn_sal.h>
+#include <asm/sn/pcibr_provider.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/pcidev.h>
-#include "pci/pcibr_provider.h"
 
 int pcibr_invalidate_ate = 0;  /* by default don't invalidate ATE on free */
 
index 64af2b2c17879181e0610cdaa7fb10dfdb8bf26e..b058dc2a0b9d3dfb7a17fe73f2ae35f72266ebd3 100644 (file)
@@ -8,18 +8,17 @@
 
 #include <linux/types.h>
 #include <linux/pci.h>
-#include <asm/sn/sn_sal.h>
+#include <asm/sn/addrs.h>
 #include <asm/sn/geo.h>
-#include "xtalk/xwidgetdev.h"
-#include "xtalk/hubdev.h"
+#include <asm/sn/pcibr_provider.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/pcidev.h>
-#include "pci/tiocp.h"
-#include "pci/pic.h"
-#include "pci/pcibr_provider.h"
-#include "pci/tiocp.h"
+#include <asm/sn/pic.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/tiocp.h>
 #include "tio.h"
-#include <asm/sn/addrs.h>
+#include "xtalk/xwidgetdev.h"
+#include "xtalk/hubdev.h"
 
 extern int sn_ioif_inited;
 
index 3893999d23d8871a7f5f6bf4315b24d713391411..9813da56d3113c41fb1b413cfa4c7963cda316cb 100644 (file)
@@ -6,18 +6,51 @@
  * Copyright (C) 2001-2004 Silicon Graphics, Inc. All rights reserved.
  */
 
-#include <linux/types.h>
 #include <linux/interrupt.h>
+#include <linux/types.h>
 #include <linux/pci.h>
-#include <asm/sn/sn_sal.h>
-#include "xtalk/xwidgetdev.h"
+#include <asm/sn/addrs.h>
 #include <asm/sn/geo.h>
-#include "xtalk/hubdev.h"
+#include <asm/sn/pcibr_provider.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/pcidev.h>
-#include "pci/pcibr_provider.h"
-#include <asm/sn/addrs.h>
+#include <asm/sn/sn_sal.h>
+#include "xtalk/xwidgetdev.h"
+#include "xtalk/hubdev.h"
+
+int
+sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp)
+{
+       struct ia64_sal_retval ret_stuff;
+       uint64_t busnum;
+
+       ret_stuff.status = 0;
+       ret_stuff.v0 = 0;
 
+       busnum = soft->pbi_buscommon.bs_persist_busnum;
+       SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, (u64) busnum,
+                       (u64) device, (u64) resp, 0, 0, 0, 0);
+
+       return (int)ret_stuff.v0;
+}
+
+int
+sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action,
+                      void *resp)
+{
+       struct ia64_sal_retval ret_stuff;
+       uint64_t busnum;
+
+       ret_stuff.status = 0;
+       ret_stuff.v0 = 0;
+
+       busnum = soft->pbi_buscommon.bs_persist_busnum;
+       SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_DISABLE,
+                       (u64) busnum, (u64) device, (u64) action,
+                       (u64) resp, 0, 0, 0);
+
+       return (int)ret_stuff.v0;
+}
 
 static int sal_pcibr_error_interrupt(struct pcibus_info *soft)
 {
@@ -188,3 +221,6 @@ pcibr_init_provider(void)
 
        return 0;
 }
+
+EXPORT_SYMBOL_GPL(sal_pcibr_slot_enable);
+EXPORT_SYMBOL_GPL(sal_pcibr_slot_disable);
index 865c11c3b50a06cbcd31d39b1bf152bfe12e8606..21426d02fbe6a84fa818535600d145ea850e8c1c 100644 (file)
@@ -6,13 +6,13 @@
  * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved.
  */
 
-#include <linux/types.h>
 #include <linux/interrupt.h>
+#include <linux/types.h>
+#include <asm/sn/pcibr_provider.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/pcidev.h>
-#include "pci/tiocp.h"
-#include "pci/pic.h"
-#include "pci/pcibr_provider.h"
+#include <asm/sn/pic.h>
+#include <asm/sn/tiocp.h>
 
 union br_ptr {
        struct tiocp tio;
index 05aa8c2fe9bbef0f129681388e92ea97cf6c282a..51cc4e63092cca945ea64e1d9dccde352555dda9 100644 (file)
@@ -589,8 +589,7 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft)
 
        /* sanity check prom rev */
 
-       if (sn_sal_rev_major() < 4 ||
-           (sn_sal_rev_major() == 4 && sn_sal_rev_minor() < 6)) {
+       if (sn_sal_rev() < 0x0406) {
                printk
                    (KERN_ERR "%s:  SGI prom rev 4.06 or greater required "
                     "for tioca support\n", __FUNCTION__);
index b014e2c1e524973a58f8adf7ecff122966446787..a146b24a556b1aec6074728232347e9d79932bfc 100644 (file)
@@ -3,8 +3,8 @@
  *
  *  Setup routines for Renesas M32700UT Board
  *
- *  Copyright (c) 2002         Hiroyuki Kondo, Hirokazu Takata,
- *                      Hitoshi Yamamoto, Takeo Takahashi
+ *  Copyright (c) 2002-2005  Hiroyuki Kondo, Hirokazu Takata,
+ *                           Hitoshi Yamamoto, Takeo Takahashi
  *
  *  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
@@ -435,7 +435,7 @@ void __init init_IRQ(void)
        icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
        enable_m32700ut_irq(M32R_IRQ_INT2);
 
-//#if defined(CONFIG_VIDEO_M32R_AR)
+#if defined(CONFIG_VIDEO_M32R_AR)
        /*
         * INT3# is used for AR
         */
@@ -445,9 +445,11 @@ void __init init_IRQ(void)
        irq_desc[M32R_IRQ_INT3].depth = 1;
        icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
        disable_m32700ut_irq(M32R_IRQ_INT3);
-//#endif       /* CONFIG_VIDEO_M32R_AR */
+#endif /* CONFIG_VIDEO_M32R_AR */
 }
 
+#if defined(CONFIG_SMC91X)
+
 #define LAN_IOSTART     0x300
 #define LAN_IOEND       0x320
 static struct resource smc91x_resources[] = {
@@ -469,10 +471,55 @@ static struct platform_device smc91x_device = {
        .num_resources  = ARRAY_SIZE(smc91x_resources),
        .resource       = smc91x_resources,
 };
+#endif
+
+#if defined(CONFIG_FB_S1D13XXX)
+
+#include <video/s1d13xxxfb.h>
+#include <asm/s1d13806.h>
+
+static struct s1d13xxxfb_pdata s1d13xxxfb_data = {
+       .initregs               = s1d13xxxfb_initregs,
+       .initregssize           = ARRAY_SIZE(s1d13xxxfb_initregs),
+       .platform_init_video    = NULL,
+#ifdef CONFIG_PM
+       .platform_suspend_video = NULL,
+       .platform_resume_video  = NULL,
+#endif
+};
+
+static struct resource s1d13xxxfb_resources[] = {
+       [0] = {
+               .start  = 0x10600000UL,
+               .end    = 0x1073FFFFUL,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 0x10400000UL,
+               .end    = 0x104001FFUL,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device s1d13xxxfb_device = {
+       .name           = S1D_DEVICENAME,
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &s1d13xxxfb_data,
+       },
+       .num_resources  = ARRAY_SIZE(s1d13xxxfb_resources),
+       .resource       = s1d13xxxfb_resources,
+};
+#endif
 
 static int __init platform_init(void)
 {
+#if defined(CONFIG_SMC91X)
        platform_device_register(&smc91x_device);
+#endif
+#if defined(CONFIG_FB_S1D13XXX)
+       platform_device_register(&s1d13xxxfb_device);
+#endif
        return 0;
 }
 arch_initcall(platform_init);
index aaf8e569b930267a45b4603fc351d58daae9f11e..4e709809efc5f98ec1a04771a265dd33d2b5ea6d 100644 (file)
@@ -3,14 +3,15 @@
  *
  *  Setup routines for Renesas MAPPI Board
  *
- *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
- *                            Hitoshi Yamamoto
+ *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata,
+ *                           Hitoshi Yamamoto
  */
 
 #include <linux/config.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/device.h>
 
 #include <asm/system.h>
 #include <asm/m32r.h>
@@ -158,3 +159,49 @@ void __init init_IRQ(void)
        disable_mappi_irq(M32R_IRQ_INT2);
 #endif /* CONFIG_M32RPCC */
 }
+
+#if defined(CONFIG_FB_S1D13XXX)
+
+#include <video/s1d13xxxfb.h>
+#include <asm/s1d13806.h>
+
+static struct s1d13xxxfb_pdata s1d13xxxfb_data = {
+       .initregs               = s1d13xxxfb_initregs,
+       .initregssize           = ARRAY_SIZE(s1d13xxxfb_initregs),
+       .platform_init_video    = NULL,
+#ifdef CONFIG_PM
+       .platform_suspend_video = NULL,
+       .platform_resume_video  = NULL,
+#endif
+};
+
+static struct resource s1d13xxxfb_resources[] = {
+       [0] = {
+               .start  = 0x10200000UL,
+               .end    = 0x1033FFFFUL,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 0x10000000UL,
+               .end    = 0x100001FFUL,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device s1d13xxxfb_device = {
+       .name           = S1D_DEVICENAME,
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &s1d13xxxfb_data,
+       },
+       .num_resources  = ARRAY_SIZE(s1d13xxxfb_resources),
+       .resource       = s1d13xxxfb_resources,
+};
+
+static int __init platform_init(void)
+{
+       platform_device_register(&s1d13xxxfb_device);
+       return 0;
+}
+arch_initcall(platform_init);
+#endif
index 38d5e9a4142782ac201748ea4c3a0b52fae2865d..a1d801598aa44b8a449196025fb3d551e55a3a9a 100644 (file)
@@ -3,8 +3,8 @@
  *
  *  Setup routines for Renesas MAPPI-II(M3A-ZA36) Board
  *
- *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
- *                            Hitoshi Yamamoto, Mamoru Sakugawa
+ *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata,
+ *                           Hitoshi Yamamoto, Mamoru Sakugawa
  */
 
 #include <linux/config.h>
index 3d60a85aaec5209cf56c42bb1ef0911506caa9c1..a76412e883e8cecfb79396fe9ab26e6e0d6d7175 100644 (file)
@@ -3,8 +3,8 @@
  *
  *  Setup routines for Renesas MAPPI-III(M3A-2170) Board
  *
- *  Copyright (c) 2001-2005   Hiroyuki Kondo, Hirokazu Takata,
- *                            Hitoshi Yamamoto, Mamoru Sakugawa
+ *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata,
+ *                           Hitoshi Yamamoto, Mamoru Sakugawa
  */
 
 #include <linux/config.h>
@@ -178,6 +178,8 @@ void __init init_IRQ(void)
 #endif /* CONFIG_M32R_CFC */
 }
 
+#if defined(CONFIG_SMC91X)
+
 #define LAN_IOSTART     0x300
 #define LAN_IOEND       0x320
 static struct resource smc91x_resources[] = {
@@ -200,9 +202,55 @@ static struct platform_device smc91x_device = {
        .resource       = smc91x_resources,
 };
 
+#endif
+
+#if defined(CONFIG_FB_S1D13XXX)
+
+#include <video/s1d13xxxfb.h>
+#include <asm/s1d13806.h>
+
+static struct s1d13xxxfb_pdata s1d13xxxfb_data = {
+       .initregs               = s1d13xxxfb_initregs,
+       .initregssize           = ARRAY_SIZE(s1d13xxxfb_initregs),
+       .platform_init_video    = NULL,
+#ifdef CONFIG_PM
+       .platform_suspend_video = NULL,
+       .platform_resume_video  = NULL,
+#endif
+};
+
+static struct resource s1d13xxxfb_resources[] = {
+       [0] = {
+               .start  = 0x1d600000UL,
+               .end    = 0x1d73FFFFUL,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 0x1d400000UL,
+               .end    = 0x1d4001FFUL,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device s1d13xxxfb_device = {
+       .name           = S1D_DEVICENAME,
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &s1d13xxxfb_data,
+       },
+       .num_resources  = ARRAY_SIZE(s1d13xxxfb_resources),
+       .resource       = s1d13xxxfb_resources,
+};
+#endif
+
 static int __init platform_init(void)
 {
+#if defined(CONFIG_SMC91X)
        platform_device_register(&smc91x_device);
+#endif
+#if defined(CONFIG_FB_S1D13XXX)
+       platform_device_register(&s1d13xxxfb_device);
+#endif
        return 0;
 }
 arch_initcall(platform_init);
index d656640badc98f091bedb9b29004903fb445cb9d..45add5b76f194de4bee539c70bfb1ec17379f91c 100644 (file)
@@ -3,8 +3,8 @@
  *
  *  Setup routines for OAKS32R Board
  *
- *  Copyright (c) 2002-200  Hiroyuki Kondo, Hirokazu Takata,
- *                            Hitoshi Yamamoto, Mamoru Sakugawa
+ *  Copyright (c) 2002-2005  Hiroyuki Kondo, Hirokazu Takata,
+ *                           Hitoshi Yamamoto, Mamoru Sakugawa
  */
 
 #include <linux/config.h>
@@ -139,5 +139,4 @@ void __init init_IRQ(void)
        icu_data[M32R_IRQ_SIO1_S].icucr = 0;
        disable_oaks32r_irq(M32R_IRQ_SIO1_S);
 #endif /* CONFIG_SERIAL_M32R_SIO */
-
 }
index 86f4cf2a86c3ba6b4eb25c81aad7983aea924e0f..f0301f58bcce31e54e5150141af1d1c1aa9f37f5 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Setup routines for Renesas OPSPUT Board
  *
- *  Copyright (c) 2002-2004
+ *  Copyright (c) 2002-2005
  *     Hiroyuki Kondo, Hirokazu Takata,
  *      Hitoshi Yamamoto, Takeo Takahashi, Mamoru Sakugawa
  *
@@ -439,7 +439,7 @@ void __init init_IRQ(void)
        icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
        enable_opsput_irq(M32R_IRQ_INT2);
 
-//#if defined(CONFIG_VIDEO_M32R_AR)
+#if defined(CONFIG_VIDEO_M32R_AR)
        /*
         * INT3# is used for AR
         */
@@ -449,9 +449,11 @@ void __init init_IRQ(void)
        irq_desc[M32R_IRQ_INT3].depth = 1;
        icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
        disable_opsput_irq(M32R_IRQ_INT3);
-//#endif       /* CONFIG_VIDEO_M32R_AR */
+#endif /* CONFIG_VIDEO_M32R_AR */
 }
 
+#if defined(CONFIG_SMC91X)
+
 #define LAN_IOSTART     0x300
 #define LAN_IOEND       0x320
 static struct resource smc91x_resources[] = {
@@ -473,10 +475,55 @@ static struct platform_device smc91x_device = {
        .num_resources  = ARRAY_SIZE(smc91x_resources),
        .resource       = smc91x_resources,
 };
+#endif
+
+#if defined(CONFIG_FB_S1D13XXX)
+
+#include <video/s1d13xxxfb.h>
+#include <asm/s1d13806.h>
+
+static struct s1d13xxxfb_pdata s1d13xxxfb_data = {
+       .initregs               = s1d13xxxfb_initregs,
+       .initregssize           = ARRAY_SIZE(s1d13xxxfb_initregs),
+       .platform_init_video    = NULL,
+#ifdef CONFIG_PM
+       .platform_suspend_video = NULL,
+       .platform_resume_video  = NULL,
+#endif
+};
+
+static struct resource s1d13xxxfb_resources[] = {
+       [0] = {
+               .start  = 0x10600000UL,
+               .end    = 0x1073FFFFUL,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 0x10400000UL,
+               .end    = 0x104001FFUL,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device s1d13xxxfb_device = {
+       .name           = S1D_DEVICENAME,
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &s1d13xxxfb_data,
+       },
+       .num_resources  = ARRAY_SIZE(s1d13xxxfb_resources),
+       .resource       = s1d13xxxfb_resources,
+};
+#endif
 
 static int __init platform_init(void)
 {
+#if defined(CONFIG_SMC91X)
        platform_device_register(&smc91x_device);
+#endif
+#if defined(CONFIG_FB_S1D13XXX)
+       platform_device_register(&s1d13xxxfb_device);
+#endif
        return 0;
 }
 arch_initcall(platform_init);
index 5fdd4f607a40f23b25e441a9b9140c22364fa323..c0605244edda159d58b2afc5e66013d0a21a34d6 100644 (file)
@@ -452,7 +452,7 @@ static u32 __pmac read_gpio(struct device_node *np)
        return offset;
 }
 
-static int __pmac pmac_cpufreq_suspend(struct cpufreq_policy *policy, u32 state)
+static int __pmac pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg)
 {
        /* Ok, this could be made a bit smarter, but let's be robust for now. We
         * always force a speed change to high speed before sleep, to make sure
index 1d162c7c59dfb5164bbb58c9fe950c2cd7f83508..8d4c46f6f0b62ef8bb9f1d5e085f7f74f9e5cf99 100644 (file)
@@ -49,160 +49,219 @@ extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec);
 #endif
 
 struct cpu_spec        cpu_specs[] = {
-    {  /* Power3 */
-           0xffff0000, 0x00400000, "POWER3 (630)",
-           CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-                   CPU_FTR_IABR | CPU_FTR_PMC8,
-           COMMON_USER_PPC64,
-           128, 128,
-           __setup_cpu_power3,
-           COMMON_PPC64_FW
-    },
-    {  /* Power3+ */
-           0xffff0000, 0x00410000, "POWER3 (630+)",
-           CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-                   CPU_FTR_IABR | CPU_FTR_PMC8,
-           COMMON_USER_PPC64,
-           128, 128,
-           __setup_cpu_power3,
-           COMMON_PPC64_FW
-    },
-    {  /* Northstar */
-           0xffff0000, 0x00330000, "RS64-II (northstar)",
-           CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-                   CPU_FTR_IABR | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
-           COMMON_USER_PPC64,
-           128, 128,
-           __setup_cpu_power3,
-           COMMON_PPC64_FW
-    },
-    {  /* Pulsar */
-           0xffff0000, 0x00340000, "RS64-III (pulsar)",
-           CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-                   CPU_FTR_IABR | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
-           COMMON_USER_PPC64,
-           128, 128,
-           __setup_cpu_power3,
-           COMMON_PPC64_FW
-    },
-    {  /* I-star */
-           0xffff0000, 0x00360000, "RS64-III (icestar)",
-           CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-                   CPU_FTR_IABR | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
-           COMMON_USER_PPC64,
-           128, 128,
-           __setup_cpu_power3,
-           COMMON_PPC64_FW
-    },
-    {  /* S-star */
-           0xffff0000, 0x00370000, "RS64-IV (sstar)",
-           CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-                   CPU_FTR_IABR | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
-           COMMON_USER_PPC64,
-           128, 128,
-           __setup_cpu_power3,
-           COMMON_PPC64_FW
-    },
-    {  /* Power4 */
-           0xffff0000, 0x00350000, "POWER4 (gp)",
-           CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-                   CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
-           COMMON_USER_PPC64,
-           128, 128,
-           __setup_cpu_power4,
-           COMMON_PPC64_FW
-    },
-    {  /* Power4+ */
-           0xffff0000, 0x00380000, "POWER4+ (gq)",
-           CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-                   CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
-           COMMON_USER_PPC64,
-           128, 128,
-           __setup_cpu_power4,
-           COMMON_PPC64_FW
-    },
-    {  /* PPC970 */
-           0xffff0000, 0x00390000, "PPC970",
-           CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-                   CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
-                   CPU_FTR_CAN_NAP | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
-           COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP,
-           128, 128,
-           __setup_cpu_ppc970,
-           COMMON_PPC64_FW
-    },
-    {  /* PPC970FX */
-           0xffff0000, 0x003c0000, "PPC970FX",
-           CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-                   CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
-                   CPU_FTR_CAN_NAP | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
-           COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP,
-           128, 128,
-           __setup_cpu_ppc970,
-           COMMON_PPC64_FW
-    },
-    {  /* Power5 */
-           0xffff0000, 0x003a0000, "POWER5 (gr)",
-           CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-                   CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT |
-                   CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE |
-                   CPU_FTR_MMCRA_SIHV,
-           COMMON_USER_PPC64,
-           128, 128,
-           __setup_cpu_power4,
-           COMMON_PPC64_FW
-    },
-    {  /* Power5 */
-           0xffff0000, 0x003b0000, "POWER5 (gs)",
-           CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-                   CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT |
-                   CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE |
-                   CPU_FTR_MMCRA_SIHV,
-           COMMON_USER_PPC64,
-           128, 128,
-           __setup_cpu_power4,
-           COMMON_PPC64_FW
-    },
-    {  /* BE DD1.x  */
-           0xffff0000, 0x00700000, "Broadband Engine",
-           CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-                   CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
-                   CPU_FTR_SMT,
-           COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP,
-           128, 128,
-           __setup_cpu_be,
-           COMMON_PPC64_FW
-    },
-    {  /* default match */
-           0x00000000, 0x00000000, "POWER4 (compatible)",
-           CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-                   CPU_FTR_PPCAS_ARCH_V2,
-           COMMON_USER_PPC64,
-           128, 128,
-           __setup_cpu_power4,
-           COMMON_PPC64_FW
-    }
+       {       /* Power3 */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x00400000,
+               .cpu_name               = "POWER3 (630)",
+               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+                       CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
+                       CPU_FTR_PMC8,
+               .cpu_user_features = COMMON_USER_PPC64,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .cpu_setup              = __setup_cpu_power3,
+               .firmware_features      = COMMON_PPC64_FW,
+       },
+       {       /* Power3+ */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x00410000,
+               .cpu_name               = "POWER3 (630+)",
+               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+                       CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
+                       CPU_FTR_PMC8,
+               .cpu_user_features      = COMMON_USER_PPC64,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .cpu_setup              = __setup_cpu_power3,
+               .firmware_features      = COMMON_PPC64_FW,
+       },
+       {       /* Northstar */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x00330000,
+               .cpu_name               = "RS64-II (northstar)",
+               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+                       CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
+                       CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL,
+               .cpu_user_features      = COMMON_USER_PPC64,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .cpu_setup              = __setup_cpu_power3,
+               .firmware_features      = COMMON_PPC64_FW,
+       },
+       {       /* Pulsar */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x00340000,
+               .cpu_name               = "RS64-III (pulsar)",
+               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+                       CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
+                       CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL,
+               .cpu_user_features      = COMMON_USER_PPC64,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .cpu_setup              = __setup_cpu_power3,
+               .firmware_features      = COMMON_PPC64_FW,
+       },
+       {       /* I-star */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x00360000,
+               .cpu_name               = "RS64-III (icestar)",
+               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+                       CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
+                       CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL,
+               .cpu_user_features      = COMMON_USER_PPC64,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .cpu_setup              = __setup_cpu_power3,
+               .firmware_features      = COMMON_PPC64_FW,
+       },
+       {       /* S-star */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x00370000,
+               .cpu_name               = "RS64-IV (sstar)",
+               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+                       CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_IABR |
+                       CPU_FTR_PMC8 | CPU_FTR_MMCRA | CPU_FTR_CTRL,
+               .cpu_user_features      = COMMON_USER_PPC64,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .cpu_setup              = __setup_cpu_power3,
+               .firmware_features      = COMMON_PPC64_FW,
+       },
+       {       /* Power4 */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x00350000,
+               .cpu_name               = "POWER4 (gp)",
+               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+                       CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+                       CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
+               .cpu_user_features      = COMMON_USER_PPC64,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .cpu_setup              = __setup_cpu_power4,
+               .firmware_features      = COMMON_PPC64_FW,
+       },
+       {       /* Power4+ */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x00380000,
+               .cpu_name               = "POWER4+ (gq)",
+               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+                       CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+                       CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
+               .cpu_user_features      = COMMON_USER_PPC64,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .cpu_setup              = __setup_cpu_power4,
+               .firmware_features      = COMMON_PPC64_FW,
+       },
+       {       /* PPC970 */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x00390000,
+               .cpu_name               = "PPC970",
+               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+                       CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+                       CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
+                       CPU_FTR_CAN_NAP | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
+               .cpu_user_features      = COMMON_USER_PPC64 |
+                       PPC_FEATURE_HAS_ALTIVEC_COMP,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .cpu_setup              = __setup_cpu_ppc970,
+               .firmware_features      = COMMON_PPC64_FW,
+       },
+       {       /* PPC970FX */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x003c0000,
+               .cpu_name               = "PPC970FX",
+               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+                       CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+                       CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
+                       CPU_FTR_CAN_NAP | CPU_FTR_PMC8 | CPU_FTR_MMCRA,
+               .cpu_user_features      = COMMON_USER_PPC64 |
+                       PPC_FEATURE_HAS_ALTIVEC_COMP,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .cpu_setup              = __setup_cpu_ppc970,
+               .firmware_features      = COMMON_PPC64_FW,
+       },
+       {       /* Power5 */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x003a0000,
+               .cpu_name               = "POWER5 (gr)",
+               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+                       CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+                       CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT |
+                       CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE |
+                       CPU_FTR_MMCRA_SIHV,
+               .cpu_user_features      = COMMON_USER_PPC64,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .cpu_setup              = __setup_cpu_power4,
+               .firmware_features      = COMMON_PPC64_FW,
+       },
+       {       /* Power5 */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x003b0000,
+               .cpu_name               = "POWER5 (gs)",
+               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+                       CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+                       CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA | CPU_FTR_SMT |
+                       CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE |
+                       CPU_FTR_MMCRA_SIHV,
+               .cpu_user_features      = COMMON_USER_PPC64,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .cpu_setup              = __setup_cpu_power4,
+               .firmware_features      = COMMON_PPC64_FW,
+       },
+       {       /* BE DD1.x */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x00700000,
+               .cpu_name               = "Broadband Engine",
+               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+                       CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+                       CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
+                       CPU_FTR_SMT,
+               .cpu_user_features      = COMMON_USER_PPC64 |
+                       PPC_FEATURE_HAS_ALTIVEC_COMP,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .cpu_setup              = __setup_cpu_be,
+               .firmware_features      = COMMON_PPC64_FW,
+       },
+       {       /* default match */
+               .pvr_mask               = 0x00000000,
+               .pvr_value              = 0x00000000,
+               .cpu_name               = "POWER4 (compatible)",
+               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+                       CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+                       CPU_FTR_PPCAS_ARCH_V2,
+               .cpu_user_features      = COMMON_USER_PPC64,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .cpu_setup              = __setup_cpu_power4,
+               .firmware_features      = COMMON_PPC64_FW,
+       }
 };
 
 firmware_feature_t firmware_features_table[FIRMWARE_MAX_FEATURES] = {
-    {FW_FEATURE_PFT,           "hcall-pft"},
-    {FW_FEATURE_TCE,           "hcall-tce"},
-    {FW_FEATURE_SPRG0,         "hcall-sprg0"},
-    {FW_FEATURE_DABR,          "hcall-dabr"},
-    {FW_FEATURE_COPY,          "hcall-copy"},
-    {FW_FEATURE_ASR,           "hcall-asr"},
-    {FW_FEATURE_DEBUG,         "hcall-debug"},
-    {FW_FEATURE_PERF,          "hcall-perf"},
-    {FW_FEATURE_DUMP,          "hcall-dump"},
-    {FW_FEATURE_INTERRUPT,     "hcall-interrupt"},
-    {FW_FEATURE_MIGRATE,       "hcall-migrate"},
-    {FW_FEATURE_PERFMON,       "hcall-perfmon"},
-    {FW_FEATURE_CRQ,           "hcall-crq"},
-    {FW_FEATURE_VIO,           "hcall-vio"},
-    {FW_FEATURE_RDMA,          "hcall-rdma"},
-    {FW_FEATURE_LLAN,          "hcall-lLAN"},
-    {FW_FEATURE_BULK,          "hcall-bulk"},
-    {FW_FEATURE_XDABR,         "hcall-xdabr"},
-    {FW_FEATURE_MULTITCE,      "hcall-multi-tce"},
-    {FW_FEATURE_SPLPAR,                "hcall-splpar"},
+       {FW_FEATURE_PFT,                "hcall-pft"},
+       {FW_FEATURE_TCE,                "hcall-tce"},
+       {FW_FEATURE_SPRG0,              "hcall-sprg0"},
+       {FW_FEATURE_DABR,               "hcall-dabr"},
+       {FW_FEATURE_COPY,               "hcall-copy"},
+       {FW_FEATURE_ASR,                "hcall-asr"},
+       {FW_FEATURE_DEBUG,              "hcall-debug"},
+       {FW_FEATURE_PERF,               "hcall-perf"},
+       {FW_FEATURE_DUMP,               "hcall-dump"},
+       {FW_FEATURE_INTERRUPT,          "hcall-interrupt"},
+       {FW_FEATURE_MIGRATE,            "hcall-migrate"},
+       {FW_FEATURE_PERFMON,            "hcall-perfmon"},
+       {FW_FEATURE_CRQ,                "hcall-crq"},
+       {FW_FEATURE_VIO,                "hcall-vio"},
+       {FW_FEATURE_RDMA,               "hcall-rdma"},
+       {FW_FEATURE_LLAN,               "hcall-lLAN"},
+       {FW_FEATURE_BULK,               "hcall-bulk"},
+       {FW_FEATURE_XDABR,              "hcall-xdabr"},
+       {FW_FEATURE_MULTITCE,           "hcall-multi-tce"},
+       {FW_FEATURE_SPLPAR,             "hcall-splpar"},
 };
index 675c2708588f002758ff747490ec68817cb1d803..93ebcac0d5a25c12a305dd1b2b45866ec6d96f8a 100644 (file)
@@ -308,6 +308,7 @@ exception_marker:
 label##_pSeries:                                       \
        HMT_MEDIUM;                                     \
        mtspr   SPRG1,r13;              /* save r13 */  \
+       RUNLATCH_ON(r13);                               \
        EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
 
 #define STD_EXCEPTION_ISERIES(n, label, area)          \
@@ -315,6 +316,7 @@ label##_pSeries:                                    \
 label##_iSeries:                                       \
        HMT_MEDIUM;                                     \
        mtspr   SPRG1,r13;              /* save r13 */  \
+       RUNLATCH_ON(r13);                               \
        EXCEPTION_PROLOG_ISERIES_1(area);               \
        EXCEPTION_PROLOG_ISERIES_2;                     \
        b       label##_common
@@ -324,6 +326,7 @@ label##_iSeries:                                    \
 label##_iSeries:                                                       \
        HMT_MEDIUM;                                                     \
        mtspr   SPRG1,r13;              /* save r13 */                  \
+       RUNLATCH_ON(r13);                                               \
        EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN);                         \
        lbz     r10,PACAPROCENABLED(r13);                               \
        cmpwi   0,r10,0;                                                \
@@ -393,6 +396,7 @@ __start_interrupts:
 _machine_check_pSeries:
        HMT_MEDIUM
        mtspr   SPRG1,r13               /* save r13 */
+       RUNLATCH_ON(r13)
        EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
 
        . = 0x300
@@ -419,6 +423,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
 data_access_slb_pSeries:
        HMT_MEDIUM
        mtspr   SPRG1,r13
+       RUNLATCH_ON(r13)
        mfspr   r13,SPRG3               /* get paca address into r13 */
        std     r9,PACA_EXSLB+EX_R9(r13)        /* save r9 - r12 */
        std     r10,PACA_EXSLB+EX_R10(r13)
@@ -439,6 +444,7 @@ data_access_slb_pSeries:
 instruction_access_slb_pSeries:
        HMT_MEDIUM
        mtspr   SPRG1,r13
+       RUNLATCH_ON(r13)
        mfspr   r13,SPRG3               /* get paca address into r13 */
        std     r9,PACA_EXSLB+EX_R9(r13)        /* save r9 - r12 */
        std     r10,PACA_EXSLB+EX_R10(r13)
@@ -464,6 +470,7 @@ instruction_access_slb_pSeries:
        .globl  system_call_pSeries
 system_call_pSeries:
        HMT_MEDIUM
+       RUNLATCH_ON(r9)
        mr      r9,r13
        mfmsr   r10
        mfspr   r13,SPRG3
@@ -707,11 +714,13 @@ fwnmi_data_area:
 system_reset_fwnmi:
        HMT_MEDIUM
        mtspr   SPRG1,r13               /* save r13 */
+       RUNLATCH_ON(r13)
        EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
        .globl machine_check_fwnmi
 machine_check_fwnmi:
        HMT_MEDIUM
        mtspr   SPRG1,r13               /* save r13 */
+       RUNLATCH_ON(r13)
        EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
 
        /*
@@ -848,6 +857,7 @@ unrecov_fer:
        .align  7
        .globl data_access_common
 data_access_common:
+       RUNLATCH_ON(r10)                /* It wont fit in the 0x300 handler */
        mfspr   r10,DAR
        std     r10,PACA_EXGEN+EX_DAR(r13)
        mfspr   r10,DSISR
index c72fb8ffe974a3d42bd6865eeba8fcfacfda6f19..138e128a3886b851d43c50fe1747aaadd6a57172 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/module.h>
 #include <asm/hvcall.h>
 #include <asm/hvconsole.h>
-#include <asm/prom.h>
 
 /**
  * hvc_get_chars - retrieve characters from firmware for denoted vterm adatper
@@ -42,29 +41,14 @@ int hvc_get_chars(uint32_t vtermno, char *buf, int count)
        unsigned long got;
 
        if (plpar_hcall(H_GET_TERM_CHAR, vtermno, 0, 0, 0, &got,
-               (unsigned long *)buf, (unsigned long *)buf+1) == H_Success) {
-               /*
-                * Work around a HV bug where it gives us a null
-                * after every \r.  -- paulus
-                */
-               if (got > 0) {
-                       int i;
-                       for (i = 1; i < got; ++i) {
-                               if (buf[i] == 0 && buf[i-1] == '\r') {
-                                       --got;
-                                       if (i < got)
-                                               memmove(&buf[i], &buf[i+1],
-                                                       got - i);
-                               }
-                       }
-               }
+               (unsigned long *)buf, (unsigned long *)buf+1) == H_Success)
                return got;
-       }
        return 0;
 }
 
 EXPORT_SYMBOL(hvc_get_chars);
 
+
 /**
  * hvc_put_chars: send characters to firmware for denoted vterm adapter
  * @vtermno: The vtermno or unit_address of the adapter from which the data
@@ -88,34 +72,3 @@ int hvc_put_chars(uint32_t vtermno, const char *buf, int count)
 }
 
 EXPORT_SYMBOL(hvc_put_chars);
-
-/*
- * We hope/assume that the first vty found corresponds to the first console
- * device.
- */
-int hvc_find_vtys(void)
-{
-       struct device_node *vty;
-       int num_found = 0;
-
-       for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL;
-                       vty = of_find_node_by_name(vty, "vty")) {
-               uint32_t *vtermno;
-
-               /* We have statically defined space for only a certain number of
-                * console adapters. */
-               if (num_found >= MAX_NR_HVC_CONSOLES)
-                       break;
-
-               vtermno = (uint32_t *)get_property(vty, "reg", NULL);
-               if (!vtermno)
-                       continue;
-
-               if (device_is_compatible(vty, "hvterm1")) {
-                       hvc_instantiate(*vtermno, num_found);
-                       ++num_found;
-               }
-       }
-
-       return num_found;
-}
index b3f770f6d4022ef4e0484ccb4c3c26ececdd7601..077c82fc9f3a9d2f2d20c322c810daa38d464615 100644 (file)
@@ -834,6 +834,92 @@ static int __init iSeries_src_init(void)
 
 late_initcall(iSeries_src_init);
 
+static inline void process_iSeries_events(void)
+{
+       asm volatile ("li 0,0x5555; sc" : : : "r0", "r3");
+}
+
+static void yield_shared_processor(void)
+{
+       unsigned long tb;
+
+       HvCall_setEnabledInterrupts(HvCall_MaskIPI |
+                                   HvCall_MaskLpEvent |
+                                   HvCall_MaskLpProd |
+                                   HvCall_MaskTimeout);
+
+       tb = get_tb();
+       /* Compute future tb value when yield should expire */
+       HvCall_yieldProcessor(HvCall_YieldTimed, tb+tb_ticks_per_jiffy);
+
+       /*
+        * The decrementer stops during the yield.  Force a fake decrementer
+        * here and let the timer_interrupt code sort out the actual time.
+        */
+       get_paca()->lppaca.int_dword.fields.decr_int = 1;
+       process_iSeries_events();
+}
+
+static int iseries_shared_idle(void)
+{
+       while (1) {
+               while (!need_resched() && !hvlpevent_is_pending()) {
+                       local_irq_disable();
+                       ppc64_runlatch_off();
+
+                       /* Recheck with irqs off */
+                       if (!need_resched() && !hvlpevent_is_pending())
+                               yield_shared_processor();
+
+                       HMT_medium();
+                       local_irq_enable();
+               }
+
+               ppc64_runlatch_on();
+
+               if (hvlpevent_is_pending())
+                       process_iSeries_events();
+
+               schedule();
+       }
+
+       return 0;
+}
+
+static int iseries_dedicated_idle(void)
+{
+       long oldval;
+
+       while (1) {
+               oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
+
+               if (!oldval) {
+                       set_thread_flag(TIF_POLLING_NRFLAG);
+
+                       while (!need_resched()) {
+                               ppc64_runlatch_off();
+                               HMT_low();
+
+                               if (hvlpevent_is_pending()) {
+                                       HMT_medium();
+                                       ppc64_runlatch_on();
+                                       process_iSeries_events();
+                               }
+                       }
+
+                       HMT_medium();
+                       clear_thread_flag(TIF_POLLING_NRFLAG);
+               } else {
+                       set_need_resched();
+               }
+
+               ppc64_runlatch_on();
+               schedule();
+       }
+
+       return 0;
+}
+
 #ifndef CONFIG_PCI
 void __init iSeries_init_IRQ(void) { }
 #endif
@@ -859,5 +945,13 @@ void __init iSeries_early_setup(void)
        ppc_md.get_rtc_time = iSeries_get_rtc_time;
        ppc_md.calibrate_decr = iSeries_calibrate_decr;
        ppc_md.progress = iSeries_progress;
+
+       if (get_paca()->lppaca.shared_proc) {
+               ppc_md.idle_loop = iseries_shared_idle;
+               printk(KERN_INFO "Using shared processor idle loop\n");
+       } else {
+               ppc_md.idle_loop = iseries_dedicated_idle;
+               printk(KERN_INFO "Using dedicated idle loop\n");
+       }
 }
 
index 08952c7e621648e9d8593e395e14de143e674e22..954395d426363ab54c21d4f484b25a91e805abf0 100644 (file)
 #include <linux/kernel.h>
 #include <linux/smp.h>
 #include <linux/cpu.h>
-#include <linux/module.h>
 #include <linux/sysctl.h>
-#include <linux/smp.h>
 
 #include <asm/system.h>
 #include <asm/processor.h>
-#include <asm/mmu.h>
 #include <asm/cputable.h>
 #include <asm/time.h>
-#include <asm/iSeries/HvCall.h>
-#include <asm/iSeries/ItLpQueue.h>
-#include <asm/plpar_wrappers.h>
 #include <asm/systemcfg.h>
+#include <asm/machdep.h>
 
 extern void power4_idle(void);
 
-static int (*idle_loop)(void);
-
-#ifdef CONFIG_PPC_ISERIES
-static unsigned long maxYieldTime = 0;
-static unsigned long minYieldTime = 0xffffffffffffffffUL;
-
-static inline void process_iSeries_events(void)
-{
-       asm volatile ("li 0,0x5555; sc" : : : "r0", "r3");
-}
-
-static void yield_shared_processor(void)
-{
-       unsigned long tb;
-       unsigned long yieldTime;
-
-       HvCall_setEnabledInterrupts(HvCall_MaskIPI |
-                                   HvCall_MaskLpEvent |
-                                   HvCall_MaskLpProd |
-                                   HvCall_MaskTimeout);
-
-       tb = get_tb();
-       /* Compute future tb value when yield should expire */
-       HvCall_yieldProcessor(HvCall_YieldTimed, tb+tb_ticks_per_jiffy);
-
-       yieldTime = get_tb() - tb;
-       if (yieldTime > maxYieldTime)
-               maxYieldTime = yieldTime;
-
-       if (yieldTime < minYieldTime)
-               minYieldTime = yieldTime;
-       
-       /*
-        * The decrementer stops during the yield.  Force a fake decrementer
-        * here and let the timer_interrupt code sort out the actual time.
-        */
-       get_paca()->lppaca.int_dword.fields.decr_int = 1;
-       process_iSeries_events();
-}
-
-static int iSeries_idle(void)
-{
-       struct paca_struct *lpaca;
-       long oldval;
-
-       /* ensure iSeries run light will be out when idle */
-       ppc64_runlatch_off();
-
-       lpaca = get_paca();
-
-       while (1) {
-               if (lpaca->lppaca.shared_proc) {
-                       if (hvlpevent_is_pending())
-                               process_iSeries_events();
-                       if (!need_resched())
-                               yield_shared_processor();
-               } else {
-                       oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
-
-                       if (!oldval) {
-                               set_thread_flag(TIF_POLLING_NRFLAG);
-
-                               while (!need_resched()) {
-                                       HMT_medium();
-                                       if (hvlpevent_is_pending())
-                                               process_iSeries_events();
-                                       HMT_low();
-                               }
-
-                               HMT_medium();
-                               clear_thread_flag(TIF_POLLING_NRFLAG);
-                       } else {
-                               set_need_resched();
-                       }
-               }
-
-               ppc64_runlatch_on();
-               schedule();
-               ppc64_runlatch_off();
-       }
-
-       return 0;
-}
-
-#else
-
-static int default_idle(void)
+int default_idle(void)
 {
        long oldval;
        unsigned int cpu = smp_processor_id();
@@ -134,7 +43,8 @@ static int default_idle(void)
                        set_thread_flag(TIF_POLLING_NRFLAG);
 
                        while (!need_resched() && !cpu_is_offline(cpu)) {
-                               barrier();
+                               ppc64_runlatch_off();
+
                                /*
                                 * Go into low thread priority and possibly
                                 * low power mode.
@@ -149,6 +59,7 @@ static int default_idle(void)
                        set_need_resched();
                }
 
+               ppc64_runlatch_on();
                schedule();
                if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
                        cpu_die();
@@ -157,127 +68,19 @@ static int default_idle(void)
        return 0;
 }
 
-#ifdef CONFIG_PPC_PSERIES
-
-DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
-
-int dedicated_idle(void)
+int native_idle(void)
 {
-       long oldval;
-       struct paca_struct *lpaca = get_paca(), *ppaca;
-       unsigned long start_snooze;
-       unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
-       unsigned int cpu = smp_processor_id();
-
-       ppaca = &paca[cpu ^ 1];
-
        while (1) {
-               /*
-                * Indicate to the HV that we are idle. Now would be
-                * a good time to find other work to dispatch.
-                */
-               lpaca->lppaca.idle = 1;
-
-               oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
-               if (!oldval) {
-                       set_thread_flag(TIF_POLLING_NRFLAG);
-                       start_snooze = __get_tb() +
-                               *smt_snooze_delay * tb_ticks_per_usec;
-                       while (!need_resched() && !cpu_is_offline(cpu)) {
-                               /*
-                                * Go into low thread priority and possibly
-                                * low power mode.
-                                */
-                               HMT_low();
-                               HMT_very_low();
-
-                               if (*smt_snooze_delay == 0 ||
-                                   __get_tb() < start_snooze)
-                                       continue;
-
-                               HMT_medium();
-
-                               if (!(ppaca->lppaca.idle)) {
-                                       local_irq_disable();
-
-                                       /*
-                                        * We are about to sleep the thread
-                                        * and so wont be polling any
-                                        * more.
-                                        */
-                                       clear_thread_flag(TIF_POLLING_NRFLAG);
-
-                                       /*
-                                        * SMT dynamic mode. Cede will result
-                                        * in this thread going dormant, if the
-                                        * partner thread is still doing work.
-                                        * Thread wakes up if partner goes idle,
-                                        * an interrupt is presented, or a prod
-                                        * occurs.  Returning from the cede
-                                        * enables external interrupts.
-                                        */
-                                       if (!need_resched())
-                                               cede_processor();
-                                       else
-                                               local_irq_enable();
-                               } else {
-                                       /*
-                                        * Give the HV an opportunity at the
-                                        * processor, since we are not doing
-                                        * any work.
-                                        */
-                                       poll_pending();
-                               }
-                       }
-
-                       clear_thread_flag(TIF_POLLING_NRFLAG);
-               } else {
-                       set_need_resched();
-               }
-
-               HMT_medium();
-               lpaca->lppaca.idle = 0;
-               schedule();
-               if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
-                       cpu_die();
-       }
-       return 0;
-}
-
-static int shared_idle(void)
-{
-       struct paca_struct *lpaca = get_paca();
-       unsigned int cpu = smp_processor_id();
-
-       while (1) {
-               /*
-                * Indicate to the HV that we are idle. Now would be
-                * a good time to find other work to dispatch.
-                */
-               lpaca->lppaca.idle = 1;
+               ppc64_runlatch_off();
 
-               while (!need_resched() && !cpu_is_offline(cpu)) {
-                       local_irq_disable();
+               if (!need_resched())
+                       power4_idle();
 
-                       /*
-                        * Yield the processor to the hypervisor.  We return if
-                        * an external interrupt occurs (which are driven prior
-                        * to returning here) or if a prod occurs from another 
-                        * processor. When returning here, external interrupts
-                        * are enabled.
-                        *
-                        * Check need_resched() again with interrupts disabled
-                        * to avoid a race.
-                        */
-                       if (!need_resched())
-                               cede_processor();
-                       else
-                               local_irq_enable();
+               if (need_resched()) {
+                       ppc64_runlatch_on();
+                       schedule();
                }
 
-               HMT_medium();
-               lpaca->lppaca.idle = 0;
-               schedule();
                if (cpu_is_offline(smp_processor_id()) &&
                    system_state == SYSTEM_RUNNING)
                        cpu_die();
@@ -286,29 +89,10 @@ static int shared_idle(void)
        return 0;
 }
 
-#endif /* CONFIG_PPC_PSERIES */
-
-static int native_idle(void)
-{
-       while(1) {
-               /* check CPU type here */
-               if (!need_resched())
-                       power4_idle();
-               if (need_resched())
-                       schedule();
-
-               if (cpu_is_offline(raw_smp_processor_id()) &&
-                   system_state == SYSTEM_RUNNING)
-                       cpu_die();
-       }
-       return 0;
-}
-
-#endif /* CONFIG_PPC_ISERIES */
-
 void cpu_idle(void)
 {
-       idle_loop();
+       BUG_ON(NULL == ppc_md.idle_loop);
+       ppc_md.idle_loop();
 }
 
 int powersave_nap;
@@ -342,42 +126,3 @@ register_powersave_nap_sysctl(void)
 }
 __initcall(register_powersave_nap_sysctl);
 #endif
-
-int idle_setup(void)
-{
-       /*
-        * Move that junk to each platform specific file, eventually define
-        * a pSeries_idle for shared processor stuff
-        */
-#ifdef CONFIG_PPC_ISERIES
-       idle_loop = iSeries_idle;
-       return 1;
-#else
-       idle_loop = default_idle;
-#endif
-#ifdef CONFIG_PPC_PSERIES
-       if (systemcfg->platform & PLATFORM_PSERIES) {
-               if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
-                       if (get_paca()->lppaca.shared_proc) {
-                               printk(KERN_INFO "Using shared processor idle loop\n");
-                               idle_loop = shared_idle;
-                       } else {
-                               printk(KERN_INFO "Using dedicated idle loop\n");
-                               idle_loop = dedicated_idle;
-                       }
-               } else {
-                       printk(KERN_INFO "Using default idle loop\n");
-                       idle_loop = default_idle;
-               }
-       }
-#endif /* CONFIG_PPC_PSERIES */
-#ifndef CONFIG_PPC_ISERIES
-       if (systemcfg->platform == PLATFORM_POWERMAC ||
-           systemcfg->platform == PLATFORM_MAPLE) {
-               printk(KERN_INFO "Using native/NAP idle loop\n");
-               idle_loop = native_idle;
-       }
-#endif /* CONFIG_PPC_ISERIES */
-
-       return 1;
-}
index da8900b51f40af0fef7af27825cc2461e230bd56..bb55b5a569103ca48d7932d753f41ceeb9349f11 100644 (file)
@@ -177,6 +177,8 @@ void __init maple_setup_arch(void)
 #ifdef CONFIG_DUMMY_CONSOLE
        conswitchp = &dummy_con;
 #endif
+
+       printk(KERN_INFO "Using native/NAP idle loop\n");
 }
 
 /* 
@@ -297,4 +299,5 @@ struct machdep_calls __initdata maple_md = {
                .get_rtc_time           = maple_get_rtc_time,
        .calibrate_decr         = generic_calibrate_decr,
        .progress               = maple_progress,
+       .idle_loop              = native_idle,
 };
index f3dea0c5a88c201caefe0bc35f429e7e020885f3..59f4f99738189f5b2078eee806d0b46a06ba78bb 100644 (file)
@@ -1124,9 +1124,11 @@ _GLOBAL(sys_call_table32)
        .llong .compat_sys_mq_getsetattr
        .llong .compat_sys_kexec_load
        .llong .sys32_add_key
-       .llong .sys32_request_key
+       .llong .sys32_request_key       /* 270 */
        .llong .compat_sys_keyctl
        .llong .compat_sys_waitid
+       .llong .sys32_ioprio_set
+       .llong .sys32_ioprio_get
 
        .balign 8
 _GLOBAL(sys_call_table)
@@ -1403,3 +1405,5 @@ _GLOBAL(sys_call_table)
        .llong .sys_request_key         /* 270 */
        .llong .sys_keyctl
        .llong .sys_waitid
+       .llong .sys_ioprio_set
+       .llong .sys_ioprio_get
index 44d9af72d225038da83e43d5f8dab15d4bb055eb..5bec956e44a043775ffbd264807cebced14dfc77 100644 (file)
@@ -19,6 +19,7 @@
 #undef DEBUG
 
 #include <linux/config.h>
+#include <linux/cpu.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -82,6 +83,9 @@ int fwnmi_active;  /* TRUE if an FWNMI handler is present */
 extern void pSeries_system_reset_exception(struct pt_regs *regs);
 extern int pSeries_machine_check_exception(struct pt_regs *regs);
 
+static int pseries_shared_idle(void);
+static int pseries_dedicated_idle(void);
+
 static volatile void __iomem * chrp_int_ack_special;
 struct mpic *pSeries_mpic;
 
@@ -229,6 +233,20 @@ static void __init pSeries_setup_arch(void)
 
        if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
                vpa_init(boot_cpuid);
+
+       /* Choose an idle loop */
+       if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
+               if (get_paca()->lppaca.shared_proc) {
+                       printk(KERN_INFO "Using shared processor idle loop\n");
+                       ppc_md.idle_loop = pseries_shared_idle;
+               } else {
+                       printk(KERN_INFO "Using dedicated idle loop\n");
+                       ppc_md.idle_loop = pseries_dedicated_idle;
+               }
+       } else {
+               printk(KERN_INFO "Using default idle loop\n");
+               ppc_md.idle_loop = default_idle;
+       }
 }
 
 static int __init pSeries_init_panel(void)
@@ -418,6 +436,144 @@ static int __init pSeries_probe(int platform)
        return 1;
 }
 
+DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
+
+static inline void dedicated_idle_sleep(unsigned int cpu)
+{
+       struct paca_struct *ppaca = &paca[cpu ^ 1];
+
+       /* Only sleep if the other thread is not idle */
+       if (!(ppaca->lppaca.idle)) {
+               local_irq_disable();
+
+               /*
+                * We are about to sleep the thread and so wont be polling any
+                * more.
+                */
+               clear_thread_flag(TIF_POLLING_NRFLAG);
+
+               /*
+                * SMT dynamic mode. Cede will result in this thread going
+                * dormant, if the partner thread is still doing work.  Thread
+                * wakes up if partner goes idle, an interrupt is presented, or
+                * a prod occurs.  Returning from the cede enables external
+                * interrupts.
+                */
+               if (!need_resched())
+                       cede_processor();
+               else
+                       local_irq_enable();
+       } else {
+               /*
+                * Give the HV an opportunity at the processor, since we are
+                * not doing any work.
+                */
+               poll_pending();
+       }
+}
+
+static int pseries_dedicated_idle(void)
+{
+       long oldval;
+       struct paca_struct *lpaca = get_paca();
+       unsigned int cpu = smp_processor_id();
+       unsigned long start_snooze;
+       unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
+
+       while (1) {
+               /*
+                * Indicate to the HV that we are idle. Now would be
+                * a good time to find other work to dispatch.
+                */
+               lpaca->lppaca.idle = 1;
+
+               oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
+               if (!oldval) {
+                       set_thread_flag(TIF_POLLING_NRFLAG);
+
+                       start_snooze = __get_tb() +
+                               *smt_snooze_delay * tb_ticks_per_usec;
+
+                       while (!need_resched() && !cpu_is_offline(cpu)) {
+                               ppc64_runlatch_off();
+
+                               /*
+                                * Go into low thread priority and possibly
+                                * low power mode.
+                                */
+                               HMT_low();
+                               HMT_very_low();
+
+                               if (*smt_snooze_delay != 0 &&
+                                   __get_tb() > start_snooze) {
+                                       HMT_medium();
+                                       dedicated_idle_sleep(cpu);
+                               }
+
+                       }
+
+                       HMT_medium();
+                       clear_thread_flag(TIF_POLLING_NRFLAG);
+               } else {
+                       set_need_resched();
+               }
+
+               lpaca->lppaca.idle = 0;
+               ppc64_runlatch_on();
+
+               schedule();
+
+               if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
+                       cpu_die();
+       }
+}
+
+static int pseries_shared_idle(void)
+{
+       struct paca_struct *lpaca = get_paca();
+       unsigned int cpu = smp_processor_id();
+
+       while (1) {
+               /*
+                * Indicate to the HV that we are idle. Now would be
+                * a good time to find other work to dispatch.
+                */
+               lpaca->lppaca.idle = 1;
+
+               while (!need_resched() && !cpu_is_offline(cpu)) {
+                       local_irq_disable();
+                       ppc64_runlatch_off();
+
+                       /*
+                        * Yield the processor to the hypervisor.  We return if
+                        * an external interrupt occurs (which are driven prior
+                        * to returning here) or if a prod occurs from another
+                        * processor. When returning here, external interrupts
+                        * are enabled.
+                        *
+                        * Check need_resched() again with interrupts disabled
+                        * to avoid a race.
+                        */
+                       if (!need_resched())
+                               cede_processor();
+                       else
+                               local_irq_enable();
+
+                       HMT_medium();
+               }
+
+               lpaca->lppaca.idle = 0;
+               ppc64_runlatch_on();
+
+               schedule();
+
+               if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
+                       cpu_die();
+       }
+
+       return 0;
+}
+
 struct machdep_calls __initdata pSeries_md = {
        .probe                  = pSeries_probe,
        .setup_arch             = pSeries_setup_arch,
index 6cf03d387b912a7ef999087796238b86f5812d52..3013cdb5f93314c60f23dae42fea5c66335fc111 100644 (file)
@@ -186,6 +186,8 @@ void __init pmac_setup_arch(void)
 #ifdef CONFIG_DUMMY_CONSOLE
        conswitchp = &dummy_con;
 #endif
+
+       printk(KERN_INFO "Using native/NAP idle loop\n");
 }
 
 #ifdef CONFIG_SCSI
@@ -507,5 +509,6 @@ struct machdep_calls __initdata pmac_md = {
        .calibrate_decr         = pmac_calibrate_decr,
        .feature_call           = pmac_do_feature_call,
        .progress               = pmac_progress,
-       .check_legacy_ioport    = pmac_check_legacy_ioport
+       .check_legacy_ioport    = pmac_check_legacy_ioport,
+       .idle_loop              = native_idle,
 };
index d5e4866e9ac2e22599a5abf7979b99616071c65c..d1b33f0b26cb12261712d00b8e203cf9e7d24129 100644 (file)
@@ -96,7 +96,6 @@ extern void udbg_init_maple_realmode(void);
 extern unsigned long klimit;
 
 extern void mm_init_ppc64(void);
-extern int  idle_setup(void);
 extern void stab_initialize(unsigned long stab);
 extern void htab_initialize(void);
 extern void early_init_devtree(void *flat_dt);
@@ -1081,8 +1080,11 @@ void __init setup_arch(char **cmdline_p)
 
        ppc_md.setup_arch();
 
-       /* Select the correct idle loop for the platform. */
-       idle_setup();
+       /* Use the default idle loop if the platform hasn't provided one. */
+       if (NULL == ppc_md.idle_loop) {
+               ppc_md.idle_loop = default_idle;
+               printk(KERN_INFO "Using default idle loop\n");
+       }
 
        paging_init();
        ppc64_boot_msg(0x15, "Setup Done");
index 118436e8085ae79d31bb8de5ee28b8196c8a645a..206619080e669b42cfdb3003dc85e715bf6e8221 100644 (file)
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
-#include <linux/slab.h>
-#include <linux/uio.h>
-#include <linux/aio.h>
-#include <linux/nfs_fs.h>
-#include <linux/module.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/cache.h>
-#include <linux/nfsd/xdr.h>
-#include <linux/nfsd/syscall.h>
 #include <linux/poll.h>
 #include <linux/personality.h>
 #include <linux/stat.h>
-#include <linux/filter.h>
-#include <linux/highmem.h>
-#include <linux/highuid.h>
 #include <linux/mman.h>
-#include <linux/ipv6.h>
 #include <linux/in.h>
-#include <linux/icmpv6.h>
 #include <linux/syscalls.h>
 #include <linux/unistd.h>
 #include <linux/sysctl.h>
 #include <linux/binfmts.h>
-#include <linux/dnotify.h>
 #include <linux/security.h>
 #include <linux/compat.h>
 #include <linux/ptrace.h>
-#include <linux/aio_abi.h>
 #include <linux/elf.h>
 
-#include <net/scm.h>
-#include <net/sock.h>
-
 #include <asm/ptrace.h>
 #include <asm/types.h>
 #include <asm/ipc.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/semaphore.h>
-#include <asm/ppcdebug.h>
 #include <asm/time.h>
 #include <asm/mmu_context.h>
 #include <asm/systemcfg.h>
@@ -350,8 +329,6 @@ asmlinkage long sys32_adjtimex(struct timex32 __user *utp)
        return ret;
 }
 
-
-/* These are here just in case some old sparc32 binary calls it. */
 asmlinkage long sys32_pause(void)
 {
        current->state = TASK_INTERRUPTIBLE;
@@ -360,8 +337,6 @@ asmlinkage long sys32_pause(void)
        return -ERESTARTNOHAND;
 }
 
-
-
 static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
 {
        long usec;
@@ -847,16 +822,6 @@ asmlinkage long sys32_getpgid(u32 pid)
 }
 
 
-/* Note: it is necessary to treat which and who as unsigned ints,
- * with the corresponding cast to a signed int to insure that the 
- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
- * and the register representation of a signed int (msr in 64-bit mode) is performed.
- */
-asmlinkage long sys32_getpriority(u32 which, u32 who)
-{
-       return sys_getpriority((int)which, (int)who);
-}
-
 
 /* Note: it is necessary to treat pid as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
@@ -1048,6 +1013,11 @@ asmlinkage long sys32_setpgid(u32 pid, u32 pgid)
        return sys_setpgid((int)pid, (int)pgid);
 }
 
+long sys32_getpriority(u32 which, u32 who)
+{
+       /* sign extend which and who */
+       return sys_getpriority((int)which, (int)who);
+}
 
 long sys32_setpriority(u32 which, u32 who, u32 niceval)
 {
@@ -1055,6 +1025,18 @@ long sys32_setpriority(u32 which, u32 who, u32 niceval)
        return sys_setpriority((int)which, (int)who, (int)niceval);
 }
 
+long sys32_ioprio_get(u32 which, u32 who)
+{
+       /* sign extend which and who */
+       return sys_ioprio_get((int)which, (int)who);
+}
+
+long sys32_ioprio_set(u32 which, u32 who, u32 ioprio)
+{
+       /* sign extend which, who and ioprio */
+       return sys_ioprio_set((int)which, (int)who, (int)ioprio);
+}
+
 /* Note: it is necessary to treat newmask as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -1273,8 +1255,6 @@ long ppc32_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low,
                             (u64)len_high << 32 | len_low, advice);
 }
 
-extern asmlinkage long sys_timer_create(clockid_t, sigevent_t __user *, timer_t __user *);
-
 long ppc32_timer_create(clockid_t clock,
                        struct compat_sigevent __user *ev32,
                        timer_t __user *timer_id)
index 2f704a2cafb1a4f5dc9ece21349c6837b0dc8f72..02b8ac4e016883cfc5e4bfa0e151995346d4dc55 100644 (file)
@@ -112,7 +112,6 @@ void ppc64_enable_pmcs(void)
        unsigned long hid0;
 #ifdef CONFIG_PPC_PSERIES
        unsigned long set, reset;
-       int ret;
 #endif /* CONFIG_PPC_PSERIES */
 
        /* Only need to enable them once */
@@ -145,11 +144,7 @@ void ppc64_enable_pmcs(void)
        case PLATFORM_PSERIES_LPAR:
                set = 1UL << 63;
                reset = 0;
-               ret = plpar_hcall_norets(H_PERFMON, set, reset);
-               if (ret)
-                       printk(KERN_ERR "H_PERFMON call on cpu %u "
-                              "returned %d\n",
-                              smp_processor_id(), ret);
+               plpar_hcall_norets(H_PERFMON, set, reset);
                break;
 #endif /* CONFIG_PPC_PSERIES */
 
@@ -161,13 +156,6 @@ void ppc64_enable_pmcs(void)
        /* instruct hypervisor to maintain PMCs */
        if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
                get_paca()->lppaca.pmcregs_in_use = 1;
-
-       /*
-        * On SMT machines we have to set the run latch in the ctrl register
-        * in order to make PMC6 spin.
-        */
-       if (cpu_has_feature(CPU_FTR_SMT))
-               ppc64_runlatch_on();
 #endif /* CONFIG_PPC_PSERIES */
 }
 
index 11290c902ba324ff61688052257e368e061d7a57..6f87a916a394c37f7d63564f8d62edcd7569cc80 100644 (file)
@@ -40,9 +40,9 @@ SECTIONS
   .gcc_except_table    : { *(.gcc_except_table) }
   .fixup               : { *(.fixup) }
 
-  .got ALIGN(4)                : { *(.got.plt) *(.got) }
-
   .dynamic             : { *(.dynamic) }               :text   :dynamic
+  .got : { *(.got) }
+  .plt : { *(.plt) }
 
   _end = .;
   __end = .;
index d78bc13ebbb926dee28741b7fb92f941546c569d..4b13292862422d1108fb57a686f5ff32c2b8626a 100644 (file)
@@ -43,6 +43,8 @@ config SPARC64_PAGE_SIZE_4MB
 
 endchoice
 
+source kernel/Kconfig.hz
+
 source "init/Kconfig"
 
 config SYSVIPC_COMPAT
index b73a3c85877045a3e9c946059cc27b1d5c85414a..538522848ad4ee6661ba545c0232849fc4a5d3ff 100644 (file)
@@ -16,7 +16,7 @@
 #elif PAGE_SHIFT == 19
 #define SZ_BITS                _PAGE_SZ512K
 #elif PAGE_SHIFT == 22
-#define SZ_BITS                _PAGE_SZ4M
+#define SZ_BITS                _PAGE_SZ4MB
 #endif
 
 #define VALID_SZ_BITS  (_PAGE_VALID | SZ_BITS)
index 9469e77303e6c5a60982271d61c5c64580c763e9..6682c7883647d39413b569500dde29510d4bff23 100644 (file)
@@ -128,7 +128,6 @@ config HOSTFS
 
 config HPPFS
        tristate "HoneyPot ProcFS (EXPERIMENTAL)"
-       depends on BROKEN
        help
        hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
        entries to be overridden, removed, or fabricated from the host.
@@ -141,8 +140,9 @@ config HPPFS
        You only need this if you are setting up a UML honeypot.  Otherwise,
        it is safe to say 'N' here.
 
-       If you are actively using it, please ask for it to be fixed. In this
-       moment, it does not work on 2.6 (it works somehow on 2.4).
+       If you are actively using it, please report any problems, since it's
+       getting fixed. In this moment, it is experimental on 2.6 (it works on
+       2.4).
 
 config MCONSOLE
        bool "Management console"
index e41f3748d30f442947cc28ab3f32a9bff10634c6..27c18a8d9d17d72c22d6f1c08ec6001d8bbc9563 100644 (file)
@@ -19,6 +19,18 @@ config 3_LEVEL_PGTABLES
        memory.  All the memory that can't be mapped directly will be treated
        as high memory.
 
+config STUB_CODE
+       hex
+       default 0xbfffe000
+
+config STUB_DATA
+       hex
+       default 0xbffff000
+
+config STUB_START
+       hex
+       default STUB_CODE
+
 config ARCH_HAS_SC_SIGNALS
        bool
        default y
index f162f50f0b179539c5a6f8c0dfa439dc47ebfff5..735a047c890cadeb1784246ab92dca64cc5aa441 100644 (file)
@@ -14,6 +14,18 @@ config 3_LEVEL_PGTABLES
        bool
        default y
 
+config STUB_CODE
+       hex
+       default 0x7fbfffe000
+
+config STUB_DATA
+       hex
+       default 0x7fbffff000
+
+config STUB_START
+       hex
+       default STUB_CODE
+
 config ARCH_HAS_SC_SIGNALS
        bool
        default n
index 29e182d5a83a48508f56bc30e370469af77fe91e..301059062a3e4d5326a1ccd5199b2aa55b597003 100644 (file)
@@ -8,7 +8,7 @@ ifeq ($(CONFIG_MODE_SKAS),y)
   endif
 endif
 
-CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH)
+CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH) $(STUB_CFLAGS)
 ARCH_USER_CFLAGS :=
 
 ifneq ($(CONFIG_GPROF),y)
index 32144562c2798f749640be52f0cf43cedbec671b..d80bd0052e6ba31cec58484bafd5c5ec1ddbbdd0 100644 (file)
@@ -4,7 +4,7 @@
 SUBARCH_LIBS := arch/um/sys-x86_64/
 START := 0x60000000
 
-CFLAGS += -U__$(SUBARCH)__ -fno-builtin
+CFLAGS += -U__$(SUBARCH)__ -fno-builtin $(STUB_CFLAGS)
 ARCH_USER_CFLAGS := -D__x86_64__
 
 ELF_ARCH := i386:x86-64
index 4067c3aa5b608d8733659f2a67ac9c786cdeb3cd..80d30d19d75039e5948df2233cb901407825a100 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3-skas3-v9-pre2
-# Sun Apr 24 19:46:10 2005
+# Linux kernel version: 2.6.12-rc6-mm1
+# Tue Jun 14 18:22:21 2005
 #
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_UML=y
@@ -13,23 +13,32 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
 #
 # UML-specific options
 #
-CONFIG_MODE_TT=y
+# CONFIG_MODE_TT is not set
+# CONFIG_STATIC_LINK is not set
 CONFIG_MODE_SKAS=y
 CONFIG_UML_X86=y
 # CONFIG_64BIT is not set
 CONFIG_TOP_ADDR=0xc0000000
 # CONFIG_3_LEVEL_PGTABLES is not set
+CONFIG_STUB_CODE=0xbfffe000
+CONFIG_STUB_DATA=0xbffff000
+CONFIG_STUB_START=0xbfffe000
 CONFIG_ARCH_HAS_SC_SIGNALS=y
 CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y
-CONFIG_LD_SCRIPT_STATIC=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_LD_SCRIPT_DYN=y
 CONFIG_NET=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
-CONFIG_HOSTFS=y
+# CONFIG_HOSTFS is not set
 CONFIG_MCONSOLE=y
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_HOST_2G_2G is not set
-# CONFIG_SMP is not set
 CONFIG_NEST_LEVEL=0
 CONFIG_KERNEL_HALF_GIGS=1
 # CONFIG_HIGHMEM is not set
@@ -63,6 +72,8 @@ CONFIG_IKCONFIG_PROC=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
@@ -81,6 +92,7 @@ CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
 
@@ -115,6 +127,7 @@ CONFIG_UML_SOUND=m
 CONFIG_SOUND=m
 CONFIG_HOSTAUDIO=m
 CONFIG_UML_RANDOM=y
+# CONFIG_MMAPPER is not set
 
 #
 # Block devices
@@ -176,6 +189,17 @@ CONFIG_INET=y
 # CONFIG_INET_TUNNEL is not set
 CONFIG_IP_TCPDIAG=y
 # CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_WESTWOOD=y
+CONFIG_TCP_CONG_HTCP=y
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
@@ -206,11 +230,15 @@ CONFIG_IP_TCPDIAG=y
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_KGDBOE is not set
 # CONFIG_NETPOLL is not set
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
 CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
@@ -227,6 +255,7 @@ CONFIG_PPP=m
 # CONFIG_PPP_SYNC_TTY is not set
 # CONFIG_PPP_DEFLATE is not set
 # CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
 # CONFIG_PPPOE is not set
 CONFIG_SLIP=m
 # CONFIG_SLIP_COMPRESSED is not set
@@ -240,10 +269,12 @@ CONFIG_SLIP=m
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
+# CONFIG_REISER4_FS is not set
 CONFIG_REISERFS_FS=y
 # CONFIG_REISERFS_CHECK is not set
 # CONFIG_REISERFS_PROC_INFO is not set
@@ -256,6 +287,7 @@ CONFIG_REISERFS_FS=y
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 CONFIG_QUOTA=y
 # CONFIG_QFMT_V1 is not set
 # CONFIG_QFMT_V2 is not set
@@ -264,6 +296,12 @@ CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
 CONFIG_AUTOFS4_FS=m
 
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+# CONFIG_FUSE_FS is not set
+
 #
 # CD-ROM/DVD Filesystems
 #
@@ -291,6 +329,8 @@ CONFIG_TMPFS=y
 # CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -319,6 +359,7 @@ CONFIG_RAMFS=y
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -404,14 +445,15 @@ CONFIG_CRC32=m
 # CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_SLAB=y
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
-CONFIG_PT_PROXY=y
+# CONFIG_GPROF is not set
 # CONFIG_GCOV is not set
 # CONFIG_SYSCALL_DEBUG is not set
index 2bb4c4f5dec4f08cd420caaf19d0bf75dcd77bef..e0fdffa2d542b9a4353bd08912098eb06d17ecf3 100644 (file)
@@ -663,11 +663,15 @@ struct tty_driver *line_register_devfs(struct lines *set,
        return driver;
 }
 
+static spinlock_t winch_handler_lock;
+LIST_HEAD(winch_handlers);
+
 void lines_init(struct line *lines, int nlines)
 {
        struct line *line;
        int i;
 
+       spin_lock_init(&winch_handler_lock);
        for(i = 0; i < nlines; i++){
                line = &lines[i];
                INIT_LIST_HEAD(&line->chan_list);
@@ -724,31 +728,30 @@ irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
        return IRQ_HANDLED;
 }
 
-DECLARE_MUTEX(winch_handler_sem);
-LIST_HEAD(winch_handlers);
-
 void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty)
 {
        struct winch *winch;
 
-       down(&winch_handler_sem);
        winch = kmalloc(sizeof(*winch), GFP_KERNEL);
        if (winch == NULL) {
                printk("register_winch_irq - kmalloc failed\n");
-               goto out;
+               return;
        }
+
        *winch = ((struct winch) { .list        = LIST_HEAD_INIT(winch->list),
                                   .fd          = fd,
                                   .tty_fd      = tty_fd,
                                   .pid         = pid,
                                   .tty         = tty });
+
+       spin_lock(&winch_handler_lock);
        list_add(&winch->list, &winch_handlers);
+       spin_unlock(&winch_handler_lock);
+
        if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
                          SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, 
                          "winch", winch) < 0)
                printk("register_winch_irq - failed to register IRQ\n");
- out:
-       up(&winch_handler_sem);
 }
 
 static void unregister_winch(struct tty_struct *tty)
@@ -756,7 +759,7 @@ static void unregister_winch(struct tty_struct *tty)
        struct list_head *ele;
        struct winch *winch, *found = NULL;
 
-       down(&winch_handler_sem);
+       spin_lock(&winch_handler_lock);
        list_for_each(ele, &winch_handlers){
                winch = list_entry(ele, struct winch, list);
                 if(winch->tty == tty){
@@ -764,20 +767,25 @@ static void unregister_winch(struct tty_struct *tty)
                         break;
                 }
         }
-
         if(found == NULL)
-                goto out;
+               goto err;
+
+       list_del(&winch->list);
+       spin_unlock(&winch_handler_lock);
 
         if(winch->pid != -1)
                 os_kill_process(winch->pid, 1);
 
         free_irq(WINCH_IRQ, winch);
-        list_del(&winch->list);
         kfree(winch);
- out:
-       up(&winch_handler_sem);
+
+       return;
+err:
+       spin_unlock(&winch_handler_lock);
 }
 
+/* XXX: No lock as it's an exitcall... is this valid? Depending on cleanup
+ * order... are we sure that nothing else is done on the list? */
 static void winch_cleanup(void)
 {
        struct list_head *ele;
@@ -786,6 +794,9 @@ static void winch_cleanup(void)
        list_for_each(ele, &winch_handlers){
                winch = list_entry(ele, struct winch, list);
                if(winch->fd != -1){
+                       /* Why is this different from the above free_irq(),
+                        * which deactivates SIGIO? This searches the FD
+                        * somewhere else and removes it from the list... */
                        deactivate_fd(winch->fd, WINCH_IRQ);
                        os_close_file(winch->fd);
                }
index 10c46c38949aaa723021fda57d96271a81b3bd6a..99d3ad4a03e5ab5cd060390cc340b0fdf7f6faa4 100644 (file)
@@ -13,6 +13,7 @@ extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w);
 extern int is_remapped(void *virt);
 extern int physmem_remove_mapping(void *virt);
 extern void physmem_forget_descriptor(int fd);
+extern unsigned long to_phys(void *virt);
 
 #endif
 
index 8744abb5224f13f91ebdd0fcc201628799647712..0a35e6d0baa047b455a050899f408cddf8632d5c 100644 (file)
@@ -14,6 +14,7 @@ extern int restore_fp_registers(int pid, unsigned long *fp_regs);
 extern void save_registers(int pid, union uml_pt_regs *regs);
 extern void restore_registers(int pid, union uml_pt_regs *regs);
 extern void init_registers(int pid);
+extern void get_safe_registers(unsigned long * regs);
 
 #endif
 
index eca8066e7a43b71f5af63a8df1889a027ff5f36b..899aa4b2a78d542888d09a4812fbb13da34035e3 100644 (file)
 #define PT_SYSCALL_ARG3_OFFSET PT_OFFSET(EDX)
 #define PT_SYSCALL_ARG4_OFFSET PT_OFFSET(ESI)
 #define PT_SYSCALL_ARG5_OFFSET PT_OFFSET(EDI)
+#define PT_SYSCALL_ARG6_OFFSET PT_OFFSET(EBP)
 
 #define PT_SYSCALL_RET_OFFSET PT_OFFSET(EAX)
 
+#define REGS_SYSCALL_NR EAX /* This is used before a system call */
+#define REGS_SYSCALL_ARG1 EBX
+#define REGS_SYSCALL_ARG2 ECX
+#define REGS_SYSCALL_ARG3 EDX
+#define REGS_SYSCALL_ARG4 ESI
+#define REGS_SYSCALL_ARG5 EDI
+#define REGS_SYSCALL_ARG6 EBP
+
+#define REGS_IP_INDEX EIP
+#define REGS_SP_INDEX UESP
+
 #define PT_IP_OFFSET PT_OFFSET(EIP)
 #define PT_IP(regs) ((regs)[EIP])
+#define PT_SP_OFFSET PT_OFFSET(UESP)
 #define PT_SP(regs) ((regs)[UESP])
 
 #ifndef FRAME_SIZE
diff --git a/arch/um/include/sysdep-i386/stub.h b/arch/um/include/sysdep-i386/stub.h
new file mode 100644 (file)
index 0000000..d3699fe
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_STUB_H
+#define __SYSDEP_STUB_H
+
+#include <asm/ptrace.h>
+#include <asm/unistd.h>
+
+extern void stub_segv_handler(int sig);
+extern void stub_clone_handler(void);
+
+#define STUB_SYSCALL_RET EAX
+#define STUB_MMAP_NR __NR_mmap2
+#define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT)
+
+static inline long stub_syscall2(long syscall, long arg1, long arg2)
+{
+       long ret;
+
+       __asm__("movl %0, %%ecx; " : : "g" (arg2) : "%ecx");
+       __asm__("movl %0, %%ebx; " : : "g" (arg1) : "%ebx");
+       __asm__("movl %0, %%eax; " : : "g" (syscall) : "%eax");
+       __asm__("int $0x80;" : : : "%eax");
+       __asm__ __volatile__("movl %%eax, %0; " : "=g" (ret) :);
+       return(ret);
+}
+
+static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
+{
+       __asm__("movl %0, %%edx; " : : "g" (arg3) : "%edx");
+       return(stub_syscall2(syscall, arg1, arg2));
+}
+
+static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
+                                long arg4)
+{
+       __asm__("movl %0, %%esi; " : : "g" (arg4) : "%esi");
+       return(stub_syscall3(syscall, arg1, arg2, arg3));
+}
+
+static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3,
+                                long arg4, long arg5, long arg6)
+{
+       long ret;
+       __asm__("movl %0, %%eax; " : : "g" (syscall) : "%eax");
+       __asm__("movl %0, %%ebx; " : : "g" (arg1) : "%ebx");
+       __asm__("movl %0, %%ecx; " : : "g" (arg2) : "%ecx");
+       __asm__("movl %0, %%edx; " : : "g" (arg3) : "%edx");
+       __asm__("movl %0, %%esi; " : : "g" (arg4) : "%esi");
+       __asm__("movl %0, %%edi; " : : "g" (arg5) : "%edi");
+       __asm__ __volatile__("pushl %%ebp ; movl %1, %%ebp; "
+               "int $0x80; popl %%ebp ; "
+               "movl %%eax, %0; " : "=g" (ret) : "g" (arg6) : "%eax");
+       return(ret);
+}
+
+static inline void trap_myself(void)
+{
+       __asm("int3");
+}
+
+#endif
index 31729973fb14d56672503da98069667278b33f07..128faf0273644c4d01197bb76c0b5b9aaedd342c 100644 (file)
 #define PTRACE_OLDSETOPTIONS 21
 #endif
 
+/* These are before the system call, so the the system call number is RAX
+ * rather than ORIG_RAX, and arg4 is R10 rather than RCX
+ */
+#define REGS_SYSCALL_NR PT_INDEX(RAX)
+#define REGS_SYSCALL_ARG1 PT_INDEX(RDI)
+#define REGS_SYSCALL_ARG2 PT_INDEX(RSI)
+#define REGS_SYSCALL_ARG3 PT_INDEX(RDX)
+#define REGS_SYSCALL_ARG4 PT_INDEX(R10)
+#define REGS_SYSCALL_ARG5 PT_INDEX(R8)
+#define REGS_SYSCALL_ARG6 PT_INDEX(R9)
+
+#define REGS_IP_INDEX PT_INDEX(RIP)
+#define REGS_SP_INDEX PT_INDEX(RSP)
+
 #endif
 
 /*
diff --git a/arch/um/include/sysdep-x86_64/stub.h b/arch/um/include/sysdep-x86_64/stub.h
new file mode 100644 (file)
index 0000000..f599058
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SYSDEP_STUB_H
+#define __SYSDEP_STUB_H
+
+#include <asm/ptrace.h>
+#include <asm/unistd.h>
+#include <sysdep/ptrace_user.h>
+
+extern void stub_segv_handler(int sig);
+extern void stub_clone_handler(void);
+
+#define STUB_SYSCALL_RET PT_INDEX(RAX)
+#define STUB_MMAP_NR __NR_mmap
+#define MMAP_OFFSET(o) (o)
+
+static inline long stub_syscall2(long syscall, long arg1, long arg2)
+{
+       long ret;
+
+       __asm__("movq %0, %%rsi; " : : "g" (arg2) : "%rsi");
+       __asm__("movq %0, %%rdi; " : : "g" (arg1) : "%rdi");
+       __asm__("movq %0, %%rax; " : : "g" (syscall) : "%rax");
+       __asm__("syscall;" : : : "%rax", "%r11", "%rcx");
+       __asm__ __volatile__("movq %%rax, %0; " : "=g" (ret) :);
+       return(ret);
+}
+
+static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
+{
+       __asm__("movq %0, %%rdx; " : : "g" (arg3) : "%rdx");
+       return(stub_syscall2(syscall, arg1, arg2));
+}
+
+static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
+                                long arg4)
+{
+       __asm__("movq %0, %%r10; " : : "g" (arg4) : "%r10");
+       return(stub_syscall3(syscall, arg1, arg2, arg3));
+}
+
+static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3,
+                                long arg4, long arg5, long arg6)
+{
+       __asm__("movq %0, %%r9; " : : "g" (arg6) : "%r9");
+       __asm__("movq %0, %%r8; " : : "g" (arg5) : "%r8");
+       return(stub_syscall4(syscall, arg1, arg2, arg3, arg4));
+}
+
+static inline void trap_myself(void)
+{
+       __asm("int3");
+}
+
+#endif
index f64ef77019a33af160e919baee0632a7e0957c4d..17d7ef2141f4a0f6ba1e7188c2253f0ca3f1b945 100644 (file)
@@ -10,6 +10,7 @@ extern void timer(void);
 extern void switch_timers(int to_real);
 extern void idle_sleep(int secs);
 extern void enable_timer(void);
+extern void prepare_timer(void * ptr);
 extern void disable_timer(void);
 extern unsigned long time_lock(void);
 extern void time_unlock(unsigned long);
index da1097285b8ca550e7e524273fcc3d8b189808b3..c6f9628f39bfd159a87df0dd19c07053b536142e 100644 (file)
@@ -37,31 +37,25 @@ struct host_vm_op {
 extern void mprotect_kernel_vm(int w);
 extern void force_flush_all(void);
 extern void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
-                            unsigned long end_addr, int force, int data,
-                            void (*do_ops)(int, struct host_vm_op *, int));
+                             unsigned long end_addr, int force,
+                             void (*do_ops)(union mm_context *,
+                                            struct host_vm_op *, int));
 extern int flush_tlb_kernel_range_common(unsigned long start,
                                         unsigned long end);
 
 extern int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
                    int r, int w, int x, struct host_vm_op *ops, int index,
-                   int last_filled, int data,
-                   void (*do_ops)(int, struct host_vm_op *, int));
+                    int last_filled, union mm_context *mmu,
+                    void (*do_ops)(union mm_context *, struct host_vm_op *,
+                                   int));
 extern int add_munmap(unsigned long addr, unsigned long len,
                      struct host_vm_op *ops, int index, int last_filled,
-                     int data, void (*do_ops)(int, struct host_vm_op *, int));
+                      union mm_context *mmu,
+                      void (*do_ops)(union mm_context *, struct host_vm_op *,
+                                     int));
 extern int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
                        int x, struct host_vm_op *ops, int index,
-                       int last_filled, int data,
-                       void (*do_ops)(int, struct host_vm_op *, int));
+                        int last_filled, union mm_context *mmu,
+                        void (*do_ops)(union mm_context *, struct host_vm_op *,
+                                       int));
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index 715b0838a68c5106cc6462e9df4353e0004d44cf..3942a5f245de6c038b0712155273d5097f4ff815 100644 (file)
@@ -67,6 +67,12 @@ SECTIONS
     *(.stub .text.* .gnu.linkonce.t.*)
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)
+
+    . = ALIGN(4096);
+    __syscall_stub_start = .;
+    *(.__syscall_stub*)
+    __syscall_stub_end = .;
+    . = ALIGN(4096);
   } =0x90909090
   .fini           : {
     KEEP (*(.fini))
index 420e6d51fa0f26aee042e06b66d7d84f29e57d52..a24e3b7f4bf076a7e3e1dd48d6e0ffdc906f7a6c 100644 (file)
@@ -353,6 +353,8 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
 
 #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
 
+extern int __syscall_stub_start, __binary_start;
+
 void setup_physmem(unsigned long start, unsigned long reserve_end,
                   unsigned long len, unsigned long highmem)
 {
@@ -371,6 +373,12 @@ void setup_physmem(unsigned long start, unsigned long reserve_end,
                exit(1);
        }
 
+       /* Special kludge - This page will be mapped in to userspace processes
+        * from physmem_fd, so it needs to be written out there.
+        */
+       os_seek_file(physmem_fd, __pa(&__syscall_stub_start));
+       os_write_file(physmem_fd, &__syscall_stub_start, PAGE_SIZE);
+
        bootmap_size = init_bootmem(pfn, pfn + delta);
        free_bootmem(__pa(reserve_end) + bootmap_size,
                     len - bootmap_size - reserve);
index 1b5ef3e96c7161fad6a8c2c41a927e5d795ee2fa..c45a60e9c92d14237c86a7522efc8d0da0a48292 100644 (file)
@@ -32,6 +32,7 @@
 #include "uml-config.h"
 #include "choose-mode.h"
 #include "mode.h"
+#include "tempfile.h"
 #ifdef UML_CONFIG_MODE_SKAS
 #include "skas.h"
 #include "skas_ptrace.h"
@@ -358,11 +359,16 @@ void forward_pending_sigio(int target)
                kill(target, SIGIO);
 }
 
+int ptrace_faultinfo = 0;
+int proc_mm = 1;
+
+extern void *__syscall_stub_start, __syscall_stub_end;
+
 #ifdef UML_CONFIG_MODE_SKAS
-static inline int check_skas3_ptrace_support(void)
+static inline void check_skas3_ptrace_support(void)
 {
        struct ptrace_faultinfo fi;
-       int pid, n, ret = 1;
+       int pid, n;
 
        printf("Checking for the skas3 patch in the host...");
        pid = start_ptraced_child();
@@ -374,33 +380,31 @@ static inline int check_skas3_ptrace_support(void)
                else {
                        perror("not found");
                }
-               ret = 0;
-       } else {
+       }
+       else {
+               ptrace_faultinfo = 1;
                printf("found\n");
        }
 
        init_registers(pid);
        stop_ptraced_child(pid, 1, 1);
-
-       return(ret);
 }
 
 int can_do_skas(void)
 {
-       int ret = 1;
-
        printf("Checking for /proc/mm...");
        if (os_access("/proc/mm", OS_ACC_W_OK) < 0) {
+               proc_mm = 0;
                printf("not found\n");
-               ret = 0;
                goto out;
-       } else {
+       }
+       else {
                printf("found\n");
        }
 
-       ret = check_skas3_ptrace_support();
 out:
-       return ret;
+       check_skas3_ptrace_support();
+       return 1;
 }
 #else
 int can_do_skas(void)
index ff69c4b312c0c01bf471df0ebc2ee406bb2f7e13..d296d55ade4b99b9fac4488cb76f3420c9929a2a 100644 (file)
@@ -3,11 +3,14 @@
 # Licensed under the GPL
 #
 
-obj-y := exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
+obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
        syscall_kern.o syscall_user.o tlb.o trap_user.o uaccess.o \
 
 subdir- := util
 
-USER_OBJS := process.o
+USER_OBJS := process.o clone.o
 
 include arch/um/scripts/Makefile.rules
+
+# clone.o is in the stub, so it can't be built with profiling
+$(obj)/clone.o : c_flags = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS))
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c
new file mode 100644 (file)
index 0000000..4dc55f1
--- /dev/null
@@ -0,0 +1,44 @@
+#include <sched.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <asm/unistd.h>
+#include <asm/page.h>
+#include "ptrace_user.h"
+#include "skas.h"
+#include "stub-data.h"
+#include "uml-config.h"
+#include "sysdep/stub.h"
+
+/* This is in a separate file because it needs to be compiled with any
+ * extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled
+ */
+void __attribute__ ((__section__ (".__syscall_stub")))
+stub_clone_handler(void)
+{
+       long err;
+       struct stub_data *from = (struct stub_data *) UML_CONFIG_STUB_DATA;
+
+       err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
+                           UML_CONFIG_STUB_DATA + PAGE_SIZE / 2 -
+                           sizeof(void *));
+       if(err != 0)
+               goto out;
+
+       err = stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0);
+       if(err)
+               goto out;
+
+       err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL,
+                           (long) &from->timer, 0);
+       if(err)
+               goto out;
+
+       err = stub_syscall6(STUB_MMAP_NR, UML_CONFIG_STUB_DATA, PAGE_SIZE,
+                           PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED,
+                           from->fd, from->offset);
+ out:
+       /* save current result. Parent: pid; child: retcode of mmap */
+       from->err = err;
+       trap_myself();
+}
index c6b4d5dba7897d5b7a50cde811b8510e81124be8..77ed7bbab219db000243a573a7e5db1e86920322 100644 (file)
@@ -18,7 +18,7 @@
 void flush_thread_skas(void)
 {
        force_flush_all();
-       switch_mm_skas(current->mm->context.skas.mm_fd);
+        switch_mm_skas(&current->mm->context.skas.id);
 }
 
 void start_thread_skas(struct pt_regs *regs, unsigned long eip, 
diff --git a/arch/um/kernel/skas/include/mm_id.h b/arch/um/kernel/skas/include/mm_id.h
new file mode 100644 (file)
index 0000000..48dd098
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2005 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MM_ID_H
+#define __MM_ID_H
+
+struct mm_id {
+       union {
+               int mm_fd;
+               int pid;
+       } u;
+       unsigned long stack;
+};
+
+#endif
index 4cd60d7213f3320bc88f88b58424e43f261b2a67..278b72f1d9adf5a6c3767dd972ae0bf153da9c06 100644 (file)
@@ -6,10 +6,15 @@
 #ifndef __SKAS_MMU_H
 #define __SKAS_MMU_H
 
+#include "mm_id.h"
+
 struct mmu_context_skas {
-       int mm_fd;
+       struct mm_id id;
+        unsigned long last_page_table;
 };
 
+extern void switch_mm_skas(struct mm_id * mm_idp);
+
 #endif
 
 /*
index 96b51dba34718fae36d0946c7dc26814393a88c6..d983ea842547fe807fcd5b8c7bc1ca1d51887400 100644 (file)
@@ -6,9 +6,11 @@
 #ifndef __SKAS_H
 #define __SKAS_H
 
+#include "mm_id.h"
 #include "sysdep/ptrace.h"
 
 extern int userspace_pid[];
+extern int proc_mm, ptrace_faultinfo;
 
 extern void switch_threads(void *me, void *next);
 extern void thread_wait(void *sw, void *fb);
@@ -22,16 +24,18 @@ extern void new_thread_proc(void *stack, void (*handler)(int sig));
 extern void remove_sigstack(void);
 extern void new_thread_handler(int sig);
 extern void handle_syscall(union uml_pt_regs *regs);
-extern void map(int fd, unsigned long virt, unsigned long len, int r, int w,
-               int x, int phys_fd, unsigned long long offset);
-extern int unmap(int fd, void *addr, unsigned long len);
-extern int protect(int fd, unsigned long addr, unsigned long len, 
-                  int r, int w, int x);
+extern int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len,
+               int r, int w, int x, int phys_fd, unsigned long long offset);
+extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len);
+extern int protect(struct mm_id * mm_idp, unsigned long addr,
+                  unsigned long len, int r, int w, int x);
 extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
 extern int new_mm(int from);
-extern void start_userspace(int cpu);
+extern int start_userspace(unsigned long stub_stack);
+extern int copy_context_skas0(unsigned long stack, int pid);
 extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
 extern long execute_syscall_skas(void *r);
+extern unsigned long current_stub_stack(void);
 
 #endif
 
diff --git a/arch/um/kernel/skas/include/stub-data.h b/arch/um/kernel/skas/include/stub-data.h
new file mode 100644 (file)
index 0000000..f6ed92c
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2005 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __STUB_DATA_H
+#define __STUB_DATA_H
+
+#include <sys/time.h>
+
+struct stub_data {
+       long offset;
+       int fd;
+       struct itimerval timer;
+       long err;
+};
+
+#endif
index 438db2f43456b4b646a68be9e63e4e0870a8e122..147466d7ff4f1b90e6273f3b4f99e68f1ffb7c9f 100644 (file)
@@ -5,7 +5,9 @@
 
 #include "linux/config.h"
 #include "linux/mm.h"
+#include "asm/pgtable.h"
 #include "mem_user.h"
+#include "skas.h"
 
 unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, 
                                  unsigned long *task_size_out)
@@ -18,7 +20,9 @@ unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
        *task_size_out = CONFIG_HOST_TASK_SIZE;
 #else
        *host_size_out = top;
-       *task_size_out = top;
+       if (proc_mm && ptrace_faultinfo)
+               *task_size_out = top;
+       else *task_size_out = CONFIG_STUB_START & PGDIR_MASK;
 #endif
        return(((unsigned long) set_task_sizes_skas) & ~0xffffff);
 }
index 1310bf1e88d185dfaeaa75b42386691f3066ba79..b0980ff3bd95bb14279ad94e2581f91ae725d1ac 100644 (file)
  * Licensed under the GPL
  */
 
+#include <signal.h>
 #include <errno.h>
 #include <sys/mman.h>
+#include <sys/wait.h>
+#include <asm/page.h>
+#include <asm/unistd.h>
 #include "mem_user.h"
 #include "mem.h"
+#include "mm_id.h"
 #include "user.h"
 #include "os.h"
 #include "proc_mm.h"
-
-void map(int fd, unsigned long virt, unsigned long len, int r, int w,
-        int x, int phys_fd, unsigned long long offset)
+#include "ptrace_user.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "task.h"
+#include "registers.h"
+#include "uml-config.h"
+#include "sysdep/ptrace.h"
+#include "sysdep/stub.h"
+#include "skas.h"
+
+extern unsigned long syscall_stub, __syscall_stub_start;
+
+extern void wait_stub_done(int pid, int sig, char * fname);
+
+static long run_syscall_stub(struct mm_id * mm_idp, int syscall,
+                             unsigned long *args)
 {
-       struct proc_mm_op map;
-       int prot, n;
-
-       prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 
-               (x ? PROT_EXEC : 0);
-
-       map = ((struct proc_mm_op) { .op        = MM_MMAP,
-                                    .u         = 
-                                    { .mmap    = 
-                                      { .addr          = virt,
-                                        .len           = len,
-                                        .prot          = prot,
-                                        .flags         = MAP_SHARED | 
-                                                         MAP_FIXED,
-                                        .fd            = phys_fd,
-                                        .offset        = offset
-                                      } } } );
-       n = os_write_file(fd, &map, sizeof(map));
-       if(n != sizeof(map)) 
-               printk("map : /proc/mm map failed, err = %d\n", -n);
+        int n, pid = mm_idp->u.pid;
+        unsigned long regs[MAX_REG_NR];
+
+        get_safe_registers(regs);
+        regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
+                ((unsigned long) &syscall_stub -
+                 (unsigned long) &__syscall_stub_start);
+        /* XXX Don't have a define for starting a syscall */
+        regs[REGS_SYSCALL_NR] = syscall;
+        regs[REGS_SYSCALL_ARG1] = args[0];
+        regs[REGS_SYSCALL_ARG2] = args[1];
+        regs[REGS_SYSCALL_ARG3] = args[2];
+        regs[REGS_SYSCALL_ARG4] = args[3];
+        regs[REGS_SYSCALL_ARG5] = args[4];
+        regs[REGS_SYSCALL_ARG6] = args[5];
+        n = ptrace_setregs(pid, regs);
+        if(n < 0){
+                printk("run_syscall_stub : PTRACE_SETREGS failed, "
+                       "errno = %d\n", n);
+                return(n);
+        }
+
+        wait_stub_done(pid, 0, "run_syscall_stub");
+
+        return(*((unsigned long *) mm_idp->stack));
 }
 
-int unmap(int fd, void *addr, unsigned long len)
+int map(struct mm_id *mm_idp, unsigned long virt, unsigned long len,
+        int r, int w, int x, int phys_fd, unsigned long long offset)
 {
-       struct proc_mm_op unmap;
-       int n;
-
-       unmap = ((struct proc_mm_op) { .op      = MM_MUNMAP,
-                                      .u       = 
-                                      { .munmap        = 
-                                        { .addr        = (unsigned long) addr,
-                                          .len         = len } } } );
-       n = os_write_file(fd, &unmap, sizeof(unmap));
-       if(n != sizeof(unmap)) {
-               if(n < 0)
-                       return(n);
-               else if(n > 0)
-                       return(-EIO);
-       }
-
-       return(0);
+        int prot, n;
+
+        prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
+                (x ? PROT_EXEC : 0);
+
+        if(proc_mm){
+                struct proc_mm_op map;
+                int fd = mm_idp->u.mm_fd;
+                map = ((struct proc_mm_op) { .op       = MM_MMAP,
+                                             .u                =
+                                             { .mmap   =
+                                               { .addr = virt,
+                                                 .len  = len,
+                                                 .prot = prot,
+                                                 .flags        = MAP_SHARED |
+                                                 MAP_FIXED,
+                                                 .fd   = phys_fd,
+                                                 .offset= offset
+                                               } } } );
+                n = os_write_file(fd, &map, sizeof(map));
+                if(n != sizeof(map))
+                        printk("map : /proc/mm map failed, err = %d\n", -n);
+        }
+        else {
+                long res;
+                unsigned long args[] = { virt, len, prot,
+                                         MAP_SHARED | MAP_FIXED, phys_fd,
+                                         MMAP_OFFSET(offset) };
+
+                res = run_syscall_stub(mm_idp, STUB_MMAP_NR, args);
+                if((void *) res == MAP_FAILED)
+                        printk("mmap stub failed, errno = %d\n", res);
+        }
+
+        return 0;
 }
 
-int protect(int fd, unsigned long addr, unsigned long len, int r, int w, 
-           int x, int must_succeed)
+int unmap(struct mm_id *mm_idp, void *addr, unsigned long len)
 {
-       struct proc_mm_op protect;
-       int prot, n;
-
-       prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 
-               (x ? PROT_EXEC : 0);
-
-       protect = ((struct proc_mm_op) { .op    = MM_MPROTECT,
-                                      .u       = 
-                                      { .mprotect      = 
-                                        { .addr        = (unsigned long) addr,
-                                          .len         = len,
-                                          .prot        = prot } } } );
-
-       n = os_write_file(fd, &protect, sizeof(protect));
-       if(n != sizeof(protect)) {
-               if(n == 0) return(0);
-
-               if(must_succeed)
-                       panic("protect failed, err = %d", -n);
-
-               return(-EIO);
-       }
+        int n;
+
+        if(proc_mm){
+                struct proc_mm_op unmap;
+                int fd = mm_idp->u.mm_fd;
+                unmap = ((struct proc_mm_op) { .op     = MM_MUNMAP,
+                                               .u      =
+                                               { .munmap       =
+                                                 { .addr       =
+                                                   (unsigned long) addr,
+                                                   .len                = len } } } );
+                n = os_write_file(fd, &unmap, sizeof(unmap));
+                if(n != sizeof(unmap)) {
+                        if(n < 0)
+                                return(n);
+                        else if(n > 0)
+                                return(-EIO);
+                }
+        }
+        else {
+                int res;
+                unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0,
+                                         0 };
+
+                res = run_syscall_stub(mm_idp, __NR_munmap, args);
+                if(res < 0)
+                        printk("munmap stub failed, errno = %d\n", res);
+        }
+
+        return(0);
+}
 
-       return(0);
+int protect(struct mm_id *mm_idp, unsigned long addr, unsigned long len,
+           int r, int w, int x)
+{
+        struct proc_mm_op protect;
+        int prot, n;
+
+        prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
+                (x ? PROT_EXEC : 0);
+
+        if(proc_mm){
+                int fd = mm_idp->u.mm_fd;
+                protect = ((struct proc_mm_op) { .op   = MM_MPROTECT,
+                                                 .u    =
+                                                 { .mprotect   =
+                                                   { .addr     =
+                                                     (unsigned long) addr,
+                                                     .len      = len,
+                                                     .prot     = prot } } } );
+
+                n = os_write_file(fd, &protect, sizeof(protect));
+                if(n != sizeof(protect))
+                        panic("protect failed, err = %d", -n);
+        }
+        else {
+                int res;
+                unsigned long args[] = { addr, len, prot, 0, 0, 0 };
+
+                res = run_syscall_stub(mm_idp, __NR_mprotect, args);
+                if(res < 0)
+                        panic("mprotect stub failed, errno = %d\n", res);
+        }
+
+        return(0);
 }
 
 void before_mem_skas(unsigned long unused)
 {
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index 6cb9a6d028a906cd8f51bd1a900b431de1c393b7..d232daa42c314c009aa5e76141eae73217711641 100644 (file)
  * Licensed under the GPL
  */
 
+#include "linux/config.h"
 #include "linux/sched.h"
 #include "linux/list.h"
 #include "linux/spinlock.h"
 #include "linux/slab.h"
+#include "linux/errno.h"
+#include "linux/mm.h"
 #include "asm/current.h"
 #include "asm/segment.h"
 #include "asm/mmu.h"
+#include "asm/pgalloc.h"
+#include "asm/pgtable.h"
 #include "os.h"
 #include "skas.h"
 
+extern int __syscall_stub_start;
+
+static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
+                        unsigned long kernel)
+{
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte;
+
+       spin_lock(&mm->page_table_lock);
+       pgd = pgd_offset(mm, proc);
+       pud = pud_alloc(mm, pgd, proc);
+       if (!pud)
+               goto out;
+
+       pmd = pmd_alloc(mm, pud, proc);
+       if (!pmd)
+               goto out_pmd;
+
+       pte = pte_alloc_map(mm, pmd, proc);
+       if (!pte)
+               goto out_pte;
+
+       /* There's an interaction between the skas0 stub pages, stack
+        * randomization, and the BUG at the end of exit_mmap.  exit_mmap
+         * checks that the number of page tables freed is the same as had
+         * been allocated.  If the stack is on the last page table page,
+        * then the stack pte page will be freed, and if not, it won't.  To
+        * avoid having to know where the stack is, or if the process mapped
+        * something at the top of its address space for some other reason,
+        * we set TASK_SIZE to end at the start of the last page table.
+        * This keeps exit_mmap off the last page, but introduces a leak
+        * of that page.  So, we hang onto it here and free it in
+        * destroy_context_skas.
+        */
+
+        mm->context.skas.last_page_table = pmd_page_kernel(*pmd);
+
+       *pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
+       *pte = pte_mkexec(*pte);
+       *pte = pte_wrprotect(*pte);
+       spin_unlock(&mm->page_table_lock);
+       return(0);
+
+ out_pmd:
+       pud_free(pud);
+ out_pte:
+       pmd_free(pmd);
+ out:
+       spin_unlock(&mm->page_table_lock);
+       return(-ENOMEM);
+}
+
 int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
 {
-       int from;
+       struct mm_struct *cur_mm = current->mm;
+       struct mm_id *cur_mm_id = &cur_mm->context.skas.id;
+       struct mm_id *mm_id = &mm->context.skas.id;
+       unsigned long stack;
+       int from, ret;
 
-       if((current->mm != NULL) && (current->mm != &init_mm))
-               from = current->mm->context.skas.mm_fd;
-       else from = -1;
+       if(proc_mm){
+               if((cur_mm != NULL) && (cur_mm != &init_mm))
+                       from = cur_mm->context.skas.id.u.mm_fd;
+               else from = -1;
 
-       mm->context.skas.mm_fd = new_mm(from);
-       if(mm->context.skas.mm_fd < 0){
-               printk("init_new_context_skas - new_mm failed, errno = %d\n",
-                      mm->context.skas.mm_fd);
-               return(mm->context.skas.mm_fd);
+               ret = new_mm(from);
+               if(ret < 0){
+                       printk("init_new_context_skas - new_mm failed, "
+                              "errno = %d\n", ret);
+                       return ret;
+               }
+               mm_id->u.mm_fd = ret;
        }
+       else {
+               /* This zeros the entry that pgd_alloc didn't, needed since
+                * we are about to reinitialize it, and want mm.nr_ptes to
+                * be accurate.
+                */
+               mm->pgd[USER_PTRS_PER_PGD] = __pgd(0);
 
-       return(0);
+               ret = init_stub_pte(mm, CONFIG_STUB_CODE,
+                                   (unsigned long) &__syscall_stub_start);
+               if(ret)
+                       goto out;
+
+               ret = -ENOMEM;
+               stack = get_zeroed_page(GFP_KERNEL);
+               if(stack == 0)
+                       goto out;
+               mm_id->stack = stack;
+
+               ret = init_stub_pte(mm, CONFIG_STUB_DATA, stack);
+               if(ret)
+                       goto out_free;
+
+               mm->nr_ptes--;
+
+               if((cur_mm != NULL) && (cur_mm != &init_mm))
+                       mm_id->u.pid = copy_context_skas0(stack,
+                                                         cur_mm_id->u.pid);
+               else mm_id->u.pid = start_userspace(stack);
+       }
+
+       return 0;
+
+ out_free:
+       free_page(mm_id->stack);
+ out:
+       return ret;
 }
 
 void destroy_context_skas(struct mm_struct *mm)
 {
-       os_close_file(mm->context.skas.mm_fd);
-}
+       struct mmu_context_skas *mmu = &mm->context.skas;
 
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+       if(proc_mm)
+               os_close_file(mmu->id.u.mm_fd);
+       else {
+               os_kill_ptraced_process(mmu->id.u.pid, 1);
+               free_page(mmu->id.stack);
+               free_page(mmu->last_page_table);
+       }
+}
index 773cd2b525fc6e45ea58ce891a56f39360dd3355..ba671dab8878485d605e0cc6b4dd1617328cbb54 100644 (file)
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -13,7 +13,9 @@
 #include <sys/wait.h>
 #include <sys/mman.h>
 #include <sys/user.h>
+#include <sys/time.h>
 #include <asm/unistd.h>
+#include <asm/types.h>
 #include "user.h"
 #include "ptrace_user.h"
 #include "time_user.h"
 #include "user_util.h"
 #include "kern_util.h"
 #include "skas.h"
+#include "stub-data.h"
+#include "mm_id.h"
 #include "sysdep/sigcontext.h"
+#include "sysdep/stub.h"
 #include "os.h"
 #include "proc_mm.h"
 #include "skas_ptrace.h"
 #include "chan_user.h"
 #include "signal_user.h"
 #include "registers.h"
+#include "mem.h"
+#include "uml-config.h"
 #include "process.h"
 
 int is_skas_winch(int pid, int fd, void *data)
@@ -39,20 +46,55 @@ int is_skas_winch(int pid, int fd, void *data)
        return(1);
 }
 
-void get_skas_faultinfo(int pid, struct faultinfo * fi)
+void wait_stub_done(int pid, int sig, char * fname)
 {
-       int err;
-
-        err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
-       if(err)
-                panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
-                      "errno = %d\n", errno);
+        int n, status, err;
+
+        do {
+                if ( sig != -1 ) {
+                        err = ptrace(PTRACE_CONT, pid, 0, sig);
+                        if(err)
+                                panic("%s : continue failed, errno = %d\n",
+                                      fname, errno);
+                }
+                sig = 0;
+
+                CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
+        } while((n >= 0) && WIFSTOPPED(status) &&
+                (WSTOPSIG(status) == SIGVTALRM));
+
+        if((n < 0) || !WIFSTOPPED(status) ||
+           (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status != SIGTRAP))){
+                panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
+                      "pid = %d, n = %d, errno = %d, status = 0x%x\n",
+                      fname, pid, n, errno, status);
+        }
+}
 
-        /* Special handling for i386, which has different structs */
-        if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
-                memset((char *)fi + sizeof(struct ptrace_faultinfo), 0,
-                       sizeof(struct faultinfo) -
-                       sizeof(struct ptrace_faultinfo));
+void get_skas_faultinfo(int pid, struct faultinfo * fi)
+{
+        int err;
+
+        if(ptrace_faultinfo){
+                err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
+                if(err)
+                        panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
+                              "errno = %d\n", errno);
+
+                /* Special handling for i386, which has different structs */
+                if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
+                        memset((char *)fi + sizeof(struct ptrace_faultinfo), 0,
+                               sizeof(struct faultinfo) -
+                               sizeof(struct ptrace_faultinfo));
+        }
+        else {
+                wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo");
+
+                /* faultinfo is prepared by the stub-segv-handler at start of
+                 * the stub stack page. We just have to copy it.
+                 */
+                memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
+        }
 }
 
 static void handle_segv(int pid, union uml_pt_regs * regs)
@@ -91,11 +133,56 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu
        handle_syscall(regs);
 }
 
-static int userspace_tramp(void *arg)
+extern int __syscall_stub_start;
+
+static int userspace_tramp(void *stack)
 {
-       init_new_thread_signals(0);
-       enable_timer();
+       void *addr;
+
        ptrace(PTRACE_TRACEME, 0, 0, 0);
+
+       init_new_thread_signals(1);
+       enable_timer();
+
+       if(!proc_mm){
+               /* This has a pte, but it can't be mapped in with the usual
+                * tlb_flush mechanism because this is part of that mechanism
+                */
+               int fd;
+               __u64 offset;
+
+               fd = phys_mapping(to_phys(&__syscall_stub_start), &offset);
+               addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(),
+                             PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
+               if(addr == MAP_FAILED){
+                       printk("mapping mmap stub failed, errno = %d\n",
+                              errno);
+                       exit(1);
+               }
+
+               if(stack != NULL){
+                       fd = phys_mapping(to_phys(stack), &offset);
+                       addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(),
+                                   PROT_READ | PROT_WRITE,
+                                   MAP_FIXED | MAP_SHARED, fd, offset);
+                       if(addr == MAP_FAILED){
+                               printk("mapping segfault stack failed, "
+                                      "errno = %d\n", errno);
+                               exit(1);
+                       }
+               }
+       }
+       if(!ptrace_faultinfo && (stack != NULL)){
+               unsigned long v = UML_CONFIG_STUB_CODE +
+                                 (unsigned long) stub_segv_handler -
+                                 (unsigned long) &__syscall_stub_start;
+
+               set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size());
+               set_handler(SIGSEGV, (void *) v, SA_ONSTACK,
+                           SIGIO, SIGWINCH, SIGALRM, SIGVTALRM,
+                           SIGUSR1, -1);
+       }
+
        os_stop_process(os_getpid());
        return(0);
 }
@@ -105,11 +192,11 @@ static int userspace_tramp(void *arg)
 #define NR_CPUS 1
 int userspace_pid[NR_CPUS];
 
-void start_userspace(int cpu)
+int start_userspace(unsigned long stub_stack)
 {
        void *stack;
        unsigned long sp;
-       int pid, status, n;
+       int pid, status, n, flags;
 
        stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
@@ -117,8 +204,9 @@ void start_userspace(int cpu)
                panic("start_userspace : mmap failed, errno = %d", errno);
        sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
 
-       pid = clone(userspace_tramp, (void *) sp, 
-                   CLONE_FILES | CLONE_VM | SIGCHLD, NULL);
+       flags = CLONE_FILES | SIGCHLD;
+       if(proc_mm) flags |= CLONE_VM;
+       pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
        if(pid < 0)
                panic("start_userspace : clone failed, errno = %d", errno);
 
@@ -140,7 +228,7 @@ void start_userspace(int cpu)
        if(munmap(stack, PAGE_SIZE) < 0)
                panic("start_userspace : munmap failed, errno = %d\n", errno);
 
-       userspace_pid[cpu] = pid;
+       return(pid);
 }
 
 void userspace(union uml_pt_regs *regs)
@@ -174,7 +262,9 @@ void userspace(union uml_pt_regs *regs)
                if(WIFSTOPPED(status)){
                        switch(WSTOPSIG(status)){
                        case SIGSEGV:
-                                handle_segv(pid, regs);
+                                if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo)
+                                        user_signal(SIGSEGV, regs, pid);
+                                else handle_segv(pid, regs);
                                break;
                        case SIGTRAP + 0x80:
                                handle_trap(pid, regs, local_using_sysemu);
@@ -194,6 +284,7 @@ void userspace(union uml_pt_regs *regs)
                                printk("userspace - child stopped with signal "
                                       "%d\n", WSTOPSIG(status));
                        }
+                       pid = userspace_pid[0];
                        interrupt_end();
 
                        /* Avoid -ERESTARTSYS handling in host */
@@ -207,6 +298,67 @@ void userspace(union uml_pt_regs *regs)
 #define INIT_JMP_HALT 3
 #define INIT_JMP_REBOOT 4
 
+
+int copy_context_skas0(unsigned long new_stack, int pid)
+{
+       int err;
+       unsigned long regs[MAX_REG_NR];
+       unsigned long current_stack = current_stub_stack();
+       struct stub_data *data = (struct stub_data *) current_stack;
+       struct stub_data *child_data = (struct stub_data *) new_stack;
+       __u64 new_offset;
+       int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset);
+
+       /* prepare offset and fd of child's stack as argument for parent's
+        * and child's mmap2 calls
+        */
+       *data = ((struct stub_data) { .offset   = MMAP_OFFSET(new_offset),
+                                     .fd       = new_fd,
+                                     .timer    = ((struct itimerval)
+                                                  { { 0, 1000000 / hz() },
+                                                    { 0, 1000000 / hz() }})});
+       get_safe_registers(regs);
+
+       /* Set parent's instruction pointer to start of clone-stub */
+       regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
+                               (unsigned long) stub_clone_handler -
+                               (unsigned long) &__syscall_stub_start;
+       regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -
+               sizeof(void *);
+       err = ptrace_setregs(pid, regs);
+       if(err < 0)
+               panic("copy_context_skas0 : PTRACE_SETREGS failed, "
+                     "pid = %d, errno = %d\n", pid, errno);
+
+       /* set a well known return code for detection of child write failure */
+       child_data->err = 12345678;
+
+       /* Wait, until parent has finished its work: read child's pid from
+        * parent's stack, and check, if bad result.
+        */
+       wait_stub_done(pid, 0, "copy_context_skas0");
+
+       pid = data->err;
+       if(pid < 0)
+               panic("copy_context_skas0 - stub-parent reports error %d\n",
+                     pid);
+
+       /* Wait, until child has finished too: read child's result from
+        * child's stack and check it.
+        */
+       wait_stub_done(pid, -1, "copy_context_skas0");
+       if (child_data->err != UML_CONFIG_STUB_DATA)
+               panic("copy_context_skas0 - stub-child reports error %d\n",
+                     child_data->err);
+
+       if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
+                  (void *)PTRACE_O_TRACESYSGOOD) < 0)
+               panic("copy_context_skas0 : PTRACE_SETOPTIONS failed, "
+                     "errno = %d\n", errno);
+
+       return pid;
+}
+
 void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
                void (*handler)(int))
 {
@@ -334,21 +486,19 @@ void reboot_skas(void)
        siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT);
 }
 
-void switch_mm_skas(int mm_fd)
+void switch_mm_skas(struct mm_id *mm_idp)
 {
        int err;
 
 #warning need cpu pid in switch_mm_skas
-       err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_fd);
-       if(err)
-               panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n",
-                     errno);
-}
-
-void kill_off_processes_skas(void)
-{
-#warning need to loop over userspace_pids in kill_off_processes_skas
-       os_kill_ptraced_process(userspace_pid[0], 1);
+       if(proc_mm){
+               err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
+                            mm_idp->u.mm_fd);
+               if(err)
+                       panic("switch_mm_skas - PTRACE_SWITCH_MM failed, "
+                             "errno = %d\n", errno);
+       }
+       else userspace_pid[0] = mm_idp->u.pid;
 }
 
 /*
index 0a7b8aa55db8342b905a6f8b6f395e2a4a9ad9dd..cbabab104ac3ef904bdd7a2f9ec43e3d415e73ab 100644 (file)
@@ -175,9 +175,12 @@ static int start_kernel_proc(void *unused)
        return(0);
 }
 
+extern int userspace_pid[];
+
 int start_uml_skas(void)
 {
-       start_userspace(0);
+       if(proc_mm)
+               userspace_pid[0] = start_userspace(0);
 
        init_new_thread_signals(1);
 
@@ -199,3 +202,31 @@ int thread_pid_skas(struct task_struct *task)
 #warning Need to look up userspace_pid by cpu
        return(userspace_pid[0]);
 }
+
+void kill_off_processes_skas(void)
+{
+       if(proc_mm)
+#warning need to loop over userspace_pids in kill_off_processes_skas
+               os_kill_ptraced_process(userspace_pid[0], 1);
+       else {
+               struct task_struct *p;
+               int pid, me;
+
+               me = os_getpid();
+               for_each_process(p){
+                       if(p->mm == NULL)
+                               continue;
+
+                       pid = p->mm->context.skas.id.u.pid;
+                       os_kill_ptraced_process(pid, 1);
+               }
+       }
+}
+
+unsigned long current_stub_stack(void)
+{
+       if(current->mm == NULL)
+               return(0);
+
+       return(current->mm->context.skas.id.stack);
+}
index b8c5e71763d10888283510d100acd4716e12294b..6230999c672c90ff3a36abf31d23f8c774c3f2eb 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "linux/stddef.h"
 #include "linux/sched.h"
+#include "linux/config.h"
 #include "linux/mm.h"
 #include "asm/page.h"
 #include "asm/pgtable.h"
@@ -17,7 +18,7 @@
 #include "os.h"
 #include "tlb.h"
 
-static void do_ops(int fd, struct host_vm_op *ops, int last)
+static void do_ops(union mm_context *mmu, struct host_vm_op *ops, int last)
 {
        struct host_vm_op *op;
        int i;
@@ -26,18 +27,18 @@ static void do_ops(int fd, struct host_vm_op *ops, int last)
                op = &ops[i];
                switch(op->type){
                case MMAP:
-                       map(fd, op->u.mmap.addr, op->u.mmap.len,
+                        map(&mmu->skas.id, op->u.mmap.addr, op->u.mmap.len,
                            op->u.mmap.r, op->u.mmap.w, op->u.mmap.x,
                            op->u.mmap.fd, op->u.mmap.offset);
                        break;
                case MUNMAP:
-                       unmap(fd, (void *) op->u.munmap.addr,
+                        unmap(&mmu->skas.id, (void *) op->u.munmap.addr,
                              op->u.munmap.len);
                        break;
                case MPROTECT:
-                       protect(fd, op->u.mprotect.addr, op->u.mprotect.len,
-                               op->u.mprotect.r, op->u.mprotect.w,
-                               op->u.mprotect.x);
+                        protect(&mmu->skas.id, op->u.mprotect.addr,
+                                op->u.mprotect.len, op->u.mprotect.r,
+                                op->u.mprotect.w, op->u.mprotect.x);
                        break;
                default:
                        printk("Unknown op type %d in do_ops\n", op->type);
@@ -46,12 +47,15 @@ static void do_ops(int fd, struct host_vm_op *ops, int last)
        }
 }
 
+extern int proc_mm;
+
 static void fix_range(struct mm_struct *mm, unsigned long start_addr,
                      unsigned long end_addr, int force)
 {
-        int fd = mm->context.skas.mm_fd;
+        if(!proc_mm && (end_addr > CONFIG_STUB_START))
+                end_addr = CONFIG_STUB_START;
 
-        fix_range_common(mm, start_addr, end_addr, force, fd, do_ops);
+        fix_range_common(mm, start_addr, end_addr, force, do_ops);
 }
 
 void __flush_tlb_one_skas(unsigned long addr)
@@ -69,17 +73,20 @@ void flush_tlb_range_skas(struct vm_area_struct *vma, unsigned long start,
 
 void flush_tlb_mm_skas(struct mm_struct *mm)
 {
+       unsigned long end;
+
        /* Don't bother flushing if this address space is about to be
          * destroyed.
          */
         if(atomic_read(&mm->mm_users) == 0)
                 return;
 
-        fix_range(mm, 0, host_task_size, 0);
-        flush_tlb_kernel_range_common(start_vm, end_vm);
+       end = proc_mm ? task_size : CONFIG_STUB_START;
+        fix_range(mm, 0, end, 0);
 }
 
 void force_flush_all_skas(void)
 {
-        fix_range(current->mm, 0, host_task_size, 1);
+       unsigned long end = proc_mm ? task_size : CONFIG_STUB_START;
+        fix_range(current->mm, 0, end, 1);
 }
index f829b309b63c7d7c27dd36ba87363130695ca887..c40b611e3d936dbcd120f65961e18a65ec8a4c87 100644 (file)
@@ -48,6 +48,13 @@ void enable_timer(void)
        set_interval(ITIMER_VIRTUAL);
 }
 
+void prepare_timer(void * ptr)
+{
+       int usec = 1000000/hz();
+       *(struct itimerval *)ptr = ((struct itimerval) { { 0, usec },
+                                                        { 0, usec }});
+}
+
 void disable_timer(void)
 {
        struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
index eda477edfdf5e612e8c982a4c7f5f550b3ba5c0e..83ec8d4747fd039482aca79dc9137371d0b86989 100644 (file)
 #define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1))
 
 void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
-                      unsigned long end_addr, int force, int data,
-                      void (*do_ops)(int, struct host_vm_op *, int))
+                      unsigned long end_addr, int force,
+                      void (*do_ops)(union mm_context *, struct host_vm_op *,
+                                     int))
 {
         pgd_t *npgd;
         pud_t *npud;
         pmd_t *npmd;
         pte_t *npte;
+        union mm_context *mmu = &mm->context;
         unsigned long addr, end;
         int r, w, x;
         struct host_vm_op ops[16];
@@ -40,7 +42,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
                                 end = end_addr;
                         if(force || pgd_newpage(*npgd)){
                                 op_index = add_munmap(addr, end - addr, ops,
-                                                      op_index, last_op, data,
+                                                      op_index, last_op, mmu,
                                                       do_ops);
                                 pgd_mkuptodate(*npgd);
                         }
@@ -55,7 +57,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
                                 end = end_addr;
                         if(force || pud_newpage(*npud)){
                                 op_index = add_munmap(addr, end - addr, ops,
-                                                      op_index, last_op, data,
+                                                      op_index, last_op, mmu,
                                                       do_ops);
                                 pud_mkuptodate(*npud);
                         }
@@ -70,7 +72,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
                                 end = end_addr;
                         if(force || pmd_newpage(*npmd)){
                                 op_index = add_munmap(addr, end - addr, ops,
-                                                      op_index, last_op, data,
+                                                      op_index, last_op, mmu,
                                                       do_ops);
                                 pmd_mkuptodate(*npmd);
                         }
@@ -93,21 +95,21 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
                                 op_index = add_mmap(addr,
                                                     pte_val(*npte) & PAGE_MASK,
                                                     PAGE_SIZE, r, w, x, ops,
-                                                    op_index, last_op, data,
+                                                    op_index, last_op, mmu,
                                                     do_ops);
                         else op_index = add_munmap(addr, PAGE_SIZE, ops,
-                                                   op_index, last_op, data,
+                                                   op_index, last_op, mmu,
                                                    do_ops);
                 }
                 else if(pte_newprot(*npte))
                         op_index = add_mprotect(addr, PAGE_SIZE, r, w, x, ops,
-                                                op_index, last_op, data,
+                                                op_index, last_op, mmu,
                                                 do_ops);
 
                 *npte = pte_mkuptodate(*npte);
                 addr += PAGE_SIZE;
         }
-        (*do_ops)(data, ops, op_index);
+        (*do_ops)(mmu, ops, op_index);
 }
 
 int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
@@ -195,51 +197,6 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
         return(updated);
 }
 
-void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
-{
-        address &= PAGE_MASK;
-        flush_tlb_range(vma, address, address + PAGE_SIZE);
-}
-
-void flush_tlb_all(void)
-{
-        flush_tlb_mm(current->mm);
-}
-  
-void flush_tlb_kernel_range(unsigned long start, unsigned long end)
-{
-        CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt,
-                         flush_tlb_kernel_range_common, start, end);
-}
-
-void flush_tlb_kernel_vm(void)
-{
-        CHOOSE_MODE(flush_tlb_kernel_vm_tt(),
-                    flush_tlb_kernel_range_common(start_vm, end_vm));
-}
-
-void __flush_tlb_one(unsigned long addr)
-{
-        CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
-}
-
-void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, 
-     unsigned long end)
-{
-        CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start,
-                         end);
-}
-
-void flush_tlb_mm(struct mm_struct *mm)
-{
-        CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
-}
-
-void force_flush_all(void)
-{
-        CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
-}
-
 pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
 {
         return(pgd_offset(mm, address));
@@ -270,9 +227,9 @@ pte_t *addr_pte(struct task_struct *task, unsigned long addr)
 }
 
 int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
-     int r, int w, int x, struct host_vm_op *ops, int index,
-     int last_filled, int data,
-     void (*do_ops)(int, struct host_vm_op *, int))
+             int r, int w, int x, struct host_vm_op *ops, int index,
+             int last_filled, union mm_context *mmu,
+             void (*do_ops)(union mm_context *, struct host_vm_op *, int))
 {
         __u64 offset;
        struct host_vm_op *last;
@@ -292,7 +249,7 @@ int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
        }
 
        if(index == last_filled){
-               (*do_ops)(data, ops, last_filled);
+               (*do_ops)(mmu, ops, last_filled);
                index = -1;
        }
 
@@ -310,8 +267,8 @@ int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
 }
 
 int add_munmap(unsigned long addr, unsigned long len, struct host_vm_op *ops,
-              int index, int last_filled, int data,
-              void (*do_ops)(int, struct host_vm_op *, int))
+              int index, int last_filled, union mm_context *mmu,
+              void (*do_ops)(union mm_context *, struct host_vm_op *, int))
 {
        struct host_vm_op *last;
 
@@ -325,7 +282,7 @@ int add_munmap(unsigned long addr, unsigned long len, struct host_vm_op *ops,
        }
 
        if(index == last_filled){
-               (*do_ops)(data, ops, last_filled);
+               (*do_ops)(mmu, ops, last_filled);
                index = -1;
        }
 
@@ -337,8 +294,9 @@ int add_munmap(unsigned long addr, unsigned long len, struct host_vm_op *ops,
 }
 
 int add_mprotect(unsigned long addr, unsigned long len, int r, int w, int x,
-                struct host_vm_op *ops, int index, int last_filled, int data,
-                void (*do_ops)(int, struct host_vm_op *, int))
+                 struct host_vm_op *ops, int index, int last_filled,
+                 union mm_context *mmu,
+                 void (*do_ops)(union mm_context *, struct host_vm_op *, int))
 {
        struct host_vm_op *last;
 
@@ -354,7 +312,7 @@ int add_mprotect(unsigned long addr, unsigned long len, int r, int w, int x,
        }
 
        if(index == last_filled){
-               (*do_ops)(data, ops, last_filled);
+               (*do_ops)(mmu, ops, last_filled);
                index = -1;
        }
 
@@ -367,3 +325,49 @@ int add_mprotect(unsigned long addr, unsigned long len, int r, int w, int x,
                                                      .x        = x } } });
        return(index);
 }
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
+{
+        address &= PAGE_MASK;
+        flush_tlb_range(vma, address, address + PAGE_SIZE);
+}
+
+void flush_tlb_all(void)
+{
+        flush_tlb_mm(current->mm);
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+        CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt,
+                         flush_tlb_kernel_range_common, start, end);
+}
+
+void flush_tlb_kernel_vm(void)
+{
+        CHOOSE_MODE(flush_tlb_kernel_vm_tt(),
+                    flush_tlb_kernel_range_common(start_vm, end_vm));
+}
+
+void __flush_tlb_one(unsigned long addr)
+{
+        CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
+}
+
+void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+                    unsigned long end)
+{
+        CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start,
+                         end);
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+        CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
+}
+
+void force_flush_all(void)
+{
+        CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
+}
+
index 203216ad86f1c230b9dceaf9ed297e68bdca075a..2eefb43bc9c2e3a01cb547ca657d654b98e2b19c 100644 (file)
@@ -17,7 +17,7 @@
 #include "os.h"
 #include "tlb.h"
 
-static void do_ops(int unused, struct host_vm_op *ops, int last)
+static void do_ops(union mm_context *mmu, struct host_vm_op *ops, int last)
 {
        struct host_vm_op *op;
        int i;
@@ -55,7 +55,7 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr,
                 panic("fix_range fixing wrong address space, current = 0x%p",
                       current);
 
-        fix_range_common(mm, start_addr, end_addr, force, 0, do_ops);
+        fix_range_common(mm, start_addr, end_addr, force, do_ops);
 }
 
 atomic_t vmchange_seq = ATOMIC_INIT(1);
index 61dfd4fef752a0810f24cdfdee20fa89aecc497b..163476a8cb1b7cef16d8a944049d1d6d899d73fd 100644 (file)
@@ -30,6 +30,7 @@ SECTIONS
        _einittext = .;
   }
   . = ALIGN(4096);
+
   .text      :
   {
     *(.text)
@@ -39,6 +40,12 @@ SECTIONS
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)
     *(.gnu.linkonce.t*)
+
+    . = ALIGN(4096);
+    __syscall_stub_start = .;
+    *(.__syscall_stub*)
+    __syscall_stub_end = .;
+    . = ALIGN(4096);
   }
 
   #include "asm/common.lds.S"
index 9a0ad094d926d42cafd613f0dd005e13ffb1e028..3125d320722c9c529c1c566f2854d20439192e1b 100644 (file)
@@ -121,6 +121,11 @@ void init_registers(int pid)
                      err);
 }
 
+void get_safe_registers(unsigned long *regs)
+{
+       memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long));
+}
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
index 6286c974bbeb0a44fc235aa3d47a88898bff37a0..44438d15c3d699c5492d903a2e87df3765efe550 100644 (file)
@@ -69,6 +69,11 @@ void init_registers(int pid)
                      err);
 }
 
+void get_safe_registers(unsigned long *regs)
+{
+       memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long));
+}
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
index 7459d09c233e37f99b840b4454ea2d295fd5c72f..17f305b6bade9272fb3cecc63358a2032eb26a53 100644 (file)
@@ -16,6 +16,11 @@ define unprofile
 endef
 
 
+# The stubs and unmap.o can't try to call mcount or update basic block data
+define unprofile
+       $(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
+endef
+
 quiet_cmd_make_link = SYMLINK $@
 cmd_make_link       = ln -sf $(srctree)/arch/$(SUBARCH)/$($(notdir $@)-dir)/$(notdir $@) $@
 
index 095bcdb0b9cc1f0a40a012b3511456fcee0957a4..77c3c4d29f55f48702ef4e1e42d8b00b082f273e 100644 (file)
@@ -1,6 +1,6 @@
 obj-y = bitops.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
-       ptrace_user.o semaphore.o signal.o sigcontext.o syscalls.o sysrq.o \
-       sys_call_table.o
+       ptrace_user.o semaphore.o signal.o sigcontext.o stub.o stub_segv.o \
+       syscalls.o sysrq.o sys_call_table.o
 
 obj-$(CONFIG_HIGHMEM) += highmem.o
 obj-$(CONFIG_MODULES) += module.o
@@ -16,6 +16,14 @@ semaphore.c-dir = kernel
 highmem.c-dir = mm
 module.c-dir = kernel
 
+STUB_CFLAGS = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS))
+
+# _cflags works with kernel files, not with userspace ones, but c_flags does,
+# why ask why?
+$(obj)/stub_segv.o : c_flags = $(STUB_CFLAGS)
+
+$(obj)/stub.o : a_flags = $(STUB_CFLAGS)
+
 subdir- := util
 
 include arch/um/scripts/Makefile.unmap
diff --git a/arch/um/sys-i386/stub.S b/arch/um/sys-i386/stub.S
new file mode 100644 (file)
index 0000000..2f2c70a
--- /dev/null
@@ -0,0 +1,8 @@
+#include "uml-config.h"
+
+       .globl syscall_stub
+.section .__syscall_stub, "x"
+syscall_stub:
+       int     $0x80
+       mov     %eax, UML_CONFIG_STUB_DATA
+       int3
diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c
new file mode 100644 (file)
index 0000000..b251442
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include <signal.h>
+#include <asm/sigcontext.h>
+#include <asm/unistd.h>
+#include "uml-config.h"
+#include "sysdep/sigcontext.h"
+#include "sysdep/faultinfo.h"
+
+void __attribute__ ((__section__ (".__syscall_stub")))
+stub_segv_handler(int sig)
+{
+       struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
+
+       GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA),
+                             sc);
+
+       __asm__("movl %0, %%eax ; int $0x80": : "g" (__NR_getpid));
+       __asm__("movl %%eax, %%ebx ; movl %0, %%eax ; movl %1, %%ecx ;"
+               "int $0x80": : "g" (__NR_kill), "g" (SIGUSR1));
+       /* Pop the frame pointer and return address since we need to leave
+        * the stack in its original form when we do the sigreturn here, by
+        * hand.
+        */
+       __asm__("popl %%eax ; popl %%eax ; popl %%eax ; movl %0, %%eax ; "
+               "int $0x80" : : "g" (__NR_sigreturn));
+}
index 2bc6f6849010d0ca27a7aeaa414bcfd9421fa3b8..7488206ce6f4ae91ba20123a9efcede188b10996 100644 (file)
@@ -6,8 +6,8 @@
 
 #XXX: why into lib-y?
 lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o mem.o memcpy.o \
-       ptrace.o ptrace_user.o semaphore.o sigcontext.o signal.o \
-       syscalls.o sysrq.o thunk.o syscall_table.o
+       ptrace.o ptrace_user.o semaphore.o sigcontext.o signal.o stub.o \
+       stub_segv.o syscalls.o syscall_table.o sysrq.o thunk.o
 
 obj-y := ksyms.o
 obj-$(CONFIG_MODULES) += module.o um_module.o
@@ -28,6 +28,14 @@ semaphore.c-dir = kernel
 thunk.S-dir = lib
 module.c-dir = kernel
 
+STUB_CFLAGS = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS))
+
+# _cflags works with kernel files, not with userspace ones, but c_flags does,
+# why ask why?
+$(obj)/stub_segv.o : c_flags = $(STUB_CFLAGS)
+
+$(obj)/stub.o : a_flags = $(STUB_CFLAGS)
+
 subdir- := util
 
 include arch/um/scripts/Makefile.unmap
diff --git a/arch/um/sys-x86_64/stub.S b/arch/um/sys-x86_64/stub.S
new file mode 100644 (file)
index 0000000..31c1492
--- /dev/null
@@ -0,0 +1,15 @@
+#include "uml-config.h"
+
+       .globl syscall_stub
+.section .__syscall_stub, "x"
+syscall_stub:
+       syscall
+       /* We don't have 64-bit constants, so this constructs the address
+        * we need.
+        */
+       movq    $(UML_CONFIG_STUB_DATA >> 32), %rbx
+       salq    $32, %rbx
+       movq    $(UML_CONFIG_STUB_DATA & 0xffffffff), %rcx
+       or      %rcx, %rbx
+       movq    %rax, (%rbx)
+       int3
diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c
new file mode 100644 (file)
index 0000000..161d1fe
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include <signal.h>
+#include <linux/compiler.h>
+#include <asm/unistd.h>
+#include "uml-config.h"
+#include "sysdep/sigcontext.h"
+#include "sysdep/faultinfo.h"
+
+void __attribute__ ((__section__ (".__syscall_stub")))
+stub_segv_handler(int sig)
+{
+       struct ucontext *uc;
+
+       __asm__("movq %%rdx, %0" : "=g" (uc) :);
+        GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA),
+                              &uc->uc_mcontext);
+
+       __asm__("movq %0, %%rax ; syscall": : "g" (__NR_getpid));
+       __asm__("movq %%rax, %%rdi ; movq %0, %%rax ; movq %1, %%rsi ;"
+               "syscall": : "g" (__NR_kill), "g" (SIGUSR1));
+       /* Two popqs to restore the stack to the state just before entering
+        * the handler, one pops the return address, the other pops the frame
+        * pointer.
+        */
+       __asm__("popq %%rax ; popq %%rax ; movq %0, %%rax ; syscall" : : "g"
+               (__NR_rt_sigreturn));
+}
index b02d921da4f72267cf9e7fb534fccf5a33001456..5fd03225058aa410bb60e461bb149db048844583 100644 (file)
@@ -1076,6 +1076,10 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
 #ifdef CONFIG_X86_MCE
        mcheck_init(c);
 #endif
+       if (c == &boot_cpu_data)
+               mtrr_bp_init();
+       else
+               mtrr_ap_init();
 #ifdef CONFIG_NUMA
        if (c != &boot_cpu_data)
                numa_add_cpu(c - cpu_data);
index 6c0f402e3a889c9b7234a6ed8de80b259bd12a38..0612640d91b1c31262d3022edd6ffac685190514 100644 (file)
@@ -119,6 +119,7 @@ void __restore_processor_state(struct saved_context *ctxt)
        fix_processor_context();
 
        do_fpu_end();
+       mtrr_ap_init();
 }
 
 void restore_processor_state(void)
index 73389f51c4e5b2d841619e22e3e27af9ddbbdf24..61c12758ca70594f145042dd882993a56bb872a8 100644 (file)
@@ -56,6 +56,10 @@ SECTIONS
   .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
        *(.data.cacheline_aligned)
   }
+  . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+  .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) {
+       *(.data.read_mostly)
+  }
 
 #define VSYSCALL_ADDR (-10*1024*1024)
 #define VSYSCALL_PHYS_ADDR ((LOADADDR(.data.cacheline_aligned) + SIZEOF(.data.cacheline_aligned) + 4095) & ~(4095))
index abc8ed6c7026dc7b214593380e61064d60c63be9..3540d8b119f39fee1d79c1df0751e96cfdcb9aad 100644 (file)
@@ -46,8 +46,6 @@
 
 extern void do_syscall_trace(void);
 typedef int (*syscall_t)(void *a0,...);
-extern int (*do_syscalls)(struct pt_regs *regs, syscall_t fun,
-                                    int narg);
 extern syscall_t sys_call_table[];
 extern unsigned char sys_narg_table[];
 
@@ -72,10 +70,8 @@ int sys_pipe(int __user *userfds)
 /*
  * Common code for old and new mmaps.
  */
-
-static inline long do_mmap2(unsigned long addr, unsigned long len,
-                           unsigned long prot, unsigned long flags,
-                           unsigned long fd, unsigned long pgoff)
+long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
+              unsigned long flags, unsigned long fd, unsigned long pgoff)
 {
        int error = -EBADF;
        struct file * file = NULL;
@@ -97,29 +93,6 @@ out:
        return error;
 }
 
-unsigned long old_mmap(unsigned long addr, size_t len, int prot,
-                      int flags, int fd, off_t offset)
-{
-       return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
-}
-
-long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
-              unsigned long flags, unsigned long fd, unsigned long pgoff)
-{
-       return do_mmap2(addr, len, prot, flags, fd, pgoff);
-}
-
-int sys_fork(struct pt_regs *regs)
-{
-       return do_fork(SIGCHLD, regs->areg[1], regs, 0, NULL, NULL);
-}
-
-int sys_vfork(struct pt_regs *regs)
-{
-       return do_fork(CLONE_VFORK|CLONE_VM|SIGCHLD, regs->areg[1],
-                      regs, 0, NULL, NULL);
-}
-
 int sys_clone(struct pt_regs *regs)
 {
        unsigned long clone_flags;
@@ -162,30 +135,6 @@ int sys_uname(struct old_utsname * name)
        return -EFAULT;
 }
 
-int sys_olduname(struct oldold_utsname * name)
-{
-       int error;
-
-       if (!name)
-               return -EFAULT;
-       if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
-               return -EFAULT;
-
-       error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
-       error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
-       error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
-       error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
-       error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
-       error -= __put_user(0,name->release+__OLD_UTS_LEN);
-       error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
-       error -= __put_user(0,name->version+__OLD_UTS_LEN);
-       error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
-       error -= __put_user(0,name->machine+__OLD_UTS_LEN);
-
-       return error ? -EFAULT : 0;
-}
-
-
 /*
  * Build the string table for the builtin "poor man's strace".
  */
@@ -319,100 +268,3 @@ void system_call (struct pt_regs *regs)
        regs->areg[2] = res;
        do_syscall_trace();
 }
-
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly.
- */
-
-int sys_ipc (uint call, int first, int second,
-                       int third, void __user *ptr, long fifth)
-{
-       int version, ret;
-
-       version = call >> 16; /* hack for backward compatibility */
-       call &= 0xffff;
-       ret = -ENOSYS;
-
-       switch (call) {
-       case SEMOP:
-               ret = sys_semtimedop (first, (struct sembuf __user *)ptr,
-                                    second, NULL);
-               break;
-
-       case SEMTIMEDOP:
-               ret = sys_semtimedop (first, (struct sembuf __user *)ptr,
-                                     second, (const struct timespec *) fifth);
-               break;
-
-       case SEMGET:
-               ret = sys_semget (first, second, third);
-               break;
-
-       case SEMCTL: {
-               union semun fourth;
-
-               if (ptr && !get_user(fourth.__pad, (void *__user *) ptr))
-                       ret = sys_semctl (first, second, third, fourth);
-               break;
-               }
-
-       case MSGSND:
-               ret = sys_msgsnd (first, (struct msgbuf __user*) ptr,
-                                 second, third);
-               break;
-
-       case MSGRCV:
-               switch (version) {
-               case 0: {
-                       struct ipc_kludge tmp;
-
-                       if (ptr && !copy_from_user(&tmp,
-                                          (struct ipc_kludge *) ptr,
-                                          sizeof (tmp)))
-                               ret = sys_msgrcv (first, tmp.msgp, second,
-                                                 tmp.msgtyp, third);
-                       break;
-                       }
-
-               default:
-                       ret = sys_msgrcv (first, (struct msgbuf __user *) ptr,
-                                         second, 0, third);
-                       break;
-               }
-               break;
-
-       case MSGGET:
-               ret = sys_msgget ((key_t) first, second);
-               break;
-
-       case MSGCTL:
-               ret = sys_msgctl (first, second, (struct msqid_ds __user*) ptr);
-               break;
-
-       case SHMAT: {
-               ulong raddr;
-               ret = do_shmat (first, (char __user *) ptr, second, &raddr);
-
-               if (!ret)
-                       ret = put_user (raddr, (ulong __user *) third);
-
-               break;
-               }
-
-       case SHMDT:
-               ret = sys_shmdt ((char __user *)ptr);
-               break;
-
-       case SHMGET:
-               ret = sys_shmget (first, second, third);
-               break;
-
-       case SHMCTL:
-               ret = sys_shmctl (first, second, (struct shmid_ds __user*) ptr);
-               break;
-       }
-       return ret;
-}
-
index 5b3f75f50febb4fd4aaeb410943135fb7bf49038..07580696b6024514ae05e8addf9185b66cabf423 100644 (file)
  */
 
 SYSCALL(0, 0)                          /* 00 */
-
 SYSCALL(sys_exit, 1)
-SYSCALL(sys_fork, 0)
+SYSCALL(sys_ni_syscall, 0)
 SYSCALL(sys_read, 3)
 SYSCALL(sys_write, 3)
 SYSCALL(sys_open, 3)                   /* 05 */
 SYSCALL(sys_close, 1)
-SYSCALL(sys_waitpid, 3)
+SYSCALL(sys_ni_syscall, 3)
 SYSCALL(sys_creat, 2)
 SYSCALL(sys_link, 2)
 SYSCALL(sys_unlink, 1)                 /* 10 */
 SYSCALL(sys_execve, 0)
 SYSCALL(sys_chdir, 1)
-SYSCALL(sys_time, 1)
+SYSCALL(sys_ni_syscall, 1)
 SYSCALL(sys_mknod, 3)
 SYSCALL(sys_chmod, 2)                  /* 15 */
 SYSCALL(sys_lchown, 3)
@@ -47,19 +46,19 @@ SYSCALL(sys_stat, 2)
 SYSCALL(sys_lseek, 3)
 SYSCALL(sys_getpid, 0)                 /* 20 */
 SYSCALL(sys_mount, 5)
-SYSCALL(sys_oldumount, 1)
+SYSCALL(sys_ni_syscall, 1)
 SYSCALL(sys_setuid, 1)
 SYSCALL(sys_getuid, 0)
-SYSCALL(sys_stime, 1)                  /* 25 */
+SYSCALL(sys_ni_syscall, 1)             /* 25 */
 SYSCALL(sys_ptrace, 4)
-SYSCALL(sys_alarm, 1)
+SYSCALL(sys_ni_syscall, 1)
 SYSCALL(sys_fstat, 2)
-SYSCALL(sys_pause, 0)
+SYSCALL(sys_ni_syscall, 0)
 SYSCALL(sys_utime, 2)                  /* 30 */
 SYSCALL(sys_ni_syscall, 0)
 SYSCALL(sys_ni_syscall, 0)
 SYSCALL(sys_access, 2)
-SYSCALL(sys_nice, 1)
+SYSCALL(sys_ni_syscall, 1)
 SYSCALL(sys_ni_syscall, 0)             /* 35 */
 SYSCALL(sys_sync, 0)
 SYSCALL(sys_kill, 2)
@@ -73,7 +72,7 @@ SYSCALL(sys_ni_syscall, 0)
 SYSCALL(sys_brk, 1)                    /* 45 */
 SYSCALL(sys_setgid, 1)
 SYSCALL(sys_getgid, 0)
-SYSCALL(sys_ni_syscall, 0)             /* was signal(2) */
+SYSCALL(sys_ni_syscall, 0)
 SYSCALL(sys_geteuid, 0)
 SYSCALL(sys_getegid, 0)                        /* 50 */
 SYSCALL(sys_acct, 1)
@@ -84,21 +83,21 @@ SYSCALL(sys_fcntl, 3)                       /* 55 */
 SYSCALL(sys_ni_syscall, 2)
 SYSCALL(sys_setpgid, 2)
 SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_olduname, 1)
+SYSCALL(sys_ni_syscall, 0)
 SYSCALL(sys_umask, 1)                  /* 60 */
 SYSCALL(sys_chroot, 1)
 SYSCALL(sys_ustat, 2)
 SYSCALL(sys_dup2, 2)
 SYSCALL(sys_getppid, 0)
-SYSCALL(sys_getpgrp, 0)                        /* 65 */
+SYSCALL(sys_ni_syscall, 0)             /* 65 */
 SYSCALL(sys_setsid, 0)
 SYSCALL(sys_sigaction, 3)
-SYSCALL(sys_sgetmask, 0)
-SYSCALL(sys_ssetmask, 1)
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_ni_syscall, 1)
 SYSCALL(sys_setreuid, 2)               /* 70 */
 SYSCALL(sys_setregid, 2)
 SYSCALL(sys_sigsuspend, 0)
-SYSCALL(sys_sigpending, 1)
+SYSCALL(sys_ni_syscall, 1)
 SYSCALL(sys_sethostname, 2)
 SYSCALL(sys_setrlimit, 2)              /* 75 */
 SYSCALL(sys_getrlimit, 2)
@@ -107,15 +106,15 @@ SYSCALL(sys_gettimeofday, 2)
 SYSCALL(sys_settimeofday, 2)
 SYSCALL(sys_getgroups, 2)              /* 80 */
 SYSCALL(sys_setgroups, 2)
-SYSCALL(sys_ni_syscall, 0)              /* old_select */
+SYSCALL(sys_ni_syscall, 0)
 SYSCALL(sys_symlink, 2)
 SYSCALL(sys_lstat, 2)
 SYSCALL(sys_readlink, 3)               /* 85 */
 SYSCALL(sys_uselib, 1)
 SYSCALL(sys_swapon, 2)
 SYSCALL(sys_reboot, 3)
-SYSCALL(old_readdir, 3)
-SYSCALL(old_mmap, 6)                   /* 90 */
+SYSCALL(sys_ni_syscall, 3)
+SYSCALL(sys_ni_syscall, 6)             /* 90 */
 SYSCALL(sys_munmap, 2)
 SYSCALL(sys_truncate, 2)
 SYSCALL(sys_ftruncate, 2)
@@ -127,7 +126,7 @@ SYSCALL(sys_ni_syscall, 0)
 SYSCALL(sys_statfs, 2)
 SYSCALL(sys_fstatfs, 2)                        /* 100 */
 SYSCALL(sys_ni_syscall, 3)
-SYSCALL(sys_socketcall, 2)
+SYSCALL(sys_ni_syscall, 2)
 SYSCALL(sys_syslog, 3)
 SYSCALL(sys_setitimer, 3)
 SYSCALL(sys_getitimer, 2)              /* 105 */
@@ -137,32 +136,32 @@ SYSCALL(sys_newfstat, 2)
 SYSCALL(sys_uname, 1)
 SYSCALL(sys_ni_syscall, 0)             /* 110 */
 SYSCALL(sys_vhangup, 0)
-SYSCALL(sys_ni_syscall, 0)             /* was sys_idle() */
+SYSCALL(sys_ni_syscall, 0)
 SYSCALL(sys_ni_syscall, 0)
 SYSCALL(sys_wait4, 4)
 SYSCALL(sys_swapoff, 1)                        /* 115 */
 SYSCALL(sys_sysinfo, 1)
-SYSCALL(sys_ipc, 5)                    /* 6 really, but glibc uses only 5) */
+SYSCALL(sys_ni_syscall, 0)
 SYSCALL(sys_fsync, 1)
 SYSCALL(sys_sigreturn, 0)
 SYSCALL(sys_clone, 0)                  /* 120 */
 SYSCALL(sys_setdomainname, 2)
 SYSCALL(sys_newuname, 1)
-SYSCALL(sys_ni_syscall, 0)             /* sys_modify_ldt */
+SYSCALL(sys_ni_syscall, 0)
 SYSCALL(sys_adjtimex, 1)
 SYSCALL(sys_mprotect, 3)               /* 125 */
-SYSCALL(sys_sigprocmask, 3)
-SYSCALL(sys_ni_syscall, 2)             /* old sys_create_module */
+SYSCALL(sys_ni_syscall, 3)
+SYSCALL(sys_ni_syscall, 2)
 SYSCALL(sys_init_module, 2)
 SYSCALL(sys_delete_module, 1)
-SYSCALL(sys_ni_syscall, 1)             /* old sys_get_kernel_sysm */   /* 130 */
+SYSCALL(sys_ni_syscall, 1)             /* 130 */
 SYSCALL(sys_quotactl, 0)
 SYSCALL(sys_getpgid, 1)
 SYSCALL(sys_fchdir, 1)
 SYSCALL(sys_bdflush, 2)
 SYSCALL(sys_sysfs, 3)                  /* 135 */
 SYSCALL(sys_personality, 1)
-SYSCALL(sys_ni_syscall, 0)             /* for afs_syscall */
+SYSCALL(sys_ni_syscall, 0)
 SYSCALL(sys_setfsuid, 1)
 SYSCALL(sys_setfsgid, 1)
 SYSCALL(sys_llseek, 5)                 /* 140 */
@@ -212,7 +211,7 @@ SYSCALL(sys_socket, 3)
 SYSCALL(sys_socketpair, 4)
 SYSCALL(sys_setresuid, 3)              /* 185 */
 SYSCALL(sys_getresuid, 3)
-SYSCALL(sys_ni_syscall, 5)             /* old sys_query_module */
+SYSCALL(sys_ni_syscall, 5)
 SYSCALL(sys_poll, 3)
 SYSCALL(sys_nfsservctl, 3)
 SYSCALL(sys_setresgid, 3)              /* 190 */
@@ -235,7 +234,7 @@ SYSCALL(sys_sigaltstack, 0)
 SYSCALL(sys_sendfile, 4)
 SYSCALL(sys_ni_syscall, 0)
 SYSCALL(sys_ni_syscall, 0)
-SYSCALL(sys_mmap2, 6)                  /* 210 */
+SYSCALL(sys_mmap, 6)                   /* 210 */
 SYSCALL(sys_truncate64, 2)
 SYSCALL(sys_ftruncate64, 2)
 SYSCALL(sys_stat64, 2)
@@ -245,4 +244,4 @@ SYSCALL(sys_pivot_root, 2)
 SYSCALL(sys_mincore, 3)
 SYSCALL(sys_madvise, 3)
 SYSCALL(sys_getdents64, 3)
-SYSCALL(sys_vfork, 0)                  /* 220 */
+SYSCALL(sys_ni_syscall, 0)             /* 220 */
index 5ef9adb9fe7363919cce8c530a282df0f6b562f9..bd2ec7e284cc790db66922cef1335b2479320286 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/skbuff.h>
 #include <asm/io.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -895,11 +894,6 @@ static dev_link_t *bluecard_attach(void)
        link->next = dev_list;
        dev_list = link;
        client_reg.dev_info = &dev_info;
-       client_reg.EventMask =
-               CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-               CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-               CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-       client_reg.event_handler = &bluecard_event;
        client_reg.Version = 0x0210;
        client_reg.event_callback_args.client_data = link;
 
@@ -1103,6 +1097,7 @@ static struct pcmcia_driver bluecard_driver = {
                .name   = "bluecard_cs",
        },
        .attach         = bluecard_attach,
+       .event          = bluecard_event,
        .detach         = bluecard_detach,
        .id_table       = bluecard_ids,
 };
index 9013cd759afb755cc9c406f86195ed3f9f1cb616..adf1750ea58d653a93fa71d1722412cf770912e9 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/device.h>
 #include <linux/firmware.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -696,11 +695,6 @@ static dev_link_t *bt3c_attach(void)
        link->next = dev_list;
        dev_list = link;
        client_reg.dev_info = &dev_info;
-       client_reg.EventMask =
-           CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-           CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-           CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-       client_reg.event_handler = &bt3c_event;
        client_reg.Version = 0x0210;
        client_reg.event_callback_args.client_data = link;
 
@@ -947,6 +941,7 @@ static struct pcmcia_driver bt3c_driver = {
                .name   = "bt3c_cs",
        },
        .attach         = bt3c_attach,
+       .event          = bt3c_event,
        .detach         = bt3c_detach,
        .id_table       = bt3c_ids,
 };
index c479484a1f7f0d004aa888be03b6103d2bc85ebb..e4c59fdc0e12bcc7e5d1e49231d211b5d3c67b7c 100644 (file)
@@ -43,7 +43,6 @@
 #include <asm/system.h>
 #include <asm/io.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -615,11 +614,6 @@ static dev_link_t *btuart_attach(void)
        link->next = dev_list;
        dev_list = link;
        client_reg.dev_info = &dev_info;
-       client_reg.EventMask =
-               CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-               CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-               CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-       client_reg.event_handler = &btuart_event;
        client_reg.Version = 0x0210;
        client_reg.event_callback_args.client_data = link;
 
@@ -867,6 +861,7 @@ static struct pcmcia_driver btuart_driver = {
                .name   = "btuart_cs",
        },
        .attach         = btuart_attach,
+       .event          = btuart_event,
        .detach         = btuart_detach,
        .id_table       = btuart_ids,
 };
index bb12f7daeb9195ce8a3981bab468beea50a2c041..e39868c3da4815f89fb247badd3faa9e6b15cb91 100644 (file)
@@ -43,7 +43,6 @@
 #include <asm/system.h>
 #include <asm/io.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -594,11 +593,6 @@ static dev_link_t *dtl1_attach(void)
        link->next = dev_list;
        dev_list = link;
        client_reg.dev_info = &dev_info;
-       client_reg.EventMask =
-               CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-               CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-               CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-       client_reg.event_handler = &dtl1_event;
        client_reg.Version = 0x0210;
        client_reg.event_callback_args.client_data = link;
 
@@ -820,6 +814,7 @@ static struct pcmcia_driver dtl1_driver = {
                .name   = "dtl1_cs",
        },
        .attach         = dtl1_attach,
+       .event          = dtl1_event,
        .detach         = dtl1_detach,
        .id_table       = dtl1_ids,
 };
index 3256192dcde8f72759f0aab798b03cb9739b5a55..f9b956fb2b8b81ac774cb772b21d06aee58a0a7f 100644 (file)
@@ -120,7 +120,7 @@ static unsigned int hci_vhci_chr_poll(struct file *file, poll_table * wait)
 
        poll_wait(file, &hci_vhci->read_wait, wait);
  
-       if (skb_queue_len(&hci_vhci->readq))
+       if (!skb_queue_empty(&hci_vhci->readq))
                return POLLIN | POLLRDNORM;
 
        return POLLOUT | POLLWRNORM;
index 1aff819f3832d33f11fc9a60a21bf2b30d847b30..08f69287ea36157c31477f23c8a4fc856637bebb 100644 (file)
@@ -40,7 +40,7 @@ obj-$(CONFIG_N_HDLC)          += n_hdlc.o
 obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
 obj-$(CONFIG_SX)               += sx.o generic_serial.o
 obj-$(CONFIG_RIO)              += rio/ generic_serial.o
-obj-$(CONFIG_HVC_CONSOLE)      += hvc_console.o hvsi.o
+obj-$(CONFIG_HVC_CONSOLE)      += hvc_console.o hvc_vio.o hvsi.o
 obj-$(CONFIG_RAW_DRIVER)       += raw.o
 obj-$(CONFIG_SGI_SNSC)         += snsc.o snsc_event.o
 obj-$(CONFIG_MMTIMER)          += mmtimer.o
index c2b12eab67c9de8361ad8bc839877049bbf3df26..123417e430405285dbe282fd3a5d99dd0e53910f 100644 (file)
@@ -96,3 +96,10 @@ config DRM_SIS
           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.
+
index b36b0158582e9103cde51c5a247b44e93d3a9a07..ddd941045b1f96478742450ae26a1550f941a8df 100644 (file)
@@ -18,6 +18,7 @@ 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
 ffb-objs    := ffb_drv.o ffb_context.o
 sis-objs    := sis_drv.o sis_ds.o sis_mm.o
+via-objs    := via_irq.o via_drv.o via_ds.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o
 
 ifeq ($(CONFIG_COMPAT),y)
 drm-objs    += drm_ioc32.o
@@ -38,4 +39,5 @@ obj-$(CONFIG_DRM_I830)        += i830.o
 obj-$(CONFIG_DRM_I915)  += i915.o
 obj-$(CONFIG_DRM_FFB)   += ffb.o
 obj-$(CONFIG_DRM_SIS)   += sis.o
+obj-$(CONFIG_DRM_VIA)  +=via.o
 
index 11c6950158b3d7606bc3bb859ed1c7132177bacb..70ca4fa55c9dd2433a37951095e7661240402e18 100644 (file)
        {0x8086, 0x2772, 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, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0, 0, 0}
+
diff --git a/drivers/char/drm/via_3d_reg.h b/drivers/char/drm/via_3d_reg.h
new file mode 100644 (file)
index 0000000..cf61bb5
--- /dev/null
@@ -0,0 +1,1651 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..82f8394
--- /dev/null
@@ -0,0 +1,741 @@
+/* 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;
+               }
+       } 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(drm_device_t * 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(drm_device_t * 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 DRM_ERR(EFAULT);
+       }
+
+       if (dev_priv->ring.virtual_start != NULL) {
+               DRM_ERROR("%s called again without calling cleanup\n",
+                         __FUNCTION__);
+               return DRM_ERR(EFAULT);
+       }
+
+       if (!dev->agp || !dev->agp->base) {
+               DRM_ERROR("%s called with no agp memory available\n", 
+                         __FUNCTION__);
+               return DRM_ERR(EFAULT);
+       }
+
+       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 DRM_ERR(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 = dev_priv->mmio->handle + init->reg_pause_addr;
+
+       via_cmdbuf_start(dev_priv);
+
+       return 0;
+}
+
+int via_dma_init(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       drm_via_dma_init_t init;
+       int retcode = 0;
+
+       DRM_COPY_FROM_USER_IOCTL(init, (drm_via_dma_init_t *) data,
+                                sizeof(init));
+
+       switch (init.func) {
+       case VIA_INIT_DMA:
+               if (!capable(CAP_SYS_ADMIN))
+                       retcode = DRM_ERR(EPERM);
+               else
+                       retcode = via_initialize(dev, dev_priv, &init);
+               break;
+       case VIA_CLEANUP_DMA:
+               if (!capable(CAP_SYS_ADMIN))
+                       retcode = DRM_ERR(EPERM);
+               else
+                       retcode = via_dma_cleanup(dev);
+               break;
+        case VIA_DMA_INITIALIZED:
+               retcode = (dev_priv->ring.virtual_start != NULL) ? 
+                       0: DRM_ERR( EFAULT );
+               break;
+       default:
+               retcode = DRM_ERR(EINVAL);
+               break;
+       }
+
+       return retcode;
+}
+
+
+
+static int via_dispatch_cmdbuffer(drm_device_t * 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("%s called without initializing AGP ring buffer.\n",
+                         __FUNCTION__);
+               return DRM_ERR(EFAULT);
+       }
+
+       if (cmd->size > VIA_PCI_BUF_SIZE) {
+               return DRM_ERR(ENOMEM);
+       } 
+
+
+       if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
+               return DRM_ERR(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 DRM_ERR(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(drm_device_t * dev)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+
+       if (!via_wait_idle(dev_priv)) {
+               return DRM_ERR(EBUSY);
+       }
+       return 0;
+}
+
+int via_flush_ioctl(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+
+       LOCK_TEST_WITH_RETURN( dev, filp );
+
+       return via_driver_dma_quiescent(dev);
+}
+
+int via_cmdbuffer(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_via_cmdbuffer_t cmdbuf;
+       int ret;
+
+       LOCK_TEST_WITH_RETURN( dev, filp );
+
+       DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t *) data,
+                                sizeof(cmdbuf));
+
+       DRM_DEBUG("via cmdbuffer, buf %p size %lu\n", cmdbuf.buf, cmdbuf.size);
+
+       ret = via_dispatch_cmdbuffer(dev, &cmdbuf);
+       if (ret) {
+               return ret;
+       }
+
+       return 0;
+}
+
+extern int 
+via_parse_command_stream(drm_device_t *dev, const uint32_t * buf, unsigned int size);
+static int via_dispatch_pci_cmdbuffer(drm_device_t * 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 DRM_ERR(ENOMEM);
+       } 
+       if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
+               return DRM_ERR(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;
+}
+
+int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_via_cmdbuffer_t cmdbuf;
+       int ret;
+
+       LOCK_TEST_WITH_RETURN( dev, filp );
+
+       DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t *) data,
+                                sizeof(cmdbuf));
+
+       DRM_DEBUG("via_pci_cmdbuffer, 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 mangement 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;
+
+       via_flush_write_combine();
+       while(! *(via_get_dma(dev_priv)-1));
+       *dev_priv->last_pause_ptr = pause_addr_lo;
+       via_flush_write_combine();
+
+       /*
+        * The below statement is inserted to really force the flush.
+        * Not sure it is needed.
+        */
+
+       while(! *dev_priv->last_pause_ptr);
+       dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
+       while(! *dev_priv->last_pause_ptr);
+
+
+       paused = 0;
+       count = 20; 
+
+       while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--);
+       if ((count <= 8) && (count >= 0)) {
+               uint32_t rgtr, ptr;
+               rgtr = *(dev_priv->hw_addr_ptr);
+               ptr = ((char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) + 
+                       dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4 - 
+                       CMDBUF_ALIGNMENT_SIZE;
+               if (rgtr <= ptr) {
+                       DRM_ERROR("Command regulator\npaused at count %d, address %x, "
+                                 "while current pause address is %x.\n"
+                                 "Please mail this message to "
+                                 "<unichrome-devel@lists.sourceforge.net>\n",
+                                 count, rgtr, ptr);
+               }
+       }
+               
+       if (paused && !no_pci_fire) {
+               uint32_t rgtr,ptr;
+               uint32_t ptr_low;
+
+               count = 1000000;
+               while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY) && count--);
+               
+               rgtr = *(dev_priv->hw_addr_ptr);
+               ptr = ((char *)paused_at - dev_priv->dma_ptr) + 
+                       dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
+               
+
+               ptr_low = (ptr > 3*CMDBUF_ALIGNMENT_SIZE) ? 
+                       ptr - 3*CMDBUF_ALIGNMENT_SIZE : 0;
+               if (rgtr <= ptr && rgtr >= ptr_low) {
+                       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);
+               } 
+       }
+       return paused;
+}
+
+
+
+static int via_wait_idle(drm_via_private_t * dev_priv)
+{
+       int count = 10000000;
+       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;
+
+
+       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();
+       while(! *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);
+
+       VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
+}
+
+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.
+ */
+
+int 
+via_cmdbuf_size(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_via_cmdbuf_size_t d_siz;
+       int ret = 0;
+       uint32_t tmp_size, count;
+       drm_via_private_t *dev_priv;
+
+       DRM_DEBUG("via cmdbuf_size\n");
+       LOCK_TEST_WITH_RETURN( dev, filp );
+
+       dev_priv = (drm_via_private_t *) dev->dev_private;
+
+       if (dev_priv->ring.virtual_start == NULL) {
+               DRM_ERROR("%s called without initializing AGP ring buffer.\n",
+                         __FUNCTION__);
+               return DRM_ERR(EFAULT);
+       }
+
+       DRM_COPY_FROM_USER_IOCTL(d_siz, (drm_via_cmdbuf_size_t *) data,
+                                sizeof(d_siz));
+
+
+       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 = DRM_ERR(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 = DRM_ERR(EAGAIN);
+               }
+               break;
+       default:
+               ret = DRM_ERR(EFAULT);
+       }
+       d_siz.size = tmp_size;
+
+       DRM_COPY_TO_USER_IOCTL((drm_via_cmdbuf_size_t *) data, d_siz,
+                              sizeof(d_siz));
+       return ret;
+}
diff --git a/drivers/char/drm/via_drm.h b/drivers/char/drm/via_drm.h
new file mode 100644 (file)
index 0000000..4588c9b
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * 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 drm_hw_lock_t *)(((((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_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)
+
+/* 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 VIDEO 0
+#define AGP 1
+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 *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;
+       drm_clip_rect_t 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 */
+
+} 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
+
+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;
+
+#ifdef __KERNEL__
+
+int via_fb_init(DRM_IOCTL_ARGS);
+int via_mem_alloc(DRM_IOCTL_ARGS);
+int via_mem_free(DRM_IOCTL_ARGS);
+int via_agp_init(DRM_IOCTL_ARGS);
+int via_map_init(DRM_IOCTL_ARGS);
+int via_decoder_futex(DRM_IOCTL_ARGS);
+int via_dma_init(DRM_IOCTL_ARGS);
+int via_cmdbuffer(DRM_IOCTL_ARGS);
+int via_flush_ioctl(DRM_IOCTL_ARGS);
+int via_pci_cmdbuffer(DRM_IOCTL_ARGS);
+int via_cmdbuf_size(DRM_IOCTL_ARGS);
+int via_wait_irq(DRM_IOCTL_ARGS);
+
+#endif
+#endif                         /* _VIA_DRM_H_ */
diff --git a/drivers/char/drm/via_drv.c b/drivers/char/drm/via_drv.c
new file mode 100644 (file)
index 0000000..275eefc
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * 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 <linux/config.h>
+#include "drmP.h"
+#include "via_drm.h"
+#include "via_drv.h"
+
+#include "drm_pciids.h"
+
+static int postinit(struct drm_device *dev, unsigned long flags)
+{
+       DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
+                DRIVER_NAME,
+                DRIVER_MAJOR,
+                DRIVER_MINOR,
+                DRIVER_PATCHLEVEL,
+                DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
+           );
+       return 0;
+}
+
+static int version(drm_version_t * version)
+{
+       int len;
+
+       version->version_major = DRIVER_MAJOR;
+       version->version_minor = DRIVER_MINOR;
+       version->version_patchlevel = DRIVER_PATCHLEVEL;
+       DRM_COPY(version->name, DRIVER_NAME);
+       DRM_COPY(version->date, DRIVER_DATE);
+       DRM_COPY(version->desc, DRIVER_DESC);
+       return 0;
+}
+
+static struct pci_device_id pciidlist[] = {
+       viadrv_PCI_IDS
+};
+
+static drm_ioctl_desc_t ioctls[] = {
+       [DRM_IOCTL_NR(DRM_VIA_ALLOCMEM)] = {via_mem_alloc, 1, 0},
+       [DRM_IOCTL_NR(DRM_VIA_FREEMEM)] = {via_mem_free, 1, 0},
+       [DRM_IOCTL_NR(DRM_VIA_AGP_INIT)] = {via_agp_init, 1, 0},
+       [DRM_IOCTL_NR(DRM_VIA_FB_INIT)] = {via_fb_init, 1, 0},
+       [DRM_IOCTL_NR(DRM_VIA_MAP_INIT)] = {via_map_init, 1, 0},
+       [DRM_IOCTL_NR(DRM_VIA_DEC_FUTEX)] = {via_decoder_futex, 1, 0},
+       [DRM_IOCTL_NR(DRM_VIA_DMA_INIT)] = {via_dma_init, 1, 0},
+       [DRM_IOCTL_NR(DRM_VIA_CMDBUFFER)] = {via_cmdbuffer, 1, 0},
+       [DRM_IOCTL_NR(DRM_VIA_FLUSH)] = {via_flush_ioctl, 1, 0},
+       [DRM_IOCTL_NR(DRM_VIA_PCICMD)] = {via_pci_cmdbuffer, 1, 0},
+       [DRM_IOCTL_NR(DRM_VIA_CMDBUF_SIZE)] = {via_cmdbuf_size, 1, 0},
+       [DRM_IOCTL_NR(DRM_VIA_WAIT_IRQ)] = {via_wait_irq, 1, 0}
+};
+
+static struct drm_driver driver = {
+       .driver_features =
+           DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
+           DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
+       .context_ctor = via_init_context,
+       .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,
+       .reclaim_buffers = drm_core_reclaim_buffers,
+       .get_map_ofs = drm_core_get_map_ofs,
+       .get_reg_ofs = drm_core_get_reg_ofs,
+       .postinit = postinit,
+       .version = version,
+       .ioctls = ioctls,
+       .num_ioctls = DRM_ARRAY_SIZE(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,
+       }
+};
+
+static int __init via_init(void)
+{
+       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
new file mode 100644 (file)
index 0000000..4eaa8b7
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * 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_
+
+#define DRIVER_AUTHOR  "VIA"
+
+#define DRIVER_NAME            "via"
+#define DRIVER_DESC            "VIA Unichrome / Pro"
+#define DRIVER_DATE            "20050523"
+
+#define DRIVER_MAJOR           2
+#define DRIVER_MINOR           6
+#define DRIVER_PATCHLEVEL      3
+
+#include "via_verifier.h"
+
+#define VIA_PCI_BUF_SIZE 60000
+#define VIA_FIRE_BUF_SIZE  1024
+#define VIA_NUM_IRQS 2
+
+
+
+typedef struct drm_via_ring_buffer {
+       drm_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_map_t *sarea;
+       drm_map_t *fb;
+       drm_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 pro_group_a;
+       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;      
+} drm_via_private_t;
+
+/* 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 int via_init_context(drm_device_t * dev, int context);
+extern int via_final_context(drm_device_t * dev, int context);
+
+extern int via_do_cleanup_map(drm_device_t * dev);
+extern int via_map_init(struct inode *inode, struct file *filp,
+                       unsigned int cmd, unsigned long arg);
+extern int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
+
+extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
+extern void via_driver_irq_preinstall(drm_device_t * dev);
+extern void via_driver_irq_postinstall(drm_device_t * dev);
+extern void via_driver_irq_uninstall(drm_device_t * dev);
+
+extern int via_dma_cleanup(drm_device_t * dev);
+extern void via_init_command_verifier(void);
+extern int via_driver_dma_quiescent(drm_device_t * 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);
+
+
+#endif
diff --git a/drivers/char/drm/via_ds.c b/drivers/char/drm/via_ds.c
new file mode 100644 (file)
index 0000000..daf3df7
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
+ * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
+ *
+ * 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 <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#include "via_ds.h"
+extern unsigned int VIA_DEBUG;
+
+set_t *via_setInit(void)
+{
+       int i;
+       set_t *set;
+       set = (set_t *) drm_alloc(sizeof(set_t), DRM_MEM_DRIVER);
+       for (i = 0; i < SET_SIZE; i++) {
+               set->list[i].free_next = i + 1;
+               set->list[i].alloc_next = -1;
+       }
+       set->list[SET_SIZE - 1].free_next = -1;
+       set->free = 0;
+       set->alloc = -1;
+       set->trace = -1;
+       return set;
+}
+
+int via_setAdd(set_t * set, ITEM_TYPE item)
+{
+       int free = set->free;
+       if (free != -1) {
+               set->list[free].val = item;
+               set->free = set->list[free].free_next;
+       } else {
+               return 0;
+       }
+       set->list[free].alloc_next = set->alloc;
+       set->alloc = free;
+       set->list[free].free_next = -1;
+       return 1;
+}
+
+int via_setDel(set_t * set, ITEM_TYPE item)
+{
+       int alloc = set->alloc;
+       int prev = -1;
+
+       while (alloc != -1) {
+               if (set->list[alloc].val == item) {
+                       if (prev != -1)
+                               set->list[prev].alloc_next =
+                                   set->list[alloc].alloc_next;
+                       else
+                               set->alloc = set->list[alloc].alloc_next;
+                       break;
+               }
+               prev = alloc;
+               alloc = set->list[alloc].alloc_next;
+       }
+
+       if (alloc == -1)
+               return 0;
+
+       set->list[alloc].free_next = set->free;
+       set->free = alloc;
+       set->list[alloc].alloc_next = -1;
+
+       return 1;
+}
+
+/* setFirst -> setAdd -> setNext is wrong */
+
+int via_setFirst(set_t * set, ITEM_TYPE * item)
+{
+       if (set->alloc == -1)
+               return 0;
+
+       *item = set->list[set->alloc].val;
+       set->trace = set->list[set->alloc].alloc_next;
+
+       return 1;
+}
+
+int via_setNext(set_t * set, ITEM_TYPE * item)
+{
+       if (set->trace == -1)
+               return 0;
+
+       *item = set->list[set->trace].val;
+       set->trace = set->list[set->trace].alloc_next;
+
+       return 1;
+}
+
+int via_setDestroy(set_t * set)
+{
+       drm_free(set, sizeof(set_t), DRM_MEM_DRIVER);
+
+       return 1;
+}
+
+#define ISFREE(bptr) ((bptr)->free)
+
+#define fprintf(fmt, arg...) do{}while(0)
+
+memHeap_t *via_mmInit(int ofs, int size)
+{
+       PMemBlock blocks;
+
+       if (size <= 0)
+               return 0;
+
+       blocks = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER);
+
+       if (blocks) {
+               blocks->ofs = ofs;
+               blocks->size = size;
+               blocks->free = 1;
+               return (memHeap_t *) blocks;
+       } else
+               return 0;
+}
+
+static TMemBlock *SliceBlock(TMemBlock * p,
+                            int startofs, int size,
+                            int reserved, int alignment)
+{
+       TMemBlock *newblock;
+
+       /* break left */
+       if (startofs > p->ofs) {
+               newblock =
+                   (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
+                                            DRM_MEM_DRIVER);
+               newblock->ofs = startofs;
+               newblock->size = p->size - (startofs - p->ofs);
+               newblock->free = 1;
+               newblock->next = p->next;
+               p->size -= newblock->size;
+               p->next = newblock;
+               p = newblock;
+       }
+
+       /* break right */
+       if (size < p->size) {
+               newblock =
+                   (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
+                                            DRM_MEM_DRIVER);
+               newblock->ofs = startofs + size;
+               newblock->size = p->size - size;
+               newblock->free = 1;
+               newblock->next = p->next;
+               p->size = size;
+               p->next = newblock;
+       }
+
+       /* p = middle block */
+       p->align = alignment;
+       p->free = 0;
+       p->reserved = reserved;
+       return p;
+}
+
+PMemBlock via_mmAllocMem(memHeap_t * heap, int size, int align2,
+                        int startSearch)
+{
+       int mask, startofs, endofs;
+       TMemBlock *p;
+
+       if (!heap || align2 < 0 || size <= 0)
+               return NULL;
+
+       mask = (1 << align2) - 1;
+       startofs = 0;
+       p = (TMemBlock *) heap;
+
+       while (p) {
+               if (ISFREE(p)) {
+                       startofs = (p->ofs + mask) & ~mask;
+
+                       if (startofs < startSearch)
+                               startofs = startSearch;
+
+                       endofs = startofs + size;
+
+                       if (endofs <= (p->ofs + p->size))
+                               break;
+               }
+
+               p = p->next;
+       }
+
+       if (!p)
+               return NULL;
+
+       p = SliceBlock(p, startofs, size, 0, mask + 1);
+       p->heap = heap;
+
+       return p;
+}
+
+static __inline__ int Join2Blocks(TMemBlock * p)
+{
+       if (p->free && p->next && p->next->free) {
+               TMemBlock *q = p->next;
+               p->size += q->size;
+               p->next = q->next;
+               drm_free(q, sizeof(TMemBlock), DRM_MEM_DRIVER);
+
+               return 1;
+       }
+
+       return 0;
+}
+
+int via_mmFreeMem(PMemBlock b)
+{
+       TMemBlock *p, *prev;
+
+       if (!b)
+               return 0;
+
+       if (!b->heap) {
+               fprintf(stderr, "no heap\n");
+
+               return -1;
+       }
+
+       p = b->heap;
+       prev = NULL;
+
+       while (p && p != b) {
+               prev = p;
+               p = p->next;
+       }
+
+       if (!p || p->free || p->reserved) {
+               if (!p)
+                       fprintf(stderr, "block not found in heap\n");
+               else if (p->free)
+                       fprintf(stderr, "block already free\n");
+               else
+                       fprintf(stderr, "block is reserved\n");
+
+               return -1;
+       }
+
+       p->free = 1;
+       Join2Blocks(p);
+
+       if (prev)
+               Join2Blocks(prev);
+
+       return 0;
+}
diff --git a/drivers/char/drm/via_ds.h b/drivers/char/drm/via_ds.h
new file mode 100644 (file)
index 0000000..be9c7f9
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
+ * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
+ * 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_ds_h_
+#define _via_ds_h_
+
+#include "drmP.h"
+
+/* Set Data Structure */
+#define SET_SIZE 5000
+typedef unsigned long ITEM_TYPE;
+
+typedef struct {
+       ITEM_TYPE val;
+       int alloc_next, free_next;
+} list_item_t;
+
+typedef struct {
+       int alloc;
+       int free;
+       int trace;
+       list_item_t list[SET_SIZE];
+} set_t;
+
+set_t *via_setInit(void);
+int via_setAdd(set_t * set, ITEM_TYPE item);
+int via_setDel(set_t * set, ITEM_TYPE item);
+int via_setFirst(set_t * set, ITEM_TYPE * item);
+int via_setNext(set_t * set, ITEM_TYPE * item);
+int via_setDestroy(set_t * set);
+
+#endif
+
+#ifndef MM_INC
+#define MM_INC
+
+struct mem_block_t {
+       struct mem_block_t *next;
+       struct mem_block_t *heap;
+       int ofs, size;
+       int align;
+       int free:1;
+       int reserved:1;
+};
+typedef struct mem_block_t TMemBlock;
+typedef struct mem_block_t *PMemBlock;
+
+/* a heap is just the first block in a chain */
+typedef struct mem_block_t memHeap_t;
+
+static __inline__ int mmBlockSize(PMemBlock b)
+{
+       return b->size;
+}
+
+static __inline__ int mmOffset(PMemBlock b)
+{
+       return b->ofs;
+}
+
+static __inline__ void mmMarkReserved(PMemBlock b)
+{
+       b->reserved = 1;
+}
+
+/*
+ * input: total size in bytes
+ * return: a heap pointer if OK, NULL if error
+ */
+memHeap_t *via_mmInit(int ofs, int size);
+
+PMemBlock via_mmAllocMem(memHeap_t * heap, int size, int align2,
+                        int startSearch);
+
+/*
+ * Free block starts at offset
+ * input: pointer to a block
+ * return: 0 if OK, -1 if error
+ */
+int via_mmFreeMem(PMemBlock b);
+
+#endif
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
new file mode 100644 (file)
index 0000000..e8027f3
--- /dev/null
@@ -0,0 +1,339 @@
+/* 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)
+
+/*
+ * 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 }};
+static int via_num_pro_group_a = sizeof(via_pro_group_a_irqs)/sizeof(maskarray_t);
+
+static maskarray_t via_unichrome_irqs[] = {};
+static int via_num_unichrome = sizeof(via_unichrome_irqs)/sizeof(maskarray_t);
+
+
+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)
+{
+       drm_device_t *dev = (drm_device_t *) 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;
+               }
+               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(drm_device_t * 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("viadrv_vblank_wait\n");
+       if (!dev_priv) {
+               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+               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(drm_device_t * 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 = dev_priv->via_irqs;
+       int ret = 0;
+       maskarray_t *masks = dev_priv->irq_masks;
+
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
+       if (!dev_priv) {
+               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+               return DRM_ERR(EINVAL);
+       }
+
+       if (irq >= dev_priv->num_irqs ) {
+               DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__, irq);
+               return DRM_ERR(EINVAL);
+       }
+               
+       cur_irq += irq;
+
+       if (masks[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(drm_device_t * dev)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       u32 status;
+       drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+       int i;
+
+       DRM_DEBUG("driver_irq_preinstall: dev_priv: %p\n", dev_priv);
+       if (dev_priv) {
+
+               dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE;
+               dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
+
+               dev_priv->irq_masks = (dev_priv->pro_group_a) ?
+                       via_pro_group_a_irqs : via_unichrome_irqs;
+               dev_priv->num_irqs = (dev_priv->pro_group_a) ?
+                       via_num_pro_group_a : via_num_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(drm_device_t * dev)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       u32 status;
+
+       DRM_DEBUG("via_driver_irq_postinstall\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(drm_device_t * dev)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       u32 status;
+
+       DRM_DEBUG("driver_irq_uninstall)\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(DRM_IOCTL_ARGS)
+{
+       drm_file_t *priv = filp->private_data;
+       drm_device_t *dev = priv->head->dev;
+       drm_via_irqwait_t __user *argp = (void __user *)data;
+       drm_via_irqwait_t irqwait;
+       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 DRM_ERR(EINVAL);
+
+       DRM_COPY_FROM_USER_IOCTL(irqwait, argp, sizeof(irqwait));
+       if (irqwait.request.irq >= dev_priv->num_irqs) {
+               DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__, 
+                         irqwait.request.irq);
+               return DRM_ERR(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 DRM_ERR(EINVAL);
+       }
+
+       if (irqwait.request.type & VIA_IRQ_SIGNAL) {
+               DRM_ERROR("%s Signals on Via IRQs not implemented yet.\n", 
+                         __FUNCTION__);
+               return DRM_ERR(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;
+
+       DRM_COPY_TO_USER_IOCTL(argp, irqwait, sizeof(irqwait));
+
+       return ret;
+}
diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c
new file mode 100644 (file)
index 0000000..0be829b
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * 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(drm_device_t * dev, drm_via_init_t * init)
+{
+       drm_via_private_t *dev_priv;
+
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
+       dev_priv = drm_alloc(sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+       if (dev_priv == NULL)
+               return -ENOMEM;
+
+       memset(dev_priv, 0, sizeof(drm_via_private_t));
+
+       DRM_GETSAREA();
+       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 );
+       dev_priv->pro_group_a = (dev->pdev->device == 0x3118);
+
+       dev->dev_private = (void *)dev_priv;
+       return 0;
+}
+
+int via_do_cleanup_map(drm_device_t * dev)
+{
+       if (dev->dev_private) {
+
+               drm_via_private_t *dev_priv = dev->dev_private;
+
+               via_dma_cleanup(dev);
+
+               drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+               dev->dev_private = NULL;
+       }
+
+       return 0;
+}
+
+int via_map_init(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_via_init_t init;
+
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
+       DRM_COPY_FROM_USER_IOCTL(init, (drm_via_init_t *) data, sizeof(init));
+
+       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;
+}
+
+
diff --git a/drivers/char/drm/via_mm.c b/drivers/char/drm/via_mm.c
new file mode 100644 (file)
index 0000000..c22712f
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * 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 "via_ds.h"
+#include "via_mm.h"
+
+#define MAX_CONTEXT 100
+
+typedef struct {
+       int used;
+       int context;
+       set_t *sets[2];         /* 0 for frame buffer, 1 for AGP , 2 for System */
+} via_context_t;
+
+static via_context_t global_ppriv[MAX_CONTEXT];
+
+static int via_agp_alloc(drm_via_mem_t * mem);
+static int via_agp_free(drm_via_mem_t * mem);
+static int via_fb_alloc(drm_via_mem_t * mem);
+static int via_fb_free(drm_via_mem_t * mem);
+
+static int add_alloc_set(int context, int type, unsigned int val)
+{
+       int i, retval = 0;
+
+       for (i = 0; i < MAX_CONTEXT; i++) {
+               if (global_ppriv[i].used && global_ppriv[i].context == context) {
+                       retval = via_setAdd(global_ppriv[i].sets[type], val);
+                       break;
+               }
+       }
+
+       return retval;
+}
+
+static int del_alloc_set(int context, int type, unsigned int val)
+{
+       int i, retval = 0;
+
+       for (i = 0; i < MAX_CONTEXT; i++)
+               if (global_ppriv[i].used && global_ppriv[i].context == context) {
+                       retval = via_setDel(global_ppriv[i].sets[type], val);
+                       break;
+               }
+
+       return retval;
+}
+
+/* agp memory management */
+static memHeap_t *AgpHeap = NULL;
+
+int via_agp_init(DRM_IOCTL_ARGS)
+{
+       drm_via_agp_t agp;
+
+       DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t *) data, sizeof(agp));
+
+       AgpHeap = via_mmInit(agp.offset, agp.size);
+
+       DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)agp.offset, (unsigned long)agp.size);
+
+       return 0;
+}
+
+/* fb memory management */
+static memHeap_t *FBHeap = NULL;
+
+int via_fb_init(DRM_IOCTL_ARGS)
+{
+       drm_via_fb_t fb;
+
+       DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t *) data, sizeof(fb));
+
+       FBHeap = via_mmInit(fb.offset, fb.size);
+
+       DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)fb.offset, (unsigned long)fb.size);
+
+       return 0;
+}
+
+int via_init_context(struct drm_device *dev, int context)
+{
+       int i;
+
+       for (i = 0; i < MAX_CONTEXT; i++)
+               if (global_ppriv[i].used &&
+                   (global_ppriv[i].context == context))
+                       break;
+
+       if (i >= MAX_CONTEXT) {
+               for (i = 0; i < MAX_CONTEXT; i++) {
+                       if (!global_ppriv[i].used) {
+                               global_ppriv[i].context = context;
+                               global_ppriv[i].used = 1;
+                               global_ppriv[i].sets[0] = via_setInit();
+                               global_ppriv[i].sets[1] = via_setInit();
+                               DRM_DEBUG("init allocation set, socket=%d,"
+                                         " context = %d\n", i, context);
+                               break;
+                       }
+               }
+
+               if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
+                   (global_ppriv[i].sets[1] == NULL)) {
+                       return 0;
+               }
+       }
+
+       return 1;
+}
+
+int via_final_context(struct drm_device *dev, int context)
+{      
+        int i;
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+
+       for (i = 0; i < MAX_CONTEXT; i++)
+               if (global_ppriv[i].used &&
+                   (global_ppriv[i].context == context))
+                       break;
+
+       if (i < MAX_CONTEXT) {
+               set_t *set;
+               ITEM_TYPE item;
+               int retval;
+
+               DRM_DEBUG("find socket %d, context = %d\n", i, context);
+
+               /* Video Memory */
+               set = global_ppriv[i].sets[0];
+               retval = via_setFirst(set, &item);
+               while (retval) {
+                       DRM_DEBUG("free video memory 0x%lx\n", item);
+                       via_mmFreeMem((PMemBlock) item);
+                       retval = via_setNext(set, &item);
+               }
+               via_setDestroy(set);
+
+               /* AGP Memory */
+               set = global_ppriv[i].sets[1];
+               retval = via_setFirst(set, &item);
+               while (retval) {
+                       DRM_DEBUG("free agp memory 0x%lx\n", item);
+                       via_mmFreeMem((PMemBlock) item);
+                       retval = via_setNext(set, &item);
+               }
+               via_setDestroy(set);
+               global_ppriv[i].used = 0;
+       }
+       via_release_futex(dev_priv, context); 
+       
+                       
+#if defined(__linux__)
+       /* 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);
+       }
+#endif
+
+       return 1;
+}
+
+int via_mem_alloc(DRM_IOCTL_ARGS)
+{
+       drm_via_mem_t mem;
+
+       DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t *) data, sizeof(mem));
+
+       switch (mem.type) {
+       case VIDEO:
+               if (via_fb_alloc(&mem) < 0)
+                       return -EFAULT;
+               DRM_COPY_TO_USER_IOCTL((drm_via_mem_t *) data, mem,
+                                      sizeof(mem));
+               return 0;
+       case AGP:
+               if (via_agp_alloc(&mem) < 0)
+                       return -EFAULT;
+               DRM_COPY_TO_USER_IOCTL((drm_via_mem_t *) data, mem,
+                                      sizeof(mem));
+               return 0;
+       }
+
+       return -EFAULT;
+}
+
+static int via_fb_alloc(drm_via_mem_t * mem)
+{
+       drm_via_mm_t fb;
+       PMemBlock block;
+       int retval = 0;
+
+       if (!FBHeap)
+               return -1;
+
+       fb.size = mem->size;
+       fb.context = mem->context;
+
+       block = via_mmAllocMem(FBHeap, fb.size, 5, 0);
+       if (block) {
+               fb.offset = block->ofs;
+               fb.free = (unsigned long)block;
+               if (!add_alloc_set(fb.context, VIDEO, fb.free)) {
+                       DRM_DEBUG("adding to allocation set fails\n");
+                       via_mmFreeMem((PMemBlock) fb.free);
+                       retval = -1;
+               }
+       } else {
+               fb.offset = 0;
+               fb.size = 0;
+               fb.free = 0;
+               retval = -1;
+       }
+
+       mem->offset = fb.offset;
+       mem->index = fb.free;
+
+       DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size,
+                 (int)fb.offset);
+
+       return retval;
+}
+
+static int via_agp_alloc(drm_via_mem_t * mem)
+{
+       drm_via_mm_t agp;
+       PMemBlock block;
+       int retval = 0;
+
+       if (!AgpHeap)
+               return -1;
+
+       agp.size = mem->size;
+       agp.context = mem->context;
+
+       block = via_mmAllocMem(AgpHeap, agp.size, 5, 0);
+       if (block) {
+               agp.offset = block->ofs;
+               agp.free = (unsigned long)block;
+               if (!add_alloc_set(agp.context, AGP, agp.free)) {
+                       DRM_DEBUG("adding to allocation set fails\n");
+                       via_mmFreeMem((PMemBlock) agp.free);
+                       retval = -1;
+               }
+       } else {
+               agp.offset = 0;
+               agp.size = 0;
+               agp.free = 0;
+       }
+
+       mem->offset = agp.offset;
+       mem->index = agp.free;
+
+       DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size,
+                 (unsigned int)agp.offset);
+       return retval;
+}
+
+int via_mem_free(DRM_IOCTL_ARGS)
+{
+       drm_via_mem_t mem;
+
+       DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t *) data, sizeof(mem));
+
+       switch (mem.type) {
+
+       case VIDEO:
+               if (via_fb_free(&mem) == 0)
+                       return 0;
+               break;
+       case AGP:
+               if (via_agp_free(&mem) == 0)
+                       return 0;
+               break;
+       }
+
+       return -EFAULT;
+}
+
+static int via_fb_free(drm_via_mem_t * mem)
+{
+       drm_via_mm_t fb;
+       int retval = 0;
+
+       if (!FBHeap) {
+               return -1;
+       }
+
+       fb.free = mem->index;
+       fb.context = mem->context;
+
+       if (!fb.free) {
+               return -1;
+
+       }
+
+       via_mmFreeMem((PMemBlock) fb.free);
+
+       if (!del_alloc_set(fb.context, VIDEO, fb.free)) {
+               retval = -1;
+       }
+
+       DRM_DEBUG("free fb, free = %ld\n", fb.free);
+
+       return retval;
+}
+
+static int via_agp_free(drm_via_mem_t * mem)
+{
+       drm_via_mm_t agp;
+
+       int retval = 0;
+
+       agp.free = mem->index;
+       agp.context = mem->context;
+
+       if (!agp.free)
+               return -1;
+
+       via_mmFreeMem((PMemBlock) agp.free);
+
+       if (!del_alloc_set(agp.context, AGP, agp.free)) {
+               retval = -1;
+       }
+
+       DRM_DEBUG("free agp, free = %ld\n", agp.free);
+
+       return retval;
+}
diff --git a/drivers/char/drm/via_mm.h b/drivers/char/drm/via_mm.h
new file mode 100644 (file)
index 0000000..d57efda
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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_mm_h_
+#define _via_drm_mm_h_
+
+typedef struct {
+       unsigned int context;
+       unsigned int size;
+       unsigned long offset;
+       unsigned long free;
+} drm_via_mm_t;
+
+typedef struct {
+       unsigned int size;
+       unsigned long handle;
+       void *virtual;
+} drm_via_dma_t;
+
+#endif
diff --git a/drivers/char/drm/via_verifier.c b/drivers/char/drm/via_verifier.c
new file mode 100644 (file)
index 0000000..07923b0
--- /dev/null
@@ -0,0 +1,1061 @@
+/*
+ * 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 - buf_end) >= 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_map_t *
+via_drm_lookup_agp_map (drm_via_state_t *seq, unsigned long offset, unsigned long size, 
+                       drm_device_t *dev)
+{
+       struct list_head *list;
+       drm_map_list_t *r_list;
+       drm_map_t *map = seq->map_cache;
+
+       if (map && map->offset <= offset && (offset + size) <= (map->offset + map->size)) {
+               return map;
+       }
+               
+       list_for_each(list, &dev->maplist->head) {
+               r_list = (drm_map_list_t *) list;
+               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;
+
+                       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]);
+
+                       for (i=start; i<= end; ++i) {
+                               tmp = *addr++;
+                               if (tmp < lo) lo = tmp;
+                               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) - 0x2B);
+               cur_seq->pitch[cur_seq->texture][tmp] = (cmd & 0x00F00000) >> 20;
+               if (!tmp && (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, drm_device_t *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 pro_group_a = dev_priv->pro_group_a;
+       
+       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)) 
+                               state = state_header2;
+                       else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) 
+                               state = state_header1;
+                       else if (pro_group_a && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
+                               state = state_vheader5;
+                       else if (pro_group_a && (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:
+                       *hc_state = saved_state;
+                       return DRM_ERR(EINVAL);                 
+               }
+       }       
+       if (state == state_error) {
+               *hc_state = saved_state;
+               return DRM_ERR(EINVAL);
+       }
+       return 0;
+}
+
+int 
+via_parse_command_stream(drm_device_t *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 DRM_ERR(EINVAL);                 
+               }
+       }       
+       if (state == state_error) {
+               return DRM_ERR(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
new file mode 100644 (file)
index 0000000..a8e1359
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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];
+       drm_via_sequence_t unfinished;
+       int agp_texture;
+       int multitex;
+       drm_device_t *dev;
+       drm_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, 
+                                    drm_device_t *dev, int agp);
+
+#endif
diff --git a/drivers/char/drm/via_video.c b/drivers/char/drm/via_video.c
new file mode 100644 (file)
index 0000000..37a61c6
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * 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("%s\n", __FUNCTION__);
+
+       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;
+
+       for (i=0; i < VIA_NR_XVMC_LOCKS; ++i) {
+               lock = (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(DRM_IOCTL_ARGS)
+{
+       DRM_DEVICE;
+       drm_via_futex_t fx;
+       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("%s\n", __FUNCTION__);
+
+       DRM_COPY_FROM_USER_IOCTL(fx, (drm_via_futex_t *) data, sizeof(fx));
+
+       if (fx.lock > VIA_NR_XVMC_LOCKS)
+               return -EFAULT;
+
+       lock = (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 88cd858f74d0d12d9bfdcc255f5b36be0fac5068..cddb789902db3c8766cdc3c604ced656f31cf09b 100644 (file)
@@ -22,6 +22,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#include <linux/config.h>
 #include <linux/console.h>
 #include <linux/cpumask.h>
 #include <linux/init.h>
@@ -40,7 +41,6 @@
 #include <linux/delay.h>
 #include <asm/uaccess.h>
 #include <asm/hvconsole.h>
-#include <asm/vio.h>
 
 #define HVC_MAJOR      229
 #define HVC_MINOR      0
  */
 #define HVC_ALLOC_TTY_ADAPTERS 8
 
-static struct tty_driver *hvc_driver;
-#ifdef CONFIG_MAGIC_SYSRQ
-static int sysrq_pressed;
-#endif
-
 #define N_OUTBUF       16
 #define N_INBUF                16
 
 #define __ALIGNED__    __attribute__((__aligned__(8)))
 
+static struct tty_driver *hvc_driver;
+static struct task_struct *hvc_task;
+
+/* Picks up late kicks after list walk but before schedule() */
+static int hvc_kicked;
+
+#ifdef CONFIG_MAGIC_SYSRQ
+static int sysrq_pressed;
+#endif
+
 struct hvc_struct {
        spinlock_t lock;
        int index;
@@ -80,11 +85,11 @@ struct hvc_struct {
        char outbuf[N_OUTBUF] __ALIGNED__;
        int n_outbuf;
        uint32_t vtermno;
+       struct hv_ops *ops;
        int irq_requested;
        int irq;
        struct list_head next;
        struct kobject kobj; /* ref count & hvc_struct lifetime */
-       struct vio_dev *vdev;
 };
 
 /* dynamic list of hvc_struct instances */
@@ -96,27 +101,186 @@ static struct list_head hvc_structs = LIST_HEAD_INIT(hvc_structs);
  */
 static DEFINE_SPINLOCK(hvc_structs_lock);
 
+/*
+ * This value is used to assign a tty->index value to a hvc_struct based
+ * upon order of exposure via hvc_probe(), when we can not match it to
+ * a console canidate registered with hvc_instantiate().
+ */
+static int last_hvc = -1;
+
+/*
+ * Do not call this function with either the hvc_strucst_lock or the hvc_struct
+ * lock held.  If successful, this function increments the kobject reference
+ * count against the target hvc_struct so it should be released when finished.
+ */
+struct hvc_struct *hvc_get_by_index(int index)
+{
+       struct hvc_struct *hp;
+       unsigned long flags;
+
+       spin_lock(&hvc_structs_lock);
+
+       list_for_each_entry(hp, &hvc_structs, next) {
+               spin_lock_irqsave(&hp->lock, flags);
+               if (hp->index == index) {
+                       kobject_get(&hp->kobj);
+                       spin_unlock_irqrestore(&hp->lock, flags);
+                       spin_unlock(&hvc_structs_lock);
+                       return hp;
+               }
+               spin_unlock_irqrestore(&hp->lock, flags);
+       }
+       hp = NULL;
+
+       spin_unlock(&hvc_structs_lock);
+       return hp;
+}
+
+
 /*
  * Initial console vtermnos for console API usage prior to full console
  * initialization.  Any vty adapter outside this range will not have usable
  * console interfaces but can still be used as a tty device.  This has to be
  * static because kmalloc will not work during early console init.
  */
-static uint32_t vtermnos[MAX_NR_HVC_CONSOLES];
+static struct hv_ops *cons_ops[MAX_NR_HVC_CONSOLES];
+static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] =
+       {[0 ... MAX_NR_HVC_CONSOLES - 1] = -1};
 
-/* Used for accounting purposes */
-static int num_vterms = 0;
+/*
+ * Console APIs, NOT TTY.  These APIs are available immediately when
+ * hvc_console_setup() finds adapters.
+ */
 
-static struct task_struct *hvc_task;
+void hvc_console_print(struct console *co, const char *b, unsigned count)
+{
+       char c[16] __ALIGNED__;
+       unsigned i = 0, n = 0;
+       int r, donecr = 0, index = co->index;
+
+       /* Console access attempt outside of acceptable console range. */
+       if (index >= MAX_NR_HVC_CONSOLES)
+               return;
+
+       /* This console adapter was removed so it is not useable. */
+       if (vtermnos[index] < 0)
+               return;
+
+       while (count > 0 || i > 0) {
+               if (count > 0 && i < sizeof(c)) {
+                       if (b[n] == '\n' && !donecr) {
+                               c[i++] = '\r';
+                               donecr = 1;
+                       } else {
+                               c[i++] = b[n++];
+                               donecr = 0;
+                               --count;
+                       }
+               } else {
+                       r = cons_ops[index]->put_chars(vtermnos[index], c, i);
+                       if (r < 0) {
+                               /* throw away chars on error */
+                               i = 0;
+                       } else if (r > 0) {
+                               i -= r;
+                               if (i > 0)
+                                       memmove(c, c+r, i);
+                       }
+               }
+       }
+}
+
+static struct tty_driver *hvc_console_device(struct console *c, int *index)
+{
+       if (vtermnos[c->index] == -1)
+               return NULL;
+
+       *index = c->index;
+       return hvc_driver;
+}
+
+static int __init hvc_console_setup(struct console *co, char *options)
+{
+       if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES)
+               return -ENODEV;
+
+       if (vtermnos[co->index] == -1)
+               return -ENODEV;
+
+       return 0;
+}
+
+struct console hvc_con_driver = {
+       .name           = "hvc",
+       .write          = hvc_console_print,
+       .device         = hvc_console_device,
+       .setup          = hvc_console_setup,
+       .flags          = CON_PRINTBUFFER,
+       .index          = -1,
+};
 
 /*
- * This value is used to associate a tty->index value to a hvc_struct based
- * upon order of exposure via hvc_probe().
+ * Early console initialization.  Preceeds driver initialization.
+ *
+ * (1) we are first, and the user specified another driver
+ * -- index will remain -1
+ * (2) we are first and the user specified no driver
+ * -- index will be set to 0, then we will fail setup.
+ * (3)  we are first and the user specified our driver
+ * -- index will be set to user specified driver, and we will fail
+ * (4) we are after driver, and this initcall will register us
+ * -- if the user didn't specify a driver then the console will match
+ *
+ * Note that for cases 2 and 3, we will match later when the io driver
+ * calls hvc_instantiate() and call register again.
  */
-static int hvc_count = -1;
+static int __init hvc_console_init(void)
+{
+       register_console(&hvc_con_driver);
+       return 0;
+}
+console_initcall(hvc_console_init);
 
-/* Picks up late kicks after list walk but before schedule() */
-static int hvc_kicked;
+/*
+ * hvc_instantiate() is an early console discovery method which locates
+ * consoles * prior to the vio subsystem discovering them.  Hotplugged
+ * vty adapters do NOT get an hvc_instantiate() callback since they
+ * appear after early console init.
+ */
+int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops)
+{
+       struct hvc_struct *hp;
+
+       if (index < 0 || index >= MAX_NR_HVC_CONSOLES)
+               return -1;
+
+       if (vtermnos[index] != -1)
+               return -1;
+
+       /* make sure no no tty has been registerd in this index */
+       hp = hvc_get_by_index(index);
+       if (hp) {
+               kobject_put(&hp->kobj);
+               return -1;
+       }
+
+       vtermnos[index] = vtermno;
+       cons_ops[index] = ops;
+
+       /* reserve all indices upto and including this index */
+       if (last_hvc < index)
+               last_hvc = index;
+
+       /* if this index is what the user requested, then register
+        * now (setup won't fail at this point).  It's ok to just
+        * call register again if previously .setup failed.
+        */
+       if (index == hvc_con_driver.index)
+               register_console(&hvc_con_driver);
+
+       return 0;
+}
+EXPORT_SYMBOL(hvc_instantiate);
 
 /* Wake the sleeping khvcd */
 static void hvc_kick(void)
@@ -125,13 +289,17 @@ static void hvc_kick(void)
        wake_up_process(hvc_task);
 }
 
+static int hvc_poll(struct hvc_struct *hp);
+
 /*
  * NOTE: This API isn't used if the console adapter doesn't support interrupts.
  * In this case the console is poll driven.
  */
 static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
-       hvc_kick();
+       /* if hvc_poll request a repoll, then kick the hvcd thread */
+       if (hvc_poll(dev_instance))
+               hvc_kick();
        return IRQ_HANDLED;
 }
 
@@ -140,34 +308,6 @@ static void hvc_unthrottle(struct tty_struct *tty)
        hvc_kick();
 }
 
-/*
- * Do not call this function with either the hvc_strucst_lock or the hvc_struct
- * lock held.  If successful, this function increments the kobject reference
- * count against the target hvc_struct so it should be released when finished.
- */
-struct hvc_struct *hvc_get_by_index(int index)
-{
-       struct hvc_struct *hp;
-       unsigned long flags;
-
-       spin_lock(&hvc_structs_lock);
-
-       list_for_each_entry(hp, &hvc_structs, next) {
-               spin_lock_irqsave(&hp->lock, flags);
-               if (hp->index == index) {
-                       kobject_get(&hp->kobj);
-                       spin_unlock_irqrestore(&hp->lock, flags);
-                       spin_unlock(&hvc_structs_lock);
-                       return hp;
-               }
-               spin_unlock_irqrestore(&hp->lock, flags);
-       }
-       hp = NULL;
-
-       spin_unlock(&hvc_structs_lock);
-       return hp;
-}
-
 /*
  * The TTY interface won't be used until after the vio layer has exposed the vty
  * adapter to the kernel.
@@ -329,7 +469,7 @@ static void hvc_push(struct hvc_struct *hp)
 {
        int n;
 
-       n = hvc_put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf);
+       n = hp->ops->put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf);
        if (n <= 0) {
                if (n == 0)
                        return;
@@ -467,7 +607,7 @@ static int hvc_poll(struct hvc_struct *hp)
                        break;
                }
 
-               n = hvc_get_chars(hp->vtermno, buf, count);
+               n = hp->ops->get_chars(hp->vtermno, buf, count);
                if (n <= 0) {
                        /* Hangup the tty when disconnected from host */
                        if (n == -EPIPE) {
@@ -479,14 +619,17 @@ static int hvc_poll(struct hvc_struct *hp)
                }
                for (i = 0; i < n; ++i) {
 #ifdef CONFIG_MAGIC_SYSRQ
-                       /* Handle the SysRq Hack */
-                       if (buf[i] == '\x0f') { /* ^O -- should support a sequence */
-                               sysrq_pressed = 1;
-                               continue;
-                       } else if (sysrq_pressed) {
-                               handle_sysrq(buf[i], NULL, tty);
-                               sysrq_pressed = 0;
-                               continue;
+                       if (hp->index == hvc_con_driver.index) {
+                               /* Handle the SysRq Hack */
+                               /* XXX should support a sequence */
+                               if (buf[i] == '\x0f') { /* ^O */
+                                       sysrq_pressed = 1;
+                                       continue;
+                               } else if (sysrq_pressed) {
+                                       handle_sysrq(buf[i], NULL, tty);
+                                       sysrq_pressed = 0;
+                                       continue;
+                               }
                        }
 #endif /* CONFIG_MAGIC_SYSRQ */
                        tty_insert_flip_char(tty, buf[i], 0);
@@ -497,8 +640,8 @@ static int hvc_poll(struct hvc_struct *hp)
 
                /*
                 * Account for the total amount read in one loop, and if above
-                * 64 bytes, we do a quick schedule loop to let the tty grok the
-                * data and eventually throttle us.
+                * 64 bytes, we do a quick schedule loop to let the tty grok
+                * the data and eventually throttle us.
                 */
                read_total += n;
                if (read_total >= 64) {
@@ -542,7 +685,6 @@ int khvcd(void *unused)
                if (cpus_empty(cpus_in_xmon)) {
                        spin_lock(&hvc_structs_lock);
                        list_for_each_entry(hp, &hvc_structs, next) {
-                               /*hp = list_entry(node, struct hvc_struct, * next); */
                                poll_mask |= hvc_poll(hp);
                        }
                        spin_unlock(&hvc_structs_lock);
@@ -577,14 +719,6 @@ static struct tty_operations hvc_ops = {
        .chars_in_buffer = hvc_chars_in_buffer,
 };
 
-char hvc_driver_name[] = "hvc_console";
-
-static struct vio_device_id hvc_driver_table[] __devinitdata= {
-       {"serial", "hvterm1"},
-       { NULL, }
-};
-MODULE_DEVICE_TABLE(vio, hvc_driver_table);
-
 /* callback when the kboject ref count reaches zero. */
 static void destroy_hvc_struct(struct kobject *kobj)
 {
@@ -606,41 +740,51 @@ static struct kobj_type hvc_kobj_type = {
        .release = destroy_hvc_struct,
 };
 
-static int __devinit hvc_probe(
-               struct vio_dev *dev,
-               const struct vio_device_id *id)
+struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
+                                       struct hv_ops *ops)
 {
        struct hvc_struct *hp;
-
-       /* probed with invalid parameters. */
-       if (!dev || !id)
-               return -EPERM;
+       int i;
 
        hp = kmalloc(sizeof(*hp), GFP_KERNEL);
        if (!hp)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        memset(hp, 0x00, sizeof(*hp));
-       hp->vtermno = dev->unit_address;
-       hp->vdev = dev;
-       hp->vdev->dev.driver_data = hp;
-       hp->irq = dev->irq;
+
+       hp->vtermno = vtermno;
+       hp->irq = irq;
+       hp->ops = ops;
 
        kobject_init(&hp->kobj);
        hp->kobj.ktype = &hvc_kobj_type;
 
        spin_lock_init(&hp->lock);
        spin_lock(&hvc_structs_lock);
-       hp->index = ++hvc_count;
+
+       /*
+        * find index to use:
+        * see if this vterm id matches one registered for console.
+        */
+       for (i=0; i < MAX_NR_HVC_CONSOLES; i++)
+               if (vtermnos[i] == hp->vtermno)
+                       break;
+
+       /* no matching slot, just use a counter */
+       if (i >= MAX_NR_HVC_CONSOLES)
+               i = ++last_hvc;
+
+       hp->index = i;
+
        list_add_tail(&(hp->next), &hvc_structs);
        spin_unlock(&hvc_structs_lock);
 
-       return 0;
+       return hp;
 }
+EXPORT_SYMBOL(hvc_alloc);
 
-static int __devexit hvc_remove(struct vio_dev *dev)
+int __devexit hvc_remove(struct hvc_struct *hp)
 {
-       struct hvc_struct *hp = dev->dev.driver_data;
        unsigned long flags;
        struct kobject *kobjp;
        struct tty_struct *tty;
@@ -673,23 +817,14 @@ static int __devexit hvc_remove(struct vio_dev *dev)
                tty_hangup(tty);
        return 0;
 }
-
-static struct vio_driver hvc_vio_driver = {
-       .name           = hvc_driver_name,
-       .id_table       = hvc_driver_table,
-       .probe          = hvc_probe,
-       .remove         = hvc_remove,
-};
+EXPORT_SYMBOL(hvc_remove);
 
 /* Driver initialization.  Follow console initialization.  This is where the TTY
  * interfaces start to become available. */
 int __init hvc_init(void)
 {
-       int rc;
-
-       /* We need more than num_vterms adapters due to hotplug additions. */
+       /* We need more than hvc_count adapters due to hotplug additions. */
        hvc_driver = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
-       /* hvc_driver = alloc_tty_driver(num_vterms); */
        if (!hvc_driver)
                return -ENOMEM;
 
@@ -716,116 +851,20 @@ int __init hvc_init(void)
                return -EIO;
        }
 
-       /* Register as a vio device to receive callbacks */
-       rc = vio_register_driver(&hvc_vio_driver);
-
-       return rc;
+       return 0;
 }
+module_init(hvc_init);
 
-/* This isn't particularily necessary due to this being a console driver but it
- * is nice to be thorough */
+/* This isn't particularily necessary due to this being a console driver
+ * but it is nice to be thorough.
+ */
 static void __exit hvc_exit(void)
 {
        kthread_stop(hvc_task);
 
-       vio_unregister_driver(&hvc_vio_driver);
        tty_unregister_driver(hvc_driver);
        /* return tty_struct instances allocated in hvc_init(). */
        put_tty_driver(hvc_driver);
+       unregister_console(&hvc_con_driver);
 }
-
-/*
- * Console APIs, NOT TTY.  These APIs are available immediately when
- * hvc_console_setup() finds adapters.
- */
-
-/*
- * hvc_instantiate() is an early console discovery method which locates consoles
- * prior to the vio subsystem discovering them.  Hotplugged vty adapters do NOT
- * get an hvc_instantiate() callback since the appear after early console init.
- */
-int hvc_instantiate(uint32_t vtermno, int index)
-{
-       if (index < 0 || index >= MAX_NR_HVC_CONSOLES)
-               return -1;
-
-       if (vtermnos[index] != -1)
-               return -1;
-
-       vtermnos[index] = vtermno;
-       return 0;
-}
-
-void hvc_console_print(struct console *co, const char *b, unsigned count)
-{
-       char c[16] __ALIGNED__;
-       unsigned i = 0, n = 0;
-       int r, donecr = 0;
-
-       /* Console access attempt outside of acceptable console range. */
-       if (co->index >= MAX_NR_HVC_CONSOLES)
-               return;
-
-       /* This console adapter was removed so it is not useable. */
-       if (vtermnos[co->index] < 0)
-               return;
-
-       while (count > 0 || i > 0) {
-               if (count > 0 && i < sizeof(c)) {
-                       if (b[n] == '\n' && !donecr) {
-                               c[i++] = '\r';
-                               donecr = 1;
-                       } else {
-                               c[i++] = b[n++];
-                               donecr = 0;
-                               --count;
-                       }
-               } else {
-                       r = hvc_put_chars(vtermnos[co->index], c, i);
-                       if (r < 0) {
-                               /* throw away chars on error */
-                               i = 0;
-                       } else if (r > 0) {
-                               i -= r;
-                               if (i > 0)
-                                       memmove(c, c+r, i);
-                       }
-               }
-       }
-}
-
-static struct tty_driver *hvc_console_device(struct console *c, int *index)
-{
-       *index = c->index;
-       return hvc_driver;
-}
-
-static int __init hvc_console_setup(struct console *co, char *options)
-{
-       return 0;
-}
-
-struct console hvc_con_driver = {
-       .name           = "hvc",
-       .write          = hvc_console_print,
-       .device         = hvc_console_device,
-       .setup          = hvc_console_setup,
-       .flags          = CON_PRINTBUFFER,
-       .index          = -1,
-};
-
-/* Early console initialization.  Preceeds driver initialization. */
-static int __init hvc_console_init(void)
-{
-       int i;
-
-       for (i=0; i<MAX_NR_HVC_CONSOLES; i++)
-               vtermnos[i] = -1;
-       num_vterms = hvc_find_vtys();
-       register_console(&hvc_con_driver);
-       return 0;
-}
-console_initcall(hvc_console_init);
-
-module_init(hvc_init);
 module_exit(hvc_exit);
diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c
new file mode 100644 (file)
index 0000000..60bb915
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * vio driver interface to hvc_console.c
+ *
+ * This code was moved here to allow the remaing code to be reused as a
+ * generic polling mode with semi-reliable transport driver core to the
+ * console and tty subsystems.
+ *
+ *
+ * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
+ * Copyright (C) 2001 Paul Mackerras <paulus@au.ibm.com>, IBM
+ * Copyright (C) 2004 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Additional Author(s):
+ *  Ryan S. Arnold <rsa@us.ibm.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/types.h>
+#include <linux/init.h>
+#include <asm/hvconsole.h>
+#include <asm/vio.h>
+#include <asm/prom.h>
+
+char hvc_driver_name[] = "hvc_console";
+
+static struct vio_device_id hvc_driver_table[] __devinitdata = {
+       {"serial", "hvterm1"},
+       { NULL, }
+};
+MODULE_DEVICE_TABLE(vio, hvc_driver_table);
+
+static int filtered_get_chars(uint32_t vtermno, char *buf, int count)
+{
+       unsigned long got;
+       int i;
+
+       got = hvc_get_chars(vtermno, buf, count);
+
+       /*
+        * Work around a HV bug where it gives us a null
+        * after every \r.  -- paulus
+        */
+       for (i = 1; i < got; ++i) {
+               if (buf[i] == 0 && buf[i-1] == '\r') {
+                       --got;
+                       if (i < got)
+                               memmove(&buf[i], &buf[i+1],
+                                       got - i);
+               }
+       }
+       return got;
+}
+
+static struct hv_ops hvc_get_put_ops = {
+       .get_chars = filtered_get_chars,
+       .put_chars = hvc_put_chars,
+};
+
+static int __devinit hvc_vio_probe(struct vio_dev *vdev,
+                               const struct vio_device_id *id)
+{
+       struct hvc_struct *hp;
+
+       /* probed with invalid parameters. */
+       if (!vdev || !id)
+               return -EPERM;
+
+       hp = hvc_alloc(vdev->unit_address, vdev->irq, &hvc_get_put_ops);
+       if (IS_ERR(hp))
+               return PTR_ERR(hp);
+       dev_set_drvdata(&vdev->dev, hp);
+
+       return 0;
+}
+
+static int __devexit hvc_vio_remove(struct vio_dev *vdev)
+{
+       struct hvc_struct *hp = dev_get_drvdata(&vdev->dev);
+
+       return hvc_remove(hp);
+}
+
+static struct vio_driver hvc_vio_driver = {
+       .name           = hvc_driver_name,
+       .id_table       = hvc_driver_table,
+       .probe          = hvc_vio_probe,
+       .remove         = hvc_vio_remove,
+       .driver         = {
+               .owner  = THIS_MODULE,
+       }
+};
+
+static int hvc_vio_init(void)
+{
+       int rc;
+
+       /* Register as a vio device to receive callbacks */
+       rc = vio_register_driver(&hvc_vio_driver);
+
+       return rc;
+}
+module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */
+
+static void hvc_vio_exit(void)
+{
+       vio_unregister_driver(&hvc_vio_driver);
+}
+module_exit(hvc_vio_exit);
+
+/* the device tree order defines our numbering */
+static int hvc_find_vtys(void)
+{
+       struct device_node *vty;
+       int num_found = 0;
+
+       for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL;
+                       vty = of_find_node_by_name(vty, "vty")) {
+               uint32_t *vtermno;
+
+               /* We have statically defined space for only a certain number
+                * of console adapters.
+                */
+               if (num_found >= MAX_NR_HVC_CONSOLES)
+                       break;
+
+               vtermno = (uint32_t *)get_property(vty, "reg", NULL);
+               if (!vtermno)
+                       continue;
+
+               if (device_is_compatible(vty, "hvterm1")) {
+                       hvc_instantiate(*vtermno, num_found, &hvc_get_put_ops);
+                       ++num_found;
+               }
+       }
+
+       return num_found;
+}
+console_initcall(hvc_find_vtys);
index f1f1192ba2b50ce00706f2dbb1ee9c850f338329..a22aa940e01e15356e81164236853526c16bfb39 100644 (file)
@@ -291,15 +291,13 @@ static void dump_packet(uint8_t *packet)
        dump_hex(packet, header->len);
 }
 
-/* can't use hvc_get_chars because that strips CRs */
 static int hvsi_read(struct hvsi_struct *hp, char *buf, int count)
 {
        unsigned long got;
 
-       if (plpar_hcall(H_GET_TERM_CHAR, hp->vtermno, 0, 0, 0, &got,
-                       (unsigned long *)buf, (unsigned long *)buf+1) == H_Success)
-               return got;
-       return 0;
+       got = hvc_get_chars(hp->vtermno, buf, count);
+
+       return got;
 }
 
 static void hvsi_recv_control(struct hvsi_struct *hp, uint8_t *packet,
index edba5a35bf2171d635ceeb71c7f3776d2acda738..09103b3d8f05a26beae37b61d6160ccfb7911fc2 100644 (file)
@@ -770,10 +770,8 @@ send_signal:
                }
                if (c == '\n') {
                        if (L_ECHO(tty) || L_ECHONL(tty)) {
-                               if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
+                               if (tty->read_cnt >= N_TTY_BUF_SIZE-1)
                                        put_char('\a', tty);
-                                       return;
-                               }
                                opost('\n', tty);
                        }
                        goto handle_newline;
@@ -790,10 +788,8 @@ send_signal:
                         * XXX are EOL_CHAR and EOL2_CHAR echoed?!?
                         */
                        if (L_ECHO(tty)) {
-                               if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
+                               if (tty->read_cnt >= N_TTY_BUF_SIZE-1)
                                        put_char('\a', tty);
-                                       return;
-                               }
                                /* Record the column of first canon char. */
                                if (tty->canon_head == tty->read_head)
                                        tty->canon_column = tty->column;
@@ -862,12 +858,9 @@ static int n_tty_receive_room(struct tty_struct *tty)
         * that erase characters will be handled.  Other excess
         * characters will be beeped.
         */
-       if (tty->icanon && !tty->canon_data)
-               return N_TTY_BUF_SIZE;
-
-       if (left > 0)
-               return left;
-       return 0;
+       if (left <= 0)
+               left = tty->icanon && !tty->canon_data;
+       return left;
 }
 
 /**
@@ -1473,13 +1466,17 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file,
                        if (tty->driver->flush_chars)
                                tty->driver->flush_chars(tty);
                } else {
-                       c = tty->driver->write(tty, b, nr);
-                       if (c < 0) {
-                               retval = c;
-                               goto break_out;
+                       while (nr > 0) {
+                               c = tty->driver->write(tty, b, nr);
+                               if (c < 0) {
+                                       retval = c;
+                                       goto break_out;
+                               }
+                               if (!c)
+                                       break;
+                               b += c;
+                               nr -= c;
                        }
-                       b += c;
-                       nr -= c;
                }
                if (!nr)
                        break;
index 8f36b1758eb6fa61f783bf72088200b81d1413e9..7a0c7464812492166a14ebbd778c6e60cfb6dc0a 100644 (file)
@@ -71,7 +71,6 @@
 #include <linux/workqueue.h>
 #include <linux/hdlc.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -593,11 +592,6 @@ static dev_link_t *mgslpc_attach(void)
     dev_list = link;
 
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask =
-           CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-           CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-           CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &mgslpc_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
 
@@ -3093,6 +3087,7 @@ static struct pcmcia_driver mgslpc_driver = {
                .name   = "synclink_cs",
        },
        .attach         = mgslpc_attach,
+       .event          = mgslpc_event,
        .detach         = mgslpc_detach,
        .id_table       = mgslpc_ids,
 };
index 460b5d475edd2324628cc95ed13347807a74904b..6b11d6b2129f08cb9a800292f05f409e0b70835d 100644 (file)
@@ -271,7 +271,7 @@ static int random_write_wakeup_thresh = 128;
  * samples to avoid wasting CPU time and reduce lock contention.
  */
 
-static int trickle_thresh = INPUT_POOL_WORDS * 28;
+static int trickle_thresh __read_mostly = INPUT_POOL_WORDS * 28;
 
 static DEFINE_PER_CPU(int, trickle_count) = 0;
 
index af79805b5576f4b08ca02b357cd4f3fb96d23ec6..12d563c648f7377ce640bff741aa782c756c1051 100644 (file)
@@ -228,7 +228,7 @@ static struct sysrq_key_op sysrq_term_op = {
 
 static void moom_callback(void *ignored)
 {
-       out_of_memory(GFP_KERNEL);
+       out_of_memory(GFP_KERNEL, 0);
 }
 
 static DECLARE_WORK(moom_work, moom_callback, NULL);
index bf62dfe4976acc4f986886aa3e922c2c453d011a..7a7859dd0d9859869f0e851aef8ebf8017a16a89 100644 (file)
@@ -869,7 +869,7 @@ EXPORT_SYMBOL(cpufreq_get);
  *     cpufreq_suspend - let the low level driver prepare for suspend
  */
 
-static int cpufreq_suspend(struct sys_device * sysdev, u32 state)
+static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg)
 {
        int cpu = sysdev->id;
        unsigned int ret = 0;
@@ -897,7 +897,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, u32 state)
        }
 
        if (cpufreq_driver->suspend) {
-               ret = cpufreq_driver->suspend(cpu_policy, state);
+               ret = cpufreq_driver->suspend(cpu_policy, pmsg);
                if (ret) {
                        printk(KERN_ERR "cpufreq: suspend failed in ->suspend "
                                        "step on CPU %u\n", cpu_policy->cpu);
index 978d27d6452dd5b7e13216fdc3bf11711c0232c3..aac59751e1b46b01f919698d485c916fe08700bc 100644 (file)
@@ -46,7 +46,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -134,11 +133,6 @@ static dev_link_t *ide_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask =
-       CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-       CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-       CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &ide_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -497,6 +491,7 @@ static struct pcmcia_driver ide_cs_driver = {
                .name   = "ide-cs",
        },
        .attach         = ide_attach,
+       .event          = ide_event,
        .detach         = ide_detach,
        .id_table       = ide_ids,
 };
index 3cc3ff0cccb194b277eed00f7c13745f8f8cc323..79c8e2dd9c33cfdc0618b228067c0c1261140cb7 100644 (file)
@@ -7,6 +7,16 @@ config INFINIBAND
          any protocols you wish to use as well as drivers for your
          InfiniBand hardware.
 
+config INFINIBAND_USER_VERBS
+       tristate "InfiniBand userspace verbs support"
+       depends on INFINIBAND
+       ---help---
+         Userspace InfiniBand verbs support.  This is the kernel side
+         of userspace verbs, which allows userspace processes to
+         directly access InfiniBand hardware for fast-path
+         operations.  You will also need libibverbs and a hardware
+         driver library from <http://www.openib.org>.
+
 source "drivers/infiniband/hw/mthca/Kconfig"
 
 source "drivers/infiniband/ulp/ipoib/Kconfig"
index d2dbfb52c0a3169c287475199f4a681a3f06ca13..e1a7cf3e86368982f68f2f224d01f4142fc92164 100644 (file)
@@ -1,6 +1,7 @@
 EXTRA_CFLAGS += -Idrivers/infiniband/include
 
-obj-$(CONFIG_INFINIBAND) +=    ib_core.o ib_mad.o ib_sa.o ib_umad.o
+obj-$(CONFIG_INFINIBAND) +=            ib_core.o ib_mad.o ib_sa.o ib_umad.o
+obj-$(CONFIG_INFINIBAND_USER_VERBS) += ib_uverbs.o
 
 ib_core-y :=                   packer.o ud_header.o verbs.o sysfs.o \
                                device.o fmr_pool.o cache.o
@@ -10,3 +11,5 @@ ib_mad-y :=                   mad.o smi.o agent.o
 ib_sa-y :=                     sa_query.o
 
 ib_umad-y :=                   user_mad.o
+
+ib_uverbs-y :=                 uverbs_main.o uverbs_cmd.o uverbs_mem.o
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
new file mode 100644 (file)
index 0000000..57347f1
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * 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.
+ *
+ * $Id: uverbs.h 2559 2005-06-06 19:43:16Z roland $
+ */
+
+#ifndef UVERBS_H
+#define UVERBS_H
+
+/* Include device.h and fs.h until cdev.h is self-sufficient */
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/kref.h>
+#include <linux/idr.h>
+
+#include <ib_verbs.h>
+#include <ib_user_verbs.h>
+
+struct ib_uverbs_device {
+       int                                     devnum;
+       struct cdev                             dev;
+       struct class_device                     class_dev;
+       struct ib_device                       *ib_dev;
+       int                                     num_comp;
+};
+
+struct ib_uverbs_event_file {
+       struct kref                             ref;
+       struct ib_uverbs_file                  *uverbs_file;
+       spinlock_t                              lock;
+       int                                     fd;
+       int                                     is_async;
+       wait_queue_head_t                       poll_wait;
+       struct list_head                        event_list;
+};
+
+struct ib_uverbs_file {
+       struct kref                             ref;
+       struct ib_uverbs_device                *device;
+       struct ib_ucontext                     *ucontext;
+       struct ib_event_handler                 event_handler;
+       struct ib_uverbs_event_file             async_file;
+       struct ib_uverbs_event_file             comp_file[1];
+};
+
+struct ib_uverbs_async_event {
+       struct ib_uverbs_async_event_desc       desc;
+       struct list_head                        list;
+};
+
+struct ib_uverbs_comp_event {
+       struct ib_uverbs_comp_event_desc        desc;
+       struct list_head                        list;
+};
+
+struct ib_uobject_mr {
+       struct ib_uobject                       uobj;
+       struct page                            *page_list;
+       struct scatterlist                     *sg_list;
+};
+
+extern struct semaphore ib_uverbs_idr_mutex;
+extern struct idr ib_uverbs_pd_idr;
+extern struct idr ib_uverbs_mr_idr;
+extern struct idr ib_uverbs_mw_idr;
+extern struct idr ib_uverbs_ah_idr;
+extern struct idr ib_uverbs_cq_idr;
+extern struct idr ib_uverbs_qp_idr;
+
+void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context);
+void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr);
+void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
+
+int ib_umem_get(struct ib_device *dev, struct ib_umem *mem,
+               void *addr, size_t size, int write);
+void ib_umem_release(struct ib_device *dev, struct ib_umem *umem);
+void ib_umem_release_on_close(struct ib_device *dev, struct ib_umem *umem);
+
+#define IB_UVERBS_DECLARE_CMD(name)                                    \
+       ssize_t ib_uverbs_##name(struct ib_uverbs_file *file,           \
+                                const char __user *buf, int in_len,    \
+                                int out_len)
+
+IB_UVERBS_DECLARE_CMD(query_params);
+IB_UVERBS_DECLARE_CMD(get_context);
+IB_UVERBS_DECLARE_CMD(query_device);
+IB_UVERBS_DECLARE_CMD(query_port);
+IB_UVERBS_DECLARE_CMD(query_gid);
+IB_UVERBS_DECLARE_CMD(query_pkey);
+IB_UVERBS_DECLARE_CMD(alloc_pd);
+IB_UVERBS_DECLARE_CMD(dealloc_pd);
+IB_UVERBS_DECLARE_CMD(reg_mr);
+IB_UVERBS_DECLARE_CMD(dereg_mr);
+IB_UVERBS_DECLARE_CMD(create_cq);
+IB_UVERBS_DECLARE_CMD(destroy_cq);
+IB_UVERBS_DECLARE_CMD(create_qp);
+IB_UVERBS_DECLARE_CMD(modify_qp);
+IB_UVERBS_DECLARE_CMD(destroy_qp);
+IB_UVERBS_DECLARE_CMD(attach_mcast);
+IB_UVERBS_DECLARE_CMD(detach_mcast);
+
+#endif /* UVERBS_H */
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
new file mode 100644 (file)
index 0000000..5f2bbcd
--- /dev/null
@@ -0,0 +1,1006 @@
+/*
+ * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * 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.
+ *
+ * $Id: uverbs_cmd.c 2708 2005-06-24 17:27:21Z roland $
+ */
+
+#include <asm/uaccess.h>
+
+#include "uverbs.h"
+
+#define INIT_UDATA(udata, ibuf, obuf, ilen, olen)                      \
+       do {                                                            \
+               (udata)->inbuf  = (void __user *) (ibuf);               \
+               (udata)->outbuf = (void __user *) (obuf);               \
+               (udata)->inlen  = (ilen);                               \
+               (udata)->outlen = (olen);                               \
+       } while (0)
+
+ssize_t ib_uverbs_query_params(struct ib_uverbs_file *file,
+                              const char __user *buf,
+                              int in_len, int out_len)
+{
+       struct ib_uverbs_query_params      cmd;
+       struct ib_uverbs_query_params_resp resp;
+
+       if (out_len < sizeof resp)
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       memset(&resp, 0, sizeof resp);
+
+       resp.num_cq_events = file->device->num_comp;
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp))
+           return -EFAULT;
+
+       return in_len;
+}
+
+ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
+                             const char __user *buf,
+                             int in_len, int out_len)
+{
+       struct ib_uverbs_get_context      cmd;
+       struct ib_uverbs_get_context_resp resp;
+       struct ib_udata                   udata;
+       struct ib_device                 *ibdev = file->device->ib_dev;
+       int i;
+       int ret = in_len;
+
+       if (out_len < sizeof resp)
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       INIT_UDATA(&udata, buf + sizeof cmd,
+                  (unsigned long) cmd.response + sizeof resp,
+                  in_len - sizeof cmd, out_len - sizeof resp);
+
+       file->ucontext = ibdev->alloc_ucontext(ibdev, &udata);
+       if (IS_ERR(file->ucontext)) {
+               ret = PTR_ERR(file->ucontext);
+               file->ucontext = NULL;
+               return ret;
+       }
+
+       file->ucontext->device = ibdev;
+       INIT_LIST_HEAD(&file->ucontext->pd_list);
+       INIT_LIST_HEAD(&file->ucontext->mr_list);
+       INIT_LIST_HEAD(&file->ucontext->mw_list);
+       INIT_LIST_HEAD(&file->ucontext->cq_list);
+       INIT_LIST_HEAD(&file->ucontext->qp_list);
+       INIT_LIST_HEAD(&file->ucontext->srq_list);
+       INIT_LIST_HEAD(&file->ucontext->ah_list);
+       spin_lock_init(&file->ucontext->lock);
+
+       resp.async_fd = file->async_file.fd;
+       for (i = 0; i < file->device->num_comp; ++i)
+               if (copy_to_user((void __user *) (unsigned long) cmd.cq_fd_tab +
+                                i * sizeof (__u32),
+                                &file->comp_file[i].fd, sizeof (__u32)))
+                       goto err;
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp))
+               goto err;
+
+       return in_len;
+
+err:
+       ibdev->dealloc_ucontext(file->ucontext);
+       file->ucontext = NULL;
+
+       return -EFAULT;
+}
+
+ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file,
+                              const char __user *buf,
+                              int in_len, int out_len)
+{
+       struct ib_uverbs_query_device      cmd;
+       struct ib_uverbs_query_device_resp resp;
+       struct ib_device_attr              attr;
+       int                                ret;
+
+       if (out_len < sizeof resp)
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       ret = ib_query_device(file->device->ib_dev, &attr);
+       if (ret)
+               return ret;
+
+       memset(&resp, 0, sizeof resp);
+
+       resp.fw_ver                    = attr.fw_ver;
+       resp.node_guid                 = attr.node_guid;
+       resp.sys_image_guid            = attr.sys_image_guid;
+       resp.max_mr_size               = attr.max_mr_size;
+       resp.page_size_cap             = attr.page_size_cap;
+       resp.vendor_id                 = attr.vendor_id;
+       resp.vendor_part_id            = attr.vendor_part_id;
+       resp.hw_ver                    = attr.hw_ver;
+       resp.max_qp                    = attr.max_qp;
+       resp.max_qp_wr                 = attr.max_qp_wr;
+       resp.device_cap_flags          = attr.device_cap_flags;
+       resp.max_sge                   = attr.max_sge;
+       resp.max_sge_rd                = attr.max_sge_rd;
+       resp.max_cq                    = attr.max_cq;
+       resp.max_cqe                   = attr.max_cqe;
+       resp.max_mr                    = attr.max_mr;
+       resp.max_pd                    = attr.max_pd;
+       resp.max_qp_rd_atom            = attr.max_qp_rd_atom;
+       resp.max_ee_rd_atom            = attr.max_ee_rd_atom;
+       resp.max_res_rd_atom           = attr.max_res_rd_atom;
+       resp.max_qp_init_rd_atom       = attr.max_qp_init_rd_atom;
+       resp.max_ee_init_rd_atom       = attr.max_ee_init_rd_atom;
+       resp.atomic_cap                = attr.atomic_cap;
+       resp.max_ee                    = attr.max_ee;
+       resp.max_rdd                   = attr.max_rdd;
+       resp.max_mw                    = attr.max_mw;
+       resp.max_raw_ipv6_qp           = attr.max_raw_ipv6_qp;
+       resp.max_raw_ethy_qp           = attr.max_raw_ethy_qp;
+       resp.max_mcast_grp             = attr.max_mcast_grp;
+       resp.max_mcast_qp_attach       = attr.max_mcast_qp_attach;
+       resp.max_total_mcast_qp_attach = attr.max_total_mcast_qp_attach;
+       resp.max_ah                    = attr.max_ah;
+       resp.max_fmr                   = attr.max_fmr;
+       resp.max_map_per_fmr           = attr.max_map_per_fmr;
+       resp.max_srq                   = attr.max_srq;
+       resp.max_srq_wr                = attr.max_srq_wr;
+       resp.max_srq_sge               = attr.max_srq_sge;
+       resp.max_pkeys                 = attr.max_pkeys;
+       resp.local_ca_ack_delay        = attr.local_ca_ack_delay;
+       resp.phys_port_cnt             = file->device->ib_dev->phys_port_cnt;
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp))
+               return -EFAULT;
+
+       return in_len;
+}
+
+ssize_t ib_uverbs_query_port(struct ib_uverbs_file *file,
+                            const char __user *buf,
+                            int in_len, int out_len)
+{
+       struct ib_uverbs_query_port      cmd;
+       struct ib_uverbs_query_port_resp resp;
+       struct ib_port_attr              attr;
+       int                              ret;
+
+       if (out_len < sizeof resp)
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       ret = ib_query_port(file->device->ib_dev, cmd.port_num, &attr);
+       if (ret)
+               return ret;
+
+       memset(&resp, 0, sizeof resp);
+
+       resp.state           = attr.state;
+       resp.max_mtu         = attr.max_mtu;
+       resp.active_mtu      = attr.active_mtu;
+       resp.gid_tbl_len     = attr.gid_tbl_len;
+       resp.port_cap_flags  = attr.port_cap_flags;
+       resp.max_msg_sz      = attr.max_msg_sz;
+       resp.bad_pkey_cntr   = attr.bad_pkey_cntr;
+       resp.qkey_viol_cntr  = attr.qkey_viol_cntr;
+       resp.pkey_tbl_len    = attr.pkey_tbl_len;
+       resp.lid             = attr.lid;
+       resp.sm_lid          = attr.sm_lid;
+       resp.lmc             = attr.lmc;
+       resp.max_vl_num      = attr.max_vl_num;
+       resp.sm_sl           = attr.sm_sl;
+       resp.subnet_timeout  = attr.subnet_timeout;
+       resp.init_type_reply = attr.init_type_reply;
+       resp.active_width    = attr.active_width;
+       resp.active_speed    = attr.active_speed;
+       resp.phys_state      = attr.phys_state;
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp))
+               return -EFAULT;
+
+       return in_len;
+}
+
+ssize_t ib_uverbs_query_gid(struct ib_uverbs_file *file,
+                           const char __user *buf,
+                           int in_len, int out_len)
+{
+       struct ib_uverbs_query_gid      cmd;
+       struct ib_uverbs_query_gid_resp resp;
+       int                             ret;
+
+       if (out_len < sizeof resp)
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       memset(&resp, 0, sizeof resp);
+
+       ret = ib_query_gid(file->device->ib_dev, cmd.port_num, cmd.index,
+                          (union ib_gid *) resp.gid);
+       if (ret)
+               return ret;
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp))
+               return -EFAULT;
+
+       return in_len;
+}
+
+ssize_t ib_uverbs_query_pkey(struct ib_uverbs_file *file,
+                            const char __user *buf,
+                            int in_len, int out_len)
+{
+       struct ib_uverbs_query_pkey      cmd;
+       struct ib_uverbs_query_pkey_resp resp;
+       int                              ret;
+
+       if (out_len < sizeof resp)
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       memset(&resp, 0, sizeof resp);
+
+       ret = ib_query_pkey(file->device->ib_dev, cmd.port_num, cmd.index,
+                           &resp.pkey);
+       if (ret)
+               return ret;
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp))
+               return -EFAULT;
+
+       return in_len;
+}
+
+ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
+                          const char __user *buf,
+                          int in_len, int out_len)
+{
+       struct ib_uverbs_alloc_pd      cmd;
+       struct ib_uverbs_alloc_pd_resp resp;
+       struct ib_udata                udata;
+       struct ib_uobject             *uobj;
+       struct ib_pd                  *pd;
+       int                            ret;
+
+       if (out_len < sizeof resp)
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       INIT_UDATA(&udata, buf + sizeof cmd,
+                  (unsigned long) cmd.response + sizeof resp,
+                  in_len - sizeof cmd, out_len - sizeof resp);
+
+       uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
+       if (!uobj)
+               return -ENOMEM;
+
+       uobj->context = file->ucontext;
+
+       pd = file->device->ib_dev->alloc_pd(file->device->ib_dev,
+                                           file->ucontext, &udata);
+       if (IS_ERR(pd)) {
+               ret = PTR_ERR(pd);
+               goto err;
+       }
+
+       pd->device  = file->device->ib_dev;
+       pd->uobject = uobj;
+       atomic_set(&pd->usecnt, 0);
+
+retry:
+       if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) {
+               ret = -ENOMEM;
+               goto err_pd;
+       }
+
+       down(&ib_uverbs_idr_mutex);
+       ret = idr_get_new(&ib_uverbs_pd_idr, pd, &uobj->id);
+       up(&ib_uverbs_idr_mutex);
+
+       if (ret == -EAGAIN)
+               goto retry;
+       if (ret)
+               goto err_pd;
+
+       spin_lock_irq(&file->ucontext->lock);
+       list_add_tail(&uobj->list, &file->ucontext->pd_list);
+       spin_unlock_irq(&file->ucontext->lock);
+
+       memset(&resp, 0, sizeof resp);
+       resp.pd_handle = uobj->id;
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp)) {
+               ret = -EFAULT;
+               goto err_list;
+       }
+
+       return in_len;
+
+err_list:
+       spin_lock_irq(&file->ucontext->lock);
+       list_del(&uobj->list);
+       spin_unlock_irq(&file->ucontext->lock);
+
+       down(&ib_uverbs_idr_mutex);
+       idr_remove(&ib_uverbs_pd_idr, uobj->id);
+       up(&ib_uverbs_idr_mutex);
+
+err_pd:
+       ib_dealloc_pd(pd);
+
+err:
+       kfree(uobj);
+       return ret;
+}
+
+ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
+                            const char __user *buf,
+                            int in_len, int out_len)
+{
+       struct ib_uverbs_dealloc_pd cmd;
+       struct ib_pd               *pd;
+       struct ib_uobject          *uobj;
+       int                         ret = -EINVAL;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       down(&ib_uverbs_idr_mutex);
+
+       pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
+       if (!pd || pd->uobject->context != file->ucontext)
+               goto out;
+
+       uobj = pd->uobject;
+
+       ret = ib_dealloc_pd(pd);
+       if (ret)
+               goto out;
+
+       idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle);
+
+       spin_lock_irq(&file->ucontext->lock);
+       list_del(&uobj->list);
+       spin_unlock_irq(&file->ucontext->lock);
+
+       kfree(uobj);
+
+out:
+       up(&ib_uverbs_idr_mutex);
+
+       return ret ? ret : in_len;
+}
+
+ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
+                        const char __user *buf, int in_len,
+                        int out_len)
+{
+       struct ib_uverbs_reg_mr      cmd;
+       struct ib_uverbs_reg_mr_resp resp;
+       struct ib_udata              udata;
+       struct ib_umem_object       *obj;
+       struct ib_pd                *pd;
+       struct ib_mr                *mr;
+       int                          ret;
+
+       if (out_len < sizeof resp)
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       INIT_UDATA(&udata, buf + sizeof cmd,
+                  (unsigned long) cmd.response + sizeof resp,
+                  in_len - sizeof cmd, out_len - sizeof resp);
+
+       if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK))
+               return -EINVAL;
+
+       obj = kmalloc(sizeof *obj, GFP_KERNEL);
+       if (!obj)
+               return -ENOMEM;
+
+       obj->uobject.context = file->ucontext;
+
+       /*
+        * We ask for writable memory if any access flags other than
+        * "remote read" are set.  "Local write" and "remote write"
+        * obviously require write access.  "Remote atomic" can do
+        * things like fetch and add, which will modify memory, and
+        * "MW bind" can change permissions by binding a window.
+        */
+       ret = ib_umem_get(file->device->ib_dev, &obj->umem,
+                         (void *) (unsigned long) cmd.start, cmd.length,
+                         !!(cmd.access_flags & ~IB_ACCESS_REMOTE_READ));
+       if (ret)
+               goto err_free;
+
+       obj->umem.virt_base = cmd.hca_va;
+
+       down(&ib_uverbs_idr_mutex);
+
+       pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
+       if (!pd || pd->uobject->context != file->ucontext) {
+               ret = -EINVAL;
+               goto err_up;
+       }
+
+       if (!pd->device->reg_user_mr) {
+               ret = -ENOSYS;
+               goto err_up;
+       }
+
+       mr = pd->device->reg_user_mr(pd, &obj->umem, cmd.access_flags, &udata);
+       if (IS_ERR(mr)) {
+               ret = PTR_ERR(mr);
+               goto err_up;
+       }
+
+       mr->device  = pd->device;
+       mr->pd      = pd;
+       mr->uobject = &obj->uobject;
+       atomic_inc(&pd->usecnt);
+       atomic_set(&mr->usecnt, 0);
+
+       memset(&resp, 0, sizeof resp);
+       resp.lkey = mr->lkey;
+       resp.rkey = mr->rkey;
+
+retry:
+       if (!idr_pre_get(&ib_uverbs_mr_idr, GFP_KERNEL)) {
+               ret = -ENOMEM;
+               goto err_unreg;
+       }
+
+       ret = idr_get_new(&ib_uverbs_mr_idr, mr, &obj->uobject.id);
+
+       if (ret == -EAGAIN)
+               goto retry;
+       if (ret)
+               goto err_unreg;
+
+       resp.mr_handle = obj->uobject.id;
+
+       spin_lock_irq(&file->ucontext->lock);
+       list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
+       spin_unlock_irq(&file->ucontext->lock);
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp)) {
+               ret = -EFAULT;
+               goto err_list;
+       }
+
+       up(&ib_uverbs_idr_mutex);
+
+       return in_len;
+
+err_list:
+       spin_lock_irq(&file->ucontext->lock);
+       list_del(&obj->uobject.list);
+       spin_unlock_irq(&file->ucontext->lock);
+
+err_unreg:
+       ib_dereg_mr(mr);
+
+err_up:
+       up(&ib_uverbs_idr_mutex);
+
+       ib_umem_release(file->device->ib_dev, &obj->umem);
+
+err_free:
+       kfree(obj);
+       return ret;
+}
+
+ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
+                          const char __user *buf, int in_len,
+                          int out_len)
+{
+       struct ib_uverbs_dereg_mr cmd;
+       struct ib_mr             *mr;
+       struct ib_umem_object    *memobj;
+       int                       ret = -EINVAL;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       down(&ib_uverbs_idr_mutex);
+
+       mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle);
+       if (!mr || mr->uobject->context != file->ucontext)
+               goto out;
+
+       memobj = container_of(mr->uobject, struct ib_umem_object, uobject);
+
+       ret = ib_dereg_mr(mr);
+       if (ret)
+               goto out;
+
+       idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle);
+
+       spin_lock_irq(&file->ucontext->lock);
+       list_del(&memobj->uobject.list);
+       spin_unlock_irq(&file->ucontext->lock);
+
+       ib_umem_release(file->device->ib_dev, &memobj->umem);
+       kfree(memobj);
+
+out:
+       up(&ib_uverbs_idr_mutex);
+
+       return ret ? ret : in_len;
+}
+
+ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
+                           const char __user *buf, int in_len,
+                           int out_len)
+{
+       struct ib_uverbs_create_cq      cmd;
+       struct ib_uverbs_create_cq_resp resp;
+       struct ib_udata                 udata;
+       struct ib_uobject              *uobj;
+       struct ib_cq                   *cq;
+       int                             ret;
+
+       if (out_len < sizeof resp)
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       INIT_UDATA(&udata, buf + sizeof cmd,
+                  (unsigned long) cmd.response + sizeof resp,
+                  in_len - sizeof cmd, out_len - sizeof resp);
+
+       if (cmd.event_handler >= file->device->num_comp)
+               return -EINVAL;
+
+       uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
+       if (!uobj)
+               return -ENOMEM;
+
+       uobj->user_handle = cmd.user_handle;
+       uobj->context     = file->ucontext;
+
+       cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe,
+                                            file->ucontext, &udata);
+       if (IS_ERR(cq)) {
+               ret = PTR_ERR(cq);
+               goto err;
+       }
+
+       cq->device        = file->device->ib_dev;
+       cq->uobject       = uobj;
+       cq->comp_handler  = ib_uverbs_comp_handler;
+       cq->event_handler = ib_uverbs_cq_event_handler;
+       cq->cq_context    = file;
+       atomic_set(&cq->usecnt, 0);
+
+retry:
+       if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) {
+               ret = -ENOMEM;
+               goto err_cq;
+       }
+
+       down(&ib_uverbs_idr_mutex);
+       ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->id);
+       up(&ib_uverbs_idr_mutex);
+
+       if (ret == -EAGAIN)
+               goto retry;
+       if (ret)
+               goto err_cq;
+
+       spin_lock_irq(&file->ucontext->lock);
+       list_add_tail(&uobj->list, &file->ucontext->cq_list);
+       spin_unlock_irq(&file->ucontext->lock);
+
+       memset(&resp, 0, sizeof resp);
+       resp.cq_handle = uobj->id;
+       resp.cqe       = cq->cqe;
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp)) {
+               ret = -EFAULT;
+               goto err_list;
+       }
+
+       return in_len;
+
+err_list:
+       spin_lock_irq(&file->ucontext->lock);
+       list_del(&uobj->list);
+       spin_unlock_irq(&file->ucontext->lock);
+
+       down(&ib_uverbs_idr_mutex);
+       idr_remove(&ib_uverbs_cq_idr, uobj->id);
+       up(&ib_uverbs_idr_mutex);
+
+err_cq:
+       ib_destroy_cq(cq);
+
+err:
+       kfree(uobj);
+       return ret;
+}
+
+ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
+                            const char __user *buf, int in_len,
+                            int out_len)
+{
+       struct ib_uverbs_destroy_cq cmd;
+       struct ib_cq               *cq;
+       struct ib_uobject          *uobj;
+       int                         ret = -EINVAL;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       down(&ib_uverbs_idr_mutex);
+
+       cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
+       if (!cq || cq->uobject->context != file->ucontext)
+               goto out;
+
+       uobj = cq->uobject;
+
+       ret = ib_destroy_cq(cq);
+       if (ret)
+               goto out;
+
+       idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle);
+
+       spin_lock_irq(&file->ucontext->lock);
+       list_del(&uobj->list);
+       spin_unlock_irq(&file->ucontext->lock);
+
+       kfree(uobj);
+
+out:
+       up(&ib_uverbs_idr_mutex);
+
+       return ret ? ret : in_len;
+}
+
+ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
+                           const char __user *buf, int in_len,
+                           int out_len)
+{
+       struct ib_uverbs_create_qp      cmd;
+       struct ib_uverbs_create_qp_resp resp;
+       struct ib_udata                 udata;
+       struct ib_uobject              *uobj;
+       struct ib_pd                   *pd;
+       struct ib_cq                   *scq, *rcq;
+       struct ib_qp                   *qp;
+       struct ib_qp_init_attr          attr;
+       int ret;
+
+       if (out_len < sizeof resp)
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       INIT_UDATA(&udata, buf + sizeof cmd,
+                  (unsigned long) cmd.response + sizeof resp,
+                  in_len - sizeof cmd, out_len - sizeof resp);
+
+       uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
+       if (!uobj)
+               return -ENOMEM;
+
+       down(&ib_uverbs_idr_mutex);
+
+       pd  = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
+       scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle);
+       rcq = idr_find(&ib_uverbs_cq_idr, cmd.recv_cq_handle);
+
+       if (!pd  || pd->uobject->context  != file->ucontext ||
+           !scq || scq->uobject->context != file->ucontext ||
+           !rcq || rcq->uobject->context != file->ucontext) {
+               ret = -EINVAL;
+               goto err_up;
+       }
+
+       attr.event_handler = ib_uverbs_qp_event_handler;
+       attr.qp_context    = file;
+       attr.send_cq       = scq;
+       attr.recv_cq       = rcq;
+       attr.srq           = NULL;
+       attr.sq_sig_type   = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
+       attr.qp_type       = cmd.qp_type;
+
+       attr.cap.max_send_wr     = cmd.max_send_wr;
+       attr.cap.max_recv_wr     = cmd.max_recv_wr;
+       attr.cap.max_send_sge    = cmd.max_send_sge;
+       attr.cap.max_recv_sge    = cmd.max_recv_sge;
+       attr.cap.max_inline_data = cmd.max_inline_data;
+
+       uobj->user_handle = cmd.user_handle;
+       uobj->context     = file->ucontext;
+
+       qp = pd->device->create_qp(pd, &attr, &udata);
+       if (IS_ERR(qp)) {
+               ret = PTR_ERR(qp);
+               goto err_up;
+       }
+
+       qp->device        = pd->device;
+       qp->pd            = pd;
+       qp->send_cq       = attr.send_cq;
+       qp->recv_cq       = attr.recv_cq;
+       qp->srq           = attr.srq;
+       qp->uobject       = uobj;
+       qp->event_handler = attr.event_handler;
+       qp->qp_context    = attr.qp_context;
+       qp->qp_type       = attr.qp_type;
+       atomic_inc(&pd->usecnt);
+       atomic_inc(&attr.send_cq->usecnt);
+       atomic_inc(&attr.recv_cq->usecnt);
+       if (attr.srq)
+               atomic_inc(&attr.srq->usecnt);
+
+       memset(&resp, 0, sizeof resp);
+       resp.qpn = qp->qp_num;
+
+retry:
+       if (!idr_pre_get(&ib_uverbs_qp_idr, GFP_KERNEL)) {
+               ret = -ENOMEM;
+               goto err_destroy;
+       }
+
+       ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->id);
+
+       if (ret == -EAGAIN)
+               goto retry;
+       if (ret)
+               goto err_destroy;
+
+       resp.qp_handle = uobj->id;
+
+       spin_lock_irq(&file->ucontext->lock);
+       list_add_tail(&uobj->list, &file->ucontext->qp_list);
+       spin_unlock_irq(&file->ucontext->lock);
+
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp)) {
+               ret = -EFAULT;
+               goto err_list;
+       }
+
+       up(&ib_uverbs_idr_mutex);
+
+       return in_len;
+
+err_list:
+       spin_lock_irq(&file->ucontext->lock);
+       list_del(&uobj->list);
+       spin_unlock_irq(&file->ucontext->lock);
+
+err_destroy:
+       ib_destroy_qp(qp);
+
+err_up:
+       up(&ib_uverbs_idr_mutex);
+
+       kfree(uobj);
+       return ret;
+}
+
+ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
+                           const char __user *buf, int in_len,
+                           int out_len)
+{
+       struct ib_uverbs_modify_qp cmd;
+       struct ib_qp              *qp;
+       struct ib_qp_attr         *attr;
+       int                        ret;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       attr = kmalloc(sizeof *attr, GFP_KERNEL);
+       if (!attr)
+               return -ENOMEM;
+
+       down(&ib_uverbs_idr_mutex);
+
+       qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
+       if (!qp || qp->uobject->context != file->ucontext) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       attr->qp_state            = cmd.qp_state;
+       attr->cur_qp_state        = cmd.cur_qp_state;
+       attr->path_mtu            = cmd.path_mtu;
+       attr->path_mig_state      = cmd.path_mig_state;
+       attr->qkey                = cmd.qkey;
+       attr->rq_psn              = cmd.rq_psn;
+       attr->sq_psn              = cmd.sq_psn;
+       attr->dest_qp_num         = cmd.dest_qp_num;
+       attr->qp_access_flags     = cmd.qp_access_flags;
+       attr->pkey_index          = cmd.pkey_index;
+       attr->alt_pkey_index      = cmd.pkey_index;
+       attr->en_sqd_async_notify = cmd.en_sqd_async_notify;
+       attr->max_rd_atomic       = cmd.max_rd_atomic;
+       attr->max_dest_rd_atomic  = cmd.max_dest_rd_atomic;
+       attr->min_rnr_timer       = cmd.min_rnr_timer;
+       attr->port_num            = cmd.port_num;
+       attr->timeout             = cmd.timeout;
+       attr->retry_cnt           = cmd.retry_cnt;
+       attr->rnr_retry           = cmd.rnr_retry;
+       attr->alt_port_num        = cmd.alt_port_num;
+       attr->alt_timeout         = cmd.alt_timeout;
+
+       memcpy(attr->ah_attr.grh.dgid.raw, cmd.dest.dgid, 16);
+       attr->ah_attr.grh.flow_label        = cmd.dest.flow_label;
+       attr->ah_attr.grh.sgid_index        = cmd.dest.sgid_index;
+       attr->ah_attr.grh.hop_limit         = cmd.dest.hop_limit;
+       attr->ah_attr.grh.traffic_class     = cmd.dest.traffic_class;
+       attr->ah_attr.dlid                  = cmd.dest.dlid;
+       attr->ah_attr.sl                    = cmd.dest.sl;
+       attr->ah_attr.src_path_bits         = cmd.dest.src_path_bits;
+       attr->ah_attr.static_rate           = cmd.dest.static_rate;
+       attr->ah_attr.ah_flags              = cmd.dest.is_global ? IB_AH_GRH : 0;
+       attr->ah_attr.port_num              = cmd.dest.port_num;
+
+       memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd.alt_dest.dgid, 16);
+       attr->alt_ah_attr.grh.flow_label    = cmd.alt_dest.flow_label;
+       attr->alt_ah_attr.grh.sgid_index    = cmd.alt_dest.sgid_index;
+       attr->alt_ah_attr.grh.hop_limit     = cmd.alt_dest.hop_limit;
+       attr->alt_ah_attr.grh.traffic_class = cmd.alt_dest.traffic_class;
+       attr->alt_ah_attr.dlid              = cmd.alt_dest.dlid;
+       attr->alt_ah_attr.sl                = cmd.alt_dest.sl;
+       attr->alt_ah_attr.src_path_bits     = cmd.alt_dest.src_path_bits;
+       attr->alt_ah_attr.static_rate       = cmd.alt_dest.static_rate;
+       attr->alt_ah_attr.ah_flags          = cmd.alt_dest.is_global ? IB_AH_GRH : 0;
+       attr->alt_ah_attr.port_num          = cmd.alt_dest.port_num;
+
+       ret = ib_modify_qp(qp, attr, cmd.attr_mask);
+       if (ret)
+               goto out;
+
+       ret = in_len;
+
+out:
+       up(&ib_uverbs_idr_mutex);
+       kfree(attr);
+
+       return ret;
+}
+
+ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
+                            const char __user *buf, int in_len,
+                            int out_len)
+{
+       struct ib_uverbs_destroy_qp cmd;
+       struct ib_qp               *qp;
+       struct ib_uobject          *uobj;
+       int                         ret = -EINVAL;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       down(&ib_uverbs_idr_mutex);
+
+       qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
+       if (!qp || qp->uobject->context != file->ucontext)
+               goto out;
+
+       uobj = qp->uobject;
+
+       ret = ib_destroy_qp(qp);
+       if (ret)
+               goto out;
+
+       idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle);
+
+       spin_lock_irq(&file->ucontext->lock);
+       list_del(&uobj->list);
+       spin_unlock_irq(&file->ucontext->lock);
+
+       kfree(uobj);
+
+out:
+       up(&ib_uverbs_idr_mutex);
+
+       return ret ? ret : in_len;
+}
+
+ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
+                              const char __user *buf, int in_len,
+                              int out_len)
+{
+       struct ib_uverbs_attach_mcast cmd;
+       struct ib_qp                 *qp;
+       int                           ret = -EINVAL;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       down(&ib_uverbs_idr_mutex);
+
+       qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
+       if (qp && qp->uobject->context == file->ucontext)
+               ret = ib_attach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid);
+
+       up(&ib_uverbs_idr_mutex);
+
+       return ret ? ret : in_len;
+}
+
+ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
+                              const char __user *buf, int in_len,
+                              int out_len)
+{
+       struct ib_uverbs_detach_mcast cmd;
+       struct ib_qp                 *qp;
+       int                           ret = -EINVAL;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       down(&ib_uverbs_idr_mutex);
+
+       qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
+       if (qp && qp->uobject->context == file->ucontext)
+               ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid);
+
+       up(&ib_uverbs_idr_mutex);
+
+       return ret ? ret : in_len;
+}
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
new file mode 100644 (file)
index 0000000..fbbe03d
--- /dev/null
@@ -0,0 +1,698 @@
+/*
+ * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * 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.
+ *
+ * $Id: uverbs_main.c 2733 2005-06-28 19:14:34Z roland $
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/file.h>
+#include <linux/mount.h>
+
+#include <asm/uaccess.h>
+
+#include "uverbs.h"
+
+MODULE_AUTHOR("Roland Dreier");
+MODULE_DESCRIPTION("InfiniBand userspace verbs access");
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define INFINIBANDEVENTFS_MAGIC        0x49426576      /* "IBev" */
+
+enum {
+       IB_UVERBS_MAJOR       = 231,
+       IB_UVERBS_BASE_MINOR  = 192,
+       IB_UVERBS_MAX_DEVICES = 32
+};
+
+#define IB_UVERBS_BASE_DEV     MKDEV(IB_UVERBS_MAJOR, IB_UVERBS_BASE_MINOR)
+
+DECLARE_MUTEX(ib_uverbs_idr_mutex);
+DEFINE_IDR(ib_uverbs_pd_idr);
+DEFINE_IDR(ib_uverbs_mr_idr);
+DEFINE_IDR(ib_uverbs_mw_idr);
+DEFINE_IDR(ib_uverbs_ah_idr);
+DEFINE_IDR(ib_uverbs_cq_idr);
+DEFINE_IDR(ib_uverbs_qp_idr);
+
+static spinlock_t map_lock;
+static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
+
+static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
+                                    const char __user *buf, int in_len,
+                                    int out_len) = {
+       [IB_USER_VERBS_CMD_QUERY_PARAMS]  = ib_uverbs_query_params,
+       [IB_USER_VERBS_CMD_GET_CONTEXT]   = ib_uverbs_get_context,
+       [IB_USER_VERBS_CMD_QUERY_DEVICE]  = ib_uverbs_query_device,
+       [IB_USER_VERBS_CMD_QUERY_PORT]    = ib_uverbs_query_port,
+       [IB_USER_VERBS_CMD_QUERY_GID]     = ib_uverbs_query_gid,
+       [IB_USER_VERBS_CMD_QUERY_PKEY]    = ib_uverbs_query_pkey,
+       [IB_USER_VERBS_CMD_ALLOC_PD]      = ib_uverbs_alloc_pd,
+       [IB_USER_VERBS_CMD_DEALLOC_PD]    = ib_uverbs_dealloc_pd,
+       [IB_USER_VERBS_CMD_REG_MR]        = ib_uverbs_reg_mr,
+       [IB_USER_VERBS_CMD_DEREG_MR]      = ib_uverbs_dereg_mr,
+       [IB_USER_VERBS_CMD_CREATE_CQ]     = ib_uverbs_create_cq,
+       [IB_USER_VERBS_CMD_DESTROY_CQ]    = ib_uverbs_destroy_cq,
+       [IB_USER_VERBS_CMD_CREATE_QP]     = ib_uverbs_create_qp,
+       [IB_USER_VERBS_CMD_MODIFY_QP]     = ib_uverbs_modify_qp,
+       [IB_USER_VERBS_CMD_DESTROY_QP]    = ib_uverbs_destroy_qp,
+       [IB_USER_VERBS_CMD_ATTACH_MCAST]  = ib_uverbs_attach_mcast,
+       [IB_USER_VERBS_CMD_DETACH_MCAST]  = ib_uverbs_detach_mcast,
+};
+
+static struct vfsmount *uverbs_event_mnt;
+
+static void ib_uverbs_add_one(struct ib_device *device);
+static void ib_uverbs_remove_one(struct ib_device *device);
+
+static int ib_dealloc_ucontext(struct ib_ucontext *context)
+{
+       struct ib_uobject *uobj, *tmp;
+
+       if (!context)
+               return 0;
+
+       down(&ib_uverbs_idr_mutex);
+
+       /* XXX Free AHs */
+
+       list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) {
+               struct ib_qp *qp = idr_find(&ib_uverbs_qp_idr, uobj->id);
+               idr_remove(&ib_uverbs_qp_idr, uobj->id);
+               ib_destroy_qp(qp);
+               list_del(&uobj->list);
+               kfree(uobj);
+       }
+
+       list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
+               struct ib_cq *cq = idr_find(&ib_uverbs_cq_idr, uobj->id);
+               idr_remove(&ib_uverbs_cq_idr, uobj->id);
+               ib_destroy_cq(cq);
+               list_del(&uobj->list);
+               kfree(uobj);
+       }
+
+       /* XXX Free SRQs */
+       /* XXX Free MWs */
+
+       list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) {
+               struct ib_mr *mr = idr_find(&ib_uverbs_mr_idr, uobj->id);
+               struct ib_umem_object *memobj;
+
+               idr_remove(&ib_uverbs_mr_idr, uobj->id);
+               ib_dereg_mr(mr);
+
+               memobj = container_of(uobj, struct ib_umem_object, uobject);
+               ib_umem_release_on_close(mr->device, &memobj->umem);
+
+               list_del(&uobj->list);
+               kfree(memobj);
+       }
+
+       list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) {
+               struct ib_pd *pd = idr_find(&ib_uverbs_pd_idr, uobj->id);
+               idr_remove(&ib_uverbs_pd_idr, uobj->id);
+               ib_dealloc_pd(pd);
+               list_del(&uobj->list);
+               kfree(uobj);
+       }
+
+       up(&ib_uverbs_idr_mutex);
+
+       return context->device->dealloc_ucontext(context);
+}
+
+static void ib_uverbs_release_file(struct kref *ref)
+{
+       struct ib_uverbs_file *file =
+               container_of(ref, struct ib_uverbs_file, ref);
+
+       module_put(file->device->ib_dev->owner);
+       kfree(file);
+}
+
+static ssize_t ib_uverbs_event_read(struct file *filp, char __user *buf,
+                                   size_t count, loff_t *pos)
+{
+       struct ib_uverbs_event_file *file = filp->private_data;
+       void *event;
+       int eventsz;
+       int ret = 0;
+
+       spin_lock_irq(&file->lock);
+
+       while (list_empty(&file->event_list) && file->fd >= 0) {
+               spin_unlock_irq(&file->lock);
+
+               if (filp->f_flags & O_NONBLOCK)
+                       return -EAGAIN;
+
+               if (wait_event_interruptible(file->poll_wait,
+                                            !list_empty(&file->event_list) ||
+                                            file->fd < 0))
+                       return -ERESTARTSYS;
+
+               spin_lock_irq(&file->lock);
+       }
+
+       if (file->fd < 0) {
+               spin_unlock_irq(&file->lock);
+               return -ENODEV;
+       }
+
+       if (file->is_async) {
+               event   = list_entry(file->event_list.next,
+                                    struct ib_uverbs_async_event, list);
+               eventsz = sizeof (struct ib_uverbs_async_event_desc);
+       } else {
+               event   = list_entry(file->event_list.next,
+                                    struct ib_uverbs_comp_event, list);
+               eventsz = sizeof (struct ib_uverbs_comp_event_desc);
+       }
+
+       if (eventsz > count) {
+               ret   = -EINVAL;
+               event = NULL;
+       } else
+               list_del(file->event_list.next);
+
+       spin_unlock_irq(&file->lock);
+
+       if (event) {
+               if (copy_to_user(buf, event, eventsz))
+                       ret = -EFAULT;
+               else
+                       ret = eventsz;
+       }
+
+       kfree(event);
+
+       return ret;
+}
+
+static unsigned int ib_uverbs_event_poll(struct file *filp,
+                                        struct poll_table_struct *wait)
+{
+       unsigned int pollflags = 0;
+       struct ib_uverbs_event_file *file = filp->private_data;
+
+       poll_wait(filp, &file->poll_wait, wait);
+
+       spin_lock_irq(&file->lock);
+       if (file->fd < 0)
+               pollflags = POLLERR;
+       else if (!list_empty(&file->event_list))
+               pollflags = POLLIN | POLLRDNORM;
+       spin_unlock_irq(&file->lock);
+
+       return pollflags;
+}
+
+static void ib_uverbs_event_release(struct ib_uverbs_event_file *file)
+{
+       struct list_head *entry, *tmp;
+
+       spin_lock_irq(&file->lock);
+       if (file->fd != -1) {
+               file->fd = -1;
+               list_for_each_safe(entry, tmp, &file->event_list)
+                       if (file->is_async)
+                               kfree(list_entry(entry, struct ib_uverbs_async_event, list));
+                       else
+                               kfree(list_entry(entry, struct ib_uverbs_comp_event, list));
+       }
+       spin_unlock_irq(&file->lock);
+}
+
+static int ib_uverbs_event_close(struct inode *inode, struct file *filp)
+{
+       struct ib_uverbs_event_file *file = filp->private_data;
+
+       ib_uverbs_event_release(file);
+       kref_put(&file->uverbs_file->ref, ib_uverbs_release_file);
+
+       return 0;
+}
+
+static struct file_operations uverbs_event_fops = {
+       /*
+        * No .owner field since we artificially create event files,
+        * so there is no increment to the module reference count in
+        * the open path.  All event files come from a uverbs command
+        * file, which already takes a module reference, so this is OK.
+        */
+       .read    = ib_uverbs_event_read,
+       .poll    = ib_uverbs_event_poll,
+       .release = ib_uverbs_event_close
+};
+
+void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
+{
+       struct ib_uverbs_file       *file = cq_context;
+       struct ib_uverbs_comp_event *entry;
+       unsigned long                flags;
+
+       entry = kmalloc(sizeof *entry, GFP_ATOMIC);
+       if (!entry)
+               return;
+
+       entry->desc.cq_handle = cq->uobject->user_handle;
+
+       spin_lock_irqsave(&file->comp_file[0].lock, flags);
+       list_add_tail(&entry->list, &file->comp_file[0].event_list);
+       spin_unlock_irqrestore(&file->comp_file[0].lock, flags);
+
+       wake_up_interruptible(&file->comp_file[0].poll_wait);
+}
+
+static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
+                                   __u64 element, __u64 event)
+{
+       struct ib_uverbs_async_event *entry;
+       unsigned long flags;
+
+       entry = kmalloc(sizeof *entry, GFP_ATOMIC);
+       if (!entry)
+               return;
+
+       entry->desc.element    = element;
+       entry->desc.event_type = event;
+
+       spin_lock_irqsave(&file->async_file.lock, flags);
+       list_add_tail(&entry->list, &file->async_file.event_list);
+       spin_unlock_irqrestore(&file->async_file.lock, flags);
+
+       wake_up_interruptible(&file->async_file.poll_wait);
+}
+
+void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr)
+{
+       ib_uverbs_async_handler(context_ptr,
+                               event->element.cq->uobject->user_handle,
+                               event->event);
+}
+
+void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr)
+{
+       ib_uverbs_async_handler(context_ptr,
+                               event->element.qp->uobject->user_handle,
+                               event->event);
+}
+
+static void ib_uverbs_event_handler(struct ib_event_handler *handler,
+                                   struct ib_event *event)
+{
+       struct ib_uverbs_file *file =
+               container_of(handler, struct ib_uverbs_file, event_handler);
+
+       ib_uverbs_async_handler(file, event->element.port_num, event->event);
+}
+
+static int ib_uverbs_event_init(struct ib_uverbs_event_file *file,
+                               struct ib_uverbs_file *uverbs_file)
+{
+       struct file *filp;
+
+       spin_lock_init(&file->lock);
+       INIT_LIST_HEAD(&file->event_list);
+       init_waitqueue_head(&file->poll_wait);
+       file->uverbs_file = uverbs_file;
+
+       file->fd = get_unused_fd();
+       if (file->fd < 0)
+               return file->fd;
+
+       filp = get_empty_filp();
+       if (!filp) {
+               put_unused_fd(file->fd);
+               return -ENFILE;
+       }
+
+       filp->f_op         = &uverbs_event_fops;
+       filp->f_vfsmnt     = mntget(uverbs_event_mnt);
+       filp->f_dentry     = dget(uverbs_event_mnt->mnt_root);
+       filp->f_mapping    = filp->f_dentry->d_inode->i_mapping;
+       filp->f_flags      = O_RDONLY;
+       filp->f_mode       = FMODE_READ;
+       filp->private_data = file;
+
+       fd_install(file->fd, filp);
+
+       return 0;
+}
+
+static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
+                            size_t count, loff_t *pos)
+{
+       struct ib_uverbs_file *file = filp->private_data;
+       struct ib_uverbs_cmd_hdr hdr;
+
+       if (count < sizeof hdr)
+               return -EINVAL;
+
+       if (copy_from_user(&hdr, buf, sizeof hdr))
+               return -EFAULT;
+
+       if (hdr.in_words * 4 != count)
+               return -EINVAL;
+
+       if (hdr.command < 0 || hdr.command >= ARRAY_SIZE(uverbs_cmd_table))
+               return -EINVAL;
+
+       if (!file->ucontext                               &&
+           hdr.command != IB_USER_VERBS_CMD_QUERY_PARAMS &&
+           hdr.command != IB_USER_VERBS_CMD_GET_CONTEXT)
+               return -EINVAL;
+
+       return uverbs_cmd_table[hdr.command](file, buf + sizeof hdr,
+                                            hdr.in_words * 4, hdr.out_words * 4);
+}
+
+static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+       struct ib_uverbs_file *file = filp->private_data;
+
+       if (!file->ucontext)
+               return -ENODEV;
+       else
+               return file->device->ib_dev->mmap(file->ucontext, vma);
+}
+
+static int ib_uverbs_open(struct inode *inode, struct file *filp)
+{
+       struct ib_uverbs_device *dev =
+               container_of(inode->i_cdev, struct ib_uverbs_device, dev);
+       struct ib_uverbs_file *file;
+       int i = 0;
+       int ret;
+
+       if (!try_module_get(dev->ib_dev->owner))
+               return -ENODEV;
+
+       file = kmalloc(sizeof *file +
+                      (dev->num_comp - 1) * sizeof (struct ib_uverbs_event_file),
+                      GFP_KERNEL);
+       if (!file)
+               return -ENOMEM;
+
+       file->device = dev;
+       kref_init(&file->ref);
+
+       file->ucontext = NULL;
+
+       ret = ib_uverbs_event_init(&file->async_file, file);
+       if (ret)
+               goto err;
+
+       file->async_file.is_async = 1;
+
+       kref_get(&file->ref);
+
+       for (i = 0; i < dev->num_comp; ++i) {
+               ret = ib_uverbs_event_init(&file->comp_file[i], file);
+               if (ret)
+                       goto err_async;
+               kref_get(&file->ref);
+               file->comp_file[i].is_async = 0;
+       }
+
+
+       filp->private_data = file;
+
+       INIT_IB_EVENT_HANDLER(&file->event_handler, dev->ib_dev,
+                             ib_uverbs_event_handler);
+       if (ib_register_event_handler(&file->event_handler))
+               goto err_async;
+
+       return 0;
+
+err_async:
+       while (i--)
+               ib_uverbs_event_release(&file->comp_file[i]);
+
+       ib_uverbs_event_release(&file->async_file);
+
+err:
+       kref_put(&file->ref, ib_uverbs_release_file);
+
+       return ret;
+}
+
+static int ib_uverbs_close(struct inode *inode, struct file *filp)
+{
+       struct ib_uverbs_file *file = filp->private_data;
+       int i;
+
+       ib_unregister_event_handler(&file->event_handler);
+       ib_uverbs_event_release(&file->async_file);
+       ib_dealloc_ucontext(file->ucontext);
+
+       for (i = 0; i < file->device->num_comp; ++i)
+               ib_uverbs_event_release(&file->comp_file[i]);
+
+       kref_put(&file->ref, ib_uverbs_release_file);
+
+       return 0;
+}
+
+static struct file_operations uverbs_fops = {
+       .owner   = THIS_MODULE,
+       .write   = ib_uverbs_write,
+       .open    = ib_uverbs_open,
+       .release = ib_uverbs_close
+};
+
+static struct file_operations uverbs_mmap_fops = {
+       .owner   = THIS_MODULE,
+       .write   = ib_uverbs_write,
+       .mmap    = ib_uverbs_mmap,
+       .open    = ib_uverbs_open,
+       .release = ib_uverbs_close
+};
+
+static struct ib_client uverbs_client = {
+       .name   = "uverbs",
+       .add    = ib_uverbs_add_one,
+       .remove = ib_uverbs_remove_one
+};
+
+static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
+{
+       struct ib_uverbs_device *dev =
+               container_of(class_dev, struct ib_uverbs_device, class_dev);
+
+       return sprintf(buf, "%s\n", dev->ib_dev->name);
+}
+static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
+
+static void ib_uverbs_release_class_dev(struct class_device *class_dev)
+{
+       struct ib_uverbs_device *dev =
+               container_of(class_dev, struct ib_uverbs_device, class_dev);
+
+       cdev_del(&dev->dev);
+       clear_bit(dev->devnum, dev_map);
+       kfree(dev);
+}
+
+static struct class uverbs_class = {
+       .name    = "infiniband_verbs",
+       .release = ib_uverbs_release_class_dev
+};
+
+static ssize_t show_abi_version(struct class *class, char *buf)
+{
+       return sprintf(buf, "%d\n", IB_USER_VERBS_ABI_VERSION);
+}
+static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
+
+static void ib_uverbs_add_one(struct ib_device *device)
+{
+       struct ib_uverbs_device *uverbs_dev;
+
+       if (!device->alloc_ucontext)
+               return;
+
+       uverbs_dev = kmalloc(sizeof *uverbs_dev, GFP_KERNEL);
+       if (!uverbs_dev)
+               return;
+
+       memset(uverbs_dev, 0, sizeof *uverbs_dev);
+
+       spin_lock(&map_lock);
+       uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
+       if (uverbs_dev->devnum >= IB_UVERBS_MAX_DEVICES) {
+               spin_unlock(&map_lock);
+               goto err;
+       }
+       set_bit(uverbs_dev->devnum, dev_map);
+       spin_unlock(&map_lock);
+
+       uverbs_dev->ib_dev   = device;
+       uverbs_dev->num_comp = 1;
+
+       if (device->mmap)
+               cdev_init(&uverbs_dev->dev, &uverbs_mmap_fops);
+       else
+               cdev_init(&uverbs_dev->dev, &uverbs_fops);
+       uverbs_dev->dev.owner = THIS_MODULE;
+       kobject_set_name(&uverbs_dev->dev.kobj, "uverbs%d", uverbs_dev->devnum);
+       if (cdev_add(&uverbs_dev->dev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
+               goto err;
+
+       uverbs_dev->class_dev.class = &uverbs_class;
+       uverbs_dev->class_dev.dev   = device->dma_device;
+       uverbs_dev->class_dev.devt  = uverbs_dev->dev.dev;
+       snprintf(uverbs_dev->class_dev.class_id, BUS_ID_SIZE, "uverbs%d", uverbs_dev->devnum);
+       if (class_device_register(&uverbs_dev->class_dev))
+               goto err_cdev;
+
+       if (class_device_create_file(&uverbs_dev->class_dev, &class_device_attr_ibdev))
+               goto err_class;
+
+       ib_set_client_data(device, &uverbs_client, uverbs_dev);
+
+       return;
+
+err_class:
+       class_device_unregister(&uverbs_dev->class_dev);
+
+err_cdev:
+       cdev_del(&uverbs_dev->dev);
+       clear_bit(uverbs_dev->devnum, dev_map);
+
+err:
+       kfree(uverbs_dev);
+       return;
+}
+
+static void ib_uverbs_remove_one(struct ib_device *device)
+{
+       struct ib_uverbs_device *uverbs_dev = ib_get_client_data(device, &uverbs_client);
+
+       if (!uverbs_dev)
+               return;
+
+       class_device_unregister(&uverbs_dev->class_dev);
+}
+
+static struct super_block *uverbs_event_get_sb(struct file_system_type *fs_type, int flags,
+                                              const char *dev_name, void *data)
+{
+       return get_sb_pseudo(fs_type, "infinibandevent:", NULL,
+                            INFINIBANDEVENTFS_MAGIC);
+}
+
+static struct file_system_type uverbs_event_fs = {
+       /* No owner field so module can be unloaded */
+       .name    = "infinibandeventfs",
+       .get_sb  = uverbs_event_get_sb,
+       .kill_sb = kill_litter_super
+};
+
+static int __init ib_uverbs_init(void)
+{
+       int ret;
+
+       spin_lock_init(&map_lock);
+
+       ret = register_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES,
+                                    "infiniband_verbs");
+       if (ret) {
+               printk(KERN_ERR "user_verbs: couldn't register device number\n");
+               goto out;
+       }
+
+       ret = class_register(&uverbs_class);
+       if (ret) {
+               printk(KERN_ERR "user_verbs: couldn't create class infiniband_verbs\n");
+               goto out_chrdev;
+       }
+
+       ret = class_create_file(&uverbs_class, &class_attr_abi_version);
+       if (ret) {
+               printk(KERN_ERR "user_verbs: couldn't create abi_version attribute\n");
+               goto out_class;
+       }
+
+       ret = register_filesystem(&uverbs_event_fs);
+       if (ret) {
+               printk(KERN_ERR "user_verbs: couldn't register infinibandeventfs\n");
+               goto out_class;
+       }
+
+       uverbs_event_mnt = kern_mount(&uverbs_event_fs);
+       if (IS_ERR(uverbs_event_mnt)) {
+               ret = PTR_ERR(uverbs_event_mnt);
+               printk(KERN_ERR "user_verbs: couldn't mount infinibandeventfs\n");
+               goto out_fs;
+       }
+
+       ret = ib_register_client(&uverbs_client);
+       if (ret) {
+               printk(KERN_ERR "user_verbs: couldn't register client\n");
+               goto out_mnt;
+       }
+
+       return 0;
+
+out_mnt:
+       mntput(uverbs_event_mnt);
+
+out_fs:
+       unregister_filesystem(&uverbs_event_fs);
+
+out_class:
+       class_unregister(&uverbs_class);
+
+out_chrdev:
+       unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
+
+out:
+       return ret;
+}
+
+static void __exit ib_uverbs_cleanup(void)
+{
+       ib_unregister_client(&uverbs_client);
+       mntput(uverbs_event_mnt);
+       unregister_filesystem(&uverbs_event_fs);
+       class_unregister(&uverbs_class);
+       unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);
+}
+
+module_init(ib_uverbs_init);
+module_exit(ib_uverbs_cleanup);
diff --git a/drivers/infiniband/core/uverbs_mem.c b/drivers/infiniband/core/uverbs_mem.c
new file mode 100644 (file)
index 0000000..ed550f6
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * 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.
+ *
+ * $Id: uverbs_mem.c 2743 2005-06-28 22:27:59Z roland $
+ */
+
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+
+#include "uverbs.h"
+
+struct ib_umem_account_work {
+       struct work_struct work;
+       struct mm_struct  *mm;
+       unsigned long      diff;
+};
+
+
+static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int dirty)
+{
+       struct ib_umem_chunk *chunk, *tmp;
+       int i;
+
+       list_for_each_entry_safe(chunk, tmp, &umem->chunk_list, list) {
+               dma_unmap_sg(dev->dma_device, chunk->page_list,
+                            chunk->nents, DMA_BIDIRECTIONAL);
+               for (i = 0; i < chunk->nents; ++i) {
+                       if (umem->writable && dirty)
+                               set_page_dirty_lock(chunk->page_list[i].page);
+                       put_page(chunk->page_list[i].page);
+               }
+
+               kfree(chunk);
+       }
+}
+
+int ib_umem_get(struct ib_device *dev, struct ib_umem *mem,
+               void *addr, size_t size, int write)
+{
+       struct page **page_list;
+       struct ib_umem_chunk *chunk;
+       unsigned long locked;
+       unsigned long lock_limit;
+       unsigned long cur_base;
+       unsigned long npages;
+       int ret = 0;
+       int off;
+       int i;
+
+       if (!can_do_mlock())
+               return -EPERM;
+
+       page_list = (struct page **) __get_free_page(GFP_KERNEL);
+       if (!page_list)
+               return -ENOMEM;
+
+       mem->user_base = (unsigned long) addr;
+       mem->length    = size;
+       mem->offset    = (unsigned long) addr & ~PAGE_MASK;
+       mem->page_size = PAGE_SIZE;
+       mem->writable  = write;
+
+       INIT_LIST_HEAD(&mem->chunk_list);
+
+       npages = PAGE_ALIGN(size + mem->offset) >> PAGE_SHIFT;
+
+       down_write(&current->mm->mmap_sem);
+
+       locked     = npages + current->mm->locked_vm;
+       lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
+
+       if ((locked > lock_limit) && !capable(CAP_IPC_LOCK)) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       cur_base = (unsigned long) addr & PAGE_MASK;
+
+       while (npages) {
+               ret = get_user_pages(current, current->mm, cur_base,
+                                    min_t(int, npages,
+                                          PAGE_SIZE / sizeof (struct page *)),
+                                    1, !write, page_list, NULL);
+
+               if (ret < 0)
+                       goto out;
+
+               cur_base += ret * PAGE_SIZE;
+               npages   -= ret;
+
+               off = 0;
+
+               while (ret) {
+                       chunk = kmalloc(sizeof *chunk + sizeof (struct scatterlist) *
+                                       min_t(int, ret, IB_UMEM_MAX_PAGE_CHUNK),
+                                       GFP_KERNEL);
+                       if (!chunk) {
+                               ret = -ENOMEM;
+                               goto out;
+                       }
+
+                       chunk->nents = min_t(int, ret, IB_UMEM_MAX_PAGE_CHUNK);
+                       for (i = 0; i < chunk->nents; ++i) {
+                               chunk->page_list[i].page   = page_list[i + off];
+                               chunk->page_list[i].offset = 0;
+                               chunk->page_list[i].length = PAGE_SIZE;
+                       }
+
+                       chunk->nmap = dma_map_sg(dev->dma_device,
+                                                &chunk->page_list[0],
+                                                chunk->nents,
+                                                DMA_BIDIRECTIONAL);
+                       if (chunk->nmap <= 0) {
+                               for (i = 0; i < chunk->nents; ++i)
+                                       put_page(chunk->page_list[i].page);
+                               kfree(chunk);
+
+                               ret = -ENOMEM;
+                               goto out;
+                       }
+
+                       ret -= chunk->nents;
+                       off += chunk->nents;
+                       list_add_tail(&chunk->list, &mem->chunk_list);
+               }
+
+               ret = 0;
+       }
+
+out:
+       if (ret < 0)
+               __ib_umem_release(dev, mem, 0);
+       else
+               current->mm->locked_vm = locked;
+
+       up_write(&current->mm->mmap_sem);
+       free_page((unsigned long) page_list);
+
+       return ret;
+}
+
+void ib_umem_release(struct ib_device *dev, struct ib_umem *umem)
+{
+       __ib_umem_release(dev, umem, 1);
+
+       down_write(&current->mm->mmap_sem);
+       current->mm->locked_vm -=
+               PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT;
+       up_write(&current->mm->mmap_sem);
+}
+
+static void ib_umem_account(void *work_ptr)
+{
+       struct ib_umem_account_work *work = work_ptr;
+
+       down_write(&work->mm->mmap_sem);
+       work->mm->locked_vm -= work->diff;
+       up_write(&work->mm->mmap_sem);
+       mmput(work->mm);
+       kfree(work);
+}
+
+void ib_umem_release_on_close(struct ib_device *dev, struct ib_umem *umem)
+{
+       struct ib_umem_account_work *work;
+       struct mm_struct *mm;
+
+       __ib_umem_release(dev, umem, 1);
+
+       mm = get_task_mm(current);
+       if (!mm)
+               return;
+
+       /*
+        * We may be called with the mm's mmap_sem already held.  This
+        * can happen when a userspace munmap() is the call that drops
+        * the last reference to our file and calls our release
+        * method.  If there are memory regions to destroy, we'll end
+        * up here and not be able to take the mmap_sem.  Therefore we
+        * defer the vm_locked accounting to the system workqueue.
+        */
+
+       work = kmalloc(sizeof *work, GFP_KERNEL);
+       if (!work)
+               return;
+
+       INIT_WORK(&work->work, ib_umem_account, work);
+       work->mm   = mm;
+       work->diff = PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT;
+
+       schedule_work(&work->work);
+}
index 7c08ed0cd7dd78d99a58c16fadda7bb13de797d7..2516f9646515c801e172a172dcf13db86a063cee 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (c) 2004 Intel Corporation.  All rights reserved.
  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
  * Copyright (c) 2004 Voltaire Corporation.  All rights reserved.
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -47,10 +48,11 @@ struct ib_pd *ib_alloc_pd(struct ib_device *device)
 {
        struct ib_pd *pd;
 
-       pd = device->alloc_pd(device);
+       pd = device->alloc_pd(device, NULL, NULL);
 
        if (!IS_ERR(pd)) {
-               pd->device = device;
+               pd->device  = device;
+               pd->uobject = NULL;
                atomic_set(&pd->usecnt, 0);
        }
 
@@ -76,8 +78,9 @@ struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
        ah = pd->device->create_ah(pd, ah_attr);
 
        if (!IS_ERR(ah)) {
-               ah->device = pd->device;
-               ah->pd     = pd;
+               ah->device  = pd->device;
+               ah->pd      = pd;
+               ah->uobject = NULL;
                atomic_inc(&pd->usecnt);
        }
 
@@ -122,7 +125,7 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
 {
        struct ib_qp *qp;
 
-       qp = pd->device->create_qp(pd, qp_init_attr);
+       qp = pd->device->create_qp(pd, qp_init_attr, NULL);
 
        if (!IS_ERR(qp)) {
                qp->device        = pd->device;
@@ -130,6 +133,7 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
                qp->send_cq       = qp_init_attr->send_cq;
                qp->recv_cq       = qp_init_attr->recv_cq;
                qp->srq           = qp_init_attr->srq;
+               qp->uobject       = NULL;
                qp->event_handler = qp_init_attr->event_handler;
                qp->qp_context    = qp_init_attr->qp_context;
                qp->qp_type       = qp_init_attr->qp_type;
@@ -197,10 +201,11 @@ struct ib_cq *ib_create_cq(struct ib_device *device,
 {
        struct ib_cq *cq;
 
-       cq = device->create_cq(device, cqe);
+       cq = device->create_cq(device, cqe, NULL, NULL);
 
        if (!IS_ERR(cq)) {
                cq->device        = device;
+               cq->uobject       = NULL;
                cq->comp_handler  = comp_handler;
                cq->event_handler = event_handler;
                cq->cq_context    = cq_context;
@@ -245,8 +250,9 @@ struct ib_mr *ib_get_dma_mr(struct ib_pd *pd, int mr_access_flags)
        mr = pd->device->get_dma_mr(pd, mr_access_flags);
 
        if (!IS_ERR(mr)) {
-               mr->device = pd->device;
-               mr->pd     = pd;
+               mr->device  = pd->device;
+               mr->pd      = pd;
+               mr->uobject = NULL;
                atomic_inc(&pd->usecnt);
                atomic_set(&mr->usecnt, 0);
        }
@@ -267,8 +273,9 @@ struct ib_mr *ib_reg_phys_mr(struct ib_pd *pd,
                                     mr_access_flags, iova_start);
 
        if (!IS_ERR(mr)) {
-               mr->device = pd->device;
-               mr->pd     = pd;
+               mr->device  = pd->device;
+               mr->pd      = pd;
+               mr->uobject = NULL;
                atomic_inc(&pd->usecnt);
                atomic_set(&mr->usecnt, 0);
        }
@@ -344,8 +351,9 @@ struct ib_mw *ib_alloc_mw(struct ib_pd *pd)
 
        mw = pd->device->alloc_mw(pd);
        if (!IS_ERR(mw)) {
-               mw->device = pd->device;
-               mw->pd     = pd;
+               mw->device  = pd->device;
+               mw->pd      = pd;
+               mw->uobject = NULL;
                atomic_inc(&pd->usecnt);
        }
 
index 766e9031ec4581bd05a4a727ee880b8689eeab3d..b5aea7b869f6c65bb9b820deb2f5566878126f16 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2005 Cisco Systems, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -742,6 +743,7 @@ err_out:
 }
 
 int mthca_init_cq(struct mthca_dev *dev, int nent,
+                 struct mthca_ucontext *ctx, u32 pdn,
                  struct mthca_cq *cq)
 {
        int size = nent * MTHCA_CQ_ENTRY_SIZE;
@@ -753,30 +755,33 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
 
        might_sleep();
 
-       cq->ibcq.cqe = nent - 1;
+       cq->ibcq.cqe  = nent - 1;
+       cq->is_kernel = !ctx;
 
        cq->cqn = mthca_alloc(&dev->cq_table.alloc);
        if (cq->cqn == -1)
                return -ENOMEM;
 
        if (mthca_is_memfree(dev)) {
-               cq->arm_sn = 1;
-
                err = mthca_table_get(dev, dev->cq_table.table, cq->cqn);
                if (err)
                        goto err_out;
 
-               err = -ENOMEM;
+               if (cq->is_kernel) {
+                       cq->arm_sn = 1;
+
+                       err = -ENOMEM;
 
-               cq->set_ci_db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_CQ_SET_CI,
-                                                    cq->cqn, &cq->set_ci_db);
-               if (cq->set_ci_db_index < 0)
-                       goto err_out_icm;
+                       cq->set_ci_db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_CQ_SET_CI,
+                                                            cq->cqn, &cq->set_ci_db);
+                       if (cq->set_ci_db_index < 0)
+                               goto err_out_icm;
 
-               cq->arm_db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_CQ_ARM,
-                                                 cq->cqn, &cq->arm_db);
-               if (cq->arm_db_index < 0)
-                       goto err_out_ci;
+                       cq->arm_db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_CQ_ARM,
+                                                         cq->cqn, &cq->arm_db);
+                       if (cq->arm_db_index < 0)
+                               goto err_out_ci;
+               }
        }
 
        mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
@@ -785,12 +790,14 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
 
        cq_context = mailbox->buf;
 
-       err = mthca_alloc_cq_buf(dev, size, cq);
-       if (err)
-               goto err_out_mailbox;
+       if (cq->is_kernel) {
+               err = mthca_alloc_cq_buf(dev, size, cq);
+               if (err)
+                       goto err_out_mailbox;
 
-       for (i = 0; i < nent; ++i)
-               set_cqe_hw(get_cqe(cq, i));
+               for (i = 0; i < nent; ++i)
+                       set_cqe_hw(get_cqe(cq, i));
+       }
 
        spin_lock_init(&cq->lock);
        atomic_set(&cq->refcount, 1);
@@ -801,11 +808,14 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
                                                  MTHCA_CQ_STATE_DISARMED |
                                                  MTHCA_CQ_FLAG_TR);
        cq_context->start           = cpu_to_be64(0);
-       cq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24 |
-                                                 dev->driver_uar.index);
+       cq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24);
+       if (ctx)
+               cq_context->logsize_usrpage |= cpu_to_be32(ctx->uar.index);
+       else
+               cq_context->logsize_usrpage |= cpu_to_be32(dev->driver_uar.index);
        cq_context->error_eqn       = cpu_to_be32(dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn);
        cq_context->comp_eqn        = cpu_to_be32(dev->eq_table.eq[MTHCA_EQ_COMP].eqn);
-       cq_context->pd              = cpu_to_be32(dev->driver_pd.pd_num);
+       cq_context->pd              = cpu_to_be32(pdn);
        cq_context->lkey            = cpu_to_be32(cq->mr.ibmr.lkey);
        cq_context->cqn             = cpu_to_be32(cq->cqn);
 
@@ -843,18 +853,20 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
        return 0;
 
 err_out_free_mr:
-       mthca_free_mr(dev, &cq->mr);
-       mthca_free_cq_buf(dev, cq);
+       if (cq->is_kernel) {
+               mthca_free_mr(dev, &cq->mr);
+               mthca_free_cq_buf(dev, cq);
+       }
 
 err_out_mailbox:
        mthca_free_mailbox(dev, mailbox);
 
 err_out_arm:
-       if (mthca_is_memfree(dev))
+       if (cq->is_kernel && mthca_is_memfree(dev))
                mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index);
 
 err_out_ci:
-       if (mthca_is_memfree(dev))
+       if (cq->is_kernel && mthca_is_memfree(dev))
                mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index);
 
 err_out_icm:
@@ -892,7 +904,8 @@ void mthca_free_cq(struct mthca_dev *dev,
                int j;
 
                printk(KERN_ERR "context for CQN %x (cons index %x, next sw %d)\n",
-                      cq->cqn, cq->cons_index, !!next_cqe_sw(cq));
+                      cq->cqn, cq->cons_index,
+                      cq->is_kernel ? !!next_cqe_sw(cq) : 0);
                for (j = 0; j < 16; ++j)
                        printk(KERN_ERR "[%2x] %08x\n", j * 4, be32_to_cpu(ctx[j]));
        }
@@ -910,12 +923,13 @@ void mthca_free_cq(struct mthca_dev *dev,
        atomic_dec(&cq->refcount);
        wait_event(cq->wait, !atomic_read(&cq->refcount));
 
-       mthca_free_mr(dev, &cq->mr);
-       mthca_free_cq_buf(dev, cq);
-
-       if (mthca_is_memfree(dev)) {
-               mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM,    cq->arm_db_index);
-               mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index);
+       if (cq->is_kernel) {
+               mthca_free_mr(dev, &cq->mr);
+               mthca_free_cq_buf(dev, cq);
+               if (mthca_is_memfree(dev)) {
+                       mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM,    cq->arm_db_index);
+                       mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index);
+               }
        }
 
        mthca_table_put(dev, dev->cq_table.table, cq->cqn);
index 4127f09dc5ec5cce6ffdb6133cc33a4e6904e3d7..5ecdd2eeeb0f0c18ac3e96e8c8b140acaee895ec 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -378,7 +379,7 @@ void mthca_unregister_device(struct mthca_dev *dev);
 int mthca_uar_alloc(struct mthca_dev *dev, struct mthca_uar *uar);
 void mthca_uar_free(struct mthca_dev *dev, struct mthca_uar *uar);
 
-int mthca_pd_alloc(struct mthca_dev *dev, struct mthca_pd *pd);
+int mthca_pd_alloc(struct mthca_dev *dev, int privileged, struct mthca_pd *pd);
 void mthca_pd_free(struct mthca_dev *dev, struct mthca_pd *pd);
 
 struct mthca_mtt *mthca_alloc_mtt(struct mthca_dev *dev, int size);
@@ -413,6 +414,7 @@ int mthca_poll_cq(struct ib_cq *ibcq, int num_entries,
 int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify);
 int mthca_arbel_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify);
 int mthca_init_cq(struct mthca_dev *dev, int nent,
+                 struct mthca_ucontext *ctx, u32 pdn,
                  struct mthca_cq *cq);
 void mthca_free_cq(struct mthca_dev *dev,
                   struct mthca_cq *cq);
@@ -438,12 +440,14 @@ int mthca_alloc_qp(struct mthca_dev *dev,
                   struct mthca_cq *recv_cq,
                   enum ib_qp_type type,
                   enum ib_sig_type send_policy,
+                  struct ib_qp_cap *cap,
                   struct mthca_qp *qp);
 int mthca_alloc_sqp(struct mthca_dev *dev,
                    struct mthca_pd *pd,
                    struct mthca_cq *send_cq,
                    struct mthca_cq *recv_cq,
                    enum ib_sig_type send_policy,
+                   struct ib_qp_cap *cap,
                    int qpn,
                    int port,
                    struct mthca_sqp *sqp);
index 09519b604c087bd11856d96cab5c4021b78aa3b6..2ef916859e1752427864a973df28ac27f8c006b9 100644 (file)
@@ -665,7 +665,7 @@ static int __devinit mthca_setup_hca(struct mthca_dev *dev)
                goto err_pd_table_free;
        }
 
-       err = mthca_pd_alloc(dev, &dev->driver_pd);
+       err = mthca_pd_alloc(dev, 1, &dev->driver_pd);
        if (err) {
                mthca_err(dev, "Failed to create driver PD, "
                          "aborting.\n");
index 6d3b05dd9e3f1d9ee779b9f16808df7bf9f01ad7..2a864615035510fa33d515cc5e6e406a086e42f4 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -47,6 +48,15 @@ enum {
        MTHCA_TABLE_CHUNK_SIZE = 1 << 18
 };
 
+struct mthca_user_db_table {
+       struct semaphore mutex;
+       struct {
+               u64                uvirt;
+               struct scatterlist mem;
+               int                refcount;
+       }                page[0];
+};
+
 void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm)
 {
        struct mthca_icm_chunk *chunk, *tmp;
@@ -344,13 +354,133 @@ void mthca_free_icm_table(struct mthca_dev *dev, struct mthca_icm_table *table)
        kfree(table);
 }
 
-static u64 mthca_uarc_virt(struct mthca_dev *dev, int page)
+static u64 mthca_uarc_virt(struct mthca_dev *dev, struct mthca_uar *uar, int page)
 {
        return dev->uar_table.uarc_base +
-               dev->driver_uar.index * dev->uar_table.uarc_size +
+               uar->index * dev->uar_table.uarc_size +
                page * 4096;
 }
 
+int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
+                     struct mthca_user_db_table *db_tab, int index, u64 uaddr)
+{
+       int ret = 0;
+       u8 status;
+       int i;
+
+       if (!mthca_is_memfree(dev))
+               return 0;
+
+       if (index < 0 || index > dev->uar_table.uarc_size / 8)
+               return -EINVAL;
+
+       down(&db_tab->mutex);
+
+       i = index / MTHCA_DB_REC_PER_PAGE;
+
+       if ((db_tab->page[i].refcount >= MTHCA_DB_REC_PER_PAGE)       ||
+           (db_tab->page[i].uvirt && db_tab->page[i].uvirt != uaddr) ||
+           (uaddr & 4095)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (db_tab->page[i].refcount) {
+               ++db_tab->page[i].refcount;
+               goto out;
+       }
+
+       ret = get_user_pages(current, current->mm, uaddr & PAGE_MASK, 1, 1, 0,
+                            &db_tab->page[i].mem.page, NULL);
+       if (ret < 0)
+               goto out;
+
+       db_tab->page[i].mem.length = 4096;
+       db_tab->page[i].mem.offset = uaddr & ~PAGE_MASK;
+
+       ret = pci_map_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
+       if (ret < 0) {
+               put_page(db_tab->page[i].mem.page);
+               goto out;
+       }
+
+       ret = mthca_MAP_ICM_page(dev, sg_dma_address(&db_tab->page[i].mem),
+                                mthca_uarc_virt(dev, uar, i), &status);
+       if (!ret && status)
+               ret = -EINVAL;
+       if (ret) {
+               pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
+               put_page(db_tab->page[i].mem.page);
+               goto out;
+       }
+
+       db_tab->page[i].uvirt    = uaddr;
+       db_tab->page[i].refcount = 1;
+
+out:
+       up(&db_tab->mutex);
+       return ret;
+}
+
+void mthca_unmap_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
+                        struct mthca_user_db_table *db_tab, int index)
+{
+       if (!mthca_is_memfree(dev))
+               return;
+
+       /*
+        * To make our bookkeeping simpler, we don't unmap DB
+        * pages until we clean up the whole db table.
+        */
+
+       down(&db_tab->mutex);
+
+       --db_tab->page[index / MTHCA_DB_REC_PER_PAGE].refcount;
+
+       up(&db_tab->mutex);
+}
+
+struct mthca_user_db_table *mthca_init_user_db_tab(struct mthca_dev *dev)
+{
+       struct mthca_user_db_table *db_tab;
+       int npages;
+       int i;
+
+       if (!mthca_is_memfree(dev))
+               return NULL;
+
+       npages = dev->uar_table.uarc_size / 4096;
+       db_tab = kmalloc(sizeof *db_tab + npages * sizeof *db_tab->page, GFP_KERNEL);
+       if (!db_tab)
+               return ERR_PTR(-ENOMEM);
+
+       init_MUTEX(&db_tab->mutex);
+       for (i = 0; i < npages; ++i) {
+               db_tab->page[i].refcount = 0;
+               db_tab->page[i].uvirt    = 0;
+       }
+
+       return db_tab;
+}
+
+void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
+                              struct mthca_user_db_table *db_tab)
+{
+       int i;
+       u8 status;
+
+       if (!mthca_is_memfree(dev))
+               return;
+
+       for (i = 0; i < dev->uar_table.uarc_size / 4096; ++i) {
+               if (db_tab->page[i].uvirt) {
+                       mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, uar, i), 1, &status);
+                       pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
+                       put_page(db_tab->page[i].mem.page);
+               }
+       }
+}
+
 int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, u32 **db)
 {
        int group;
@@ -407,7 +537,8 @@ int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, u32 **db)
        }
        memset(page->db_rec, 0, 4096);
 
-       ret = mthca_MAP_ICM_page(dev, page->mapping, mthca_uarc_virt(dev, i), &status);
+       ret = mthca_MAP_ICM_page(dev, page->mapping,
+                                mthca_uarc_virt(dev, &dev->driver_uar, i), &status);
        if (!ret && status)
                ret = -EINVAL;
        if (ret) {
@@ -461,7 +592,7 @@ void mthca_free_db(struct mthca_dev *dev, int type, int db_index)
 
        if (bitmap_empty(page->used, MTHCA_DB_REC_PER_PAGE) &&
            i >= dev->db_tab->max_group1 - 1) {
-               mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, i), 1, &status);
+               mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, &dev->driver_uar, i), 1, &status);
 
                dma_free_coherent(&dev->pdev->dev, 4096,
                                  page->db_rec, page->mapping);
@@ -530,7 +661,7 @@ void mthca_cleanup_db_tab(struct mthca_dev *dev)
                if (!bitmap_empty(dev->db_tab->page[i].used, MTHCA_DB_REC_PER_PAGE))
                        mthca_warn(dev, "Kernel UARC page %d not empty\n", i);
 
-               mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, i), 1, &status);
+               mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, &dev->driver_uar, i), 1, &status);
 
                dma_free_coherent(&dev->pdev->dev, 4096,
                                  dev->db_tab->page[i].db_rec,
index fe7be2a6bc4a80c56cc8ae4a8eadb4ef290e6570..4761d844cb5f93bbacb9f960b34e70d8cad8402c 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -148,7 +149,7 @@ struct mthca_db_table {
        struct semaphore      mutex;
 };
 
-enum {
+enum mthca_db_type {
        MTHCA_DB_TYPE_INVALID   = 0x0,
        MTHCA_DB_TYPE_CQ_SET_CI = 0x1,
        MTHCA_DB_TYPE_CQ_ARM    = 0x2,
@@ -158,6 +159,17 @@ enum {
        MTHCA_DB_TYPE_GROUP_SEP = 0x7
 };
 
+struct mthca_user_db_table;
+struct mthca_uar;
+
+int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
+                     struct mthca_user_db_table *db_tab, int index, u64 uaddr);
+void mthca_unmap_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
+                        struct mthca_user_db_table *db_tab, int index);
+struct mthca_user_db_table *mthca_init_user_db_tab(struct mthca_dev *dev);
+void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
+                              struct mthca_user_db_table *db_tab);
+
 int mthca_init_db_tab(struct mthca_dev *dev);
 void mthca_cleanup_db_tab(struct mthca_dev *dev);
 int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, u32 **db);
index ea66847e4ea3f762eea7f2206e1516e621885856..c2c899844e98b2ab36389c095a53aa24a6181885 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
 
 #include "mthca_dev.h"
 
-int mthca_pd_alloc(struct mthca_dev *dev, struct mthca_pd *pd)
+int mthca_pd_alloc(struct mthca_dev *dev, int privileged, struct mthca_pd *pd)
 {
-       int err;
+       int err = 0;
 
        might_sleep();
 
+       pd->privileged = privileged;
+
        atomic_set(&pd->sqp_count, 0);
        pd->pd_num = mthca_alloc(&dev->pd_table.alloc);
        if (pd->pd_num == -1)
                return -ENOMEM;
 
-       err = mthca_mr_alloc_notrans(dev, pd->pd_num,
-                                    MTHCA_MPT_FLAG_LOCAL_READ |
-                                    MTHCA_MPT_FLAG_LOCAL_WRITE,
-                                    &pd->ntmr);
-       if (err)
-               mthca_free(&dev->pd_table.alloc, pd->pd_num);
+       if (privileged) {
+               err = mthca_mr_alloc_notrans(dev, pd->pd_num,
+                                            MTHCA_MPT_FLAG_LOCAL_READ |
+                                            MTHCA_MPT_FLAG_LOCAL_WRITE,
+                                            &pd->ntmr);
+               if (err)
+                       mthca_free(&dev->pd_table.alloc, pd->pd_num);
+       }
 
        return err;
 }
@@ -61,7 +66,8 @@ int mthca_pd_alloc(struct mthca_dev *dev, struct mthca_pd *pd)
 void mthca_pd_free(struct mthca_dev *dev, struct mthca_pd *pd)
 {
        might_sleep();
-       mthca_free_mr(dev, &pd->ntmr);
+       if (pd->privileged)
+               mthca_free_mr(dev, &pd->ntmr);
        mthca_free(&dev->pd_table.alloc, pd->pd_num);
 }
 
index 0b5adfd91597a1ec376bd895d55a3b781b21f22d..7a58ce90e1799490d503503c641de07acf73a2db 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2005 Cisco Systems. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
  */
 
 #include <ib_smi.h>
+#include <linux/mm.h>
 
 #include "mthca_dev.h"
 #include "mthca_cmd.h"
+#include "mthca_user.h"
+#include "mthca_memfree.h"
 
 static int mthca_query_device(struct ib_device *ibdev,
                              struct ib_device_attr *props)
@@ -284,7 +288,78 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port,
        return err;
 }
 
-static struct ib_pd *mthca_alloc_pd(struct ib_device *ibdev)
+static struct ib_ucontext *mthca_alloc_ucontext(struct ib_device *ibdev,
+                                               struct ib_udata *udata)
+{
+       struct mthca_alloc_ucontext_resp uresp;
+       struct mthca_ucontext           *context;
+       int                              err;
+
+       memset(&uresp, 0, sizeof uresp);
+
+       uresp.qp_tab_size = to_mdev(ibdev)->limits.num_qps;
+       if (mthca_is_memfree(to_mdev(ibdev)))
+               uresp.uarc_size = to_mdev(ibdev)->uar_table.uarc_size;
+       else
+               uresp.uarc_size = 0;
+
+       context = kmalloc(sizeof *context, GFP_KERNEL);
+       if (!context)
+               return ERR_PTR(-ENOMEM);
+
+       err = mthca_uar_alloc(to_mdev(ibdev), &context->uar);
+       if (err) {
+               kfree(context);
+               return ERR_PTR(err);
+       }
+
+       context->db_tab = mthca_init_user_db_tab(to_mdev(ibdev));
+       if (IS_ERR(context->db_tab)) {
+               err = PTR_ERR(context->db_tab);
+               mthca_uar_free(to_mdev(ibdev), &context->uar);
+               kfree(context);
+               return ERR_PTR(err);
+       }
+
+       if (ib_copy_to_udata(udata, &uresp, sizeof uresp)) {
+               mthca_cleanup_user_db_tab(to_mdev(ibdev), &context->uar, context->db_tab);
+               mthca_uar_free(to_mdev(ibdev), &context->uar);
+               kfree(context);
+               return ERR_PTR(-EFAULT);
+       }
+
+       return &context->ibucontext;
+}
+
+static int mthca_dealloc_ucontext(struct ib_ucontext *context)
+{
+       mthca_cleanup_user_db_tab(to_mdev(context->device), &to_mucontext(context)->uar,
+                                 to_mucontext(context)->db_tab);
+       mthca_uar_free(to_mdev(context->device), &to_mucontext(context)->uar);
+       kfree(to_mucontext(context));
+
+       return 0;
+}
+
+static int mthca_mmap_uar(struct ib_ucontext *context,
+                         struct vm_area_struct *vma)
+{
+       if (vma->vm_end - vma->vm_start != PAGE_SIZE)
+               return -EINVAL;
+
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+       if (remap_pfn_range(vma, vma->vm_start,
+                           to_mucontext(context)->uar.pfn,
+                           PAGE_SIZE, vma->vm_page_prot))
+               return -EAGAIN;
+
+       return 0;
+}
+
+static struct ib_pd *mthca_alloc_pd(struct ib_device *ibdev,
+                                   struct ib_ucontext *context,
+                                   struct ib_udata *udata)
 {
        struct mthca_pd *pd;
        int err;
@@ -293,12 +368,20 @@ static struct ib_pd *mthca_alloc_pd(struct ib_device *ibdev)
        if (!pd)
                return ERR_PTR(-ENOMEM);
 
-       err = mthca_pd_alloc(to_mdev(ibdev), pd);
+       err = mthca_pd_alloc(to_mdev(ibdev), !context, pd);
        if (err) {
                kfree(pd);
                return ERR_PTR(err);
        }
 
+       if (context) {
+               if (ib_copy_to_udata(udata, &pd->pd_num, sizeof (__u32))) {
+                       mthca_pd_free(to_mdev(ibdev), pd);
+                       kfree(pd);
+                       return ERR_PTR(-EFAULT);
+               }
+       }
+
        return &pd->ibpd;
 }
 
@@ -338,8 +421,10 @@ static int mthca_ah_destroy(struct ib_ah *ah)
 }
 
 static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
-                                    struct ib_qp_init_attr *init_attr)
+                                    struct ib_qp_init_attr *init_attr,
+                                    struct ib_udata *udata)
 {
+       struct mthca_create_qp ucmd;
        struct mthca_qp *qp;
        int err;
 
@@ -348,41 +433,82 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
        case IB_QPT_UC:
        case IB_QPT_UD:
        {
+               struct mthca_ucontext *context;
+
                qp = kmalloc(sizeof *qp, GFP_KERNEL);
                if (!qp)
                        return ERR_PTR(-ENOMEM);
 
-               qp->sq.max    = init_attr->cap.max_send_wr;
-               qp->rq.max    = init_attr->cap.max_recv_wr;
-               qp->sq.max_gs = init_attr->cap.max_send_sge;
-               qp->rq.max_gs = init_attr->cap.max_recv_sge;
+               if (pd->uobject) {
+                       context = to_mucontext(pd->uobject->context);
+
+                       if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
+                               return ERR_PTR(-EFAULT);
+
+                       err = mthca_map_user_db(to_mdev(pd->device), &context->uar,
+                                               context->db_tab,
+                                               ucmd.sq_db_index, ucmd.sq_db_page);
+                       if (err) {
+                               kfree(qp);
+                               return ERR_PTR(err);
+                       }
+
+                       err = mthca_map_user_db(to_mdev(pd->device), &context->uar,
+                                               context->db_tab,
+                                               ucmd.rq_db_index, ucmd.rq_db_page);
+                       if (err) {
+                               mthca_unmap_user_db(to_mdev(pd->device),
+                                                   &context->uar,
+                                                   context->db_tab,
+                                                   ucmd.sq_db_index);
+                               kfree(qp);
+                               return ERR_PTR(err);
+                       }
+
+                       qp->mr.ibmr.lkey = ucmd.lkey;
+                       qp->sq.db_index  = ucmd.sq_db_index;
+                       qp->rq.db_index  = ucmd.rq_db_index;
+               }
 
                err = mthca_alloc_qp(to_mdev(pd->device), to_mpd(pd),
                                     to_mcq(init_attr->send_cq),
                                     to_mcq(init_attr->recv_cq),
                                     init_attr->qp_type, init_attr->sq_sig_type,
-                                    qp);
+                                    &init_attr->cap, qp);
+
+               if (err && pd->uobject) {
+                       context = to_mucontext(pd->uobject->context);
+
+                       mthca_unmap_user_db(to_mdev(pd->device),
+                                           &context->uar,
+                                           context->db_tab,
+                                           ucmd.sq_db_index);
+                       mthca_unmap_user_db(to_mdev(pd->device),
+                                           &context->uar,
+                                           context->db_tab,
+                                           ucmd.rq_db_index);
+               }
+
                qp->ibqp.qp_num = qp->qpn;
                break;
        }
        case IB_QPT_SMI:
        case IB_QPT_GSI:
        {
+               /* Don't allow userspace to create special QPs */
+               if (pd->uobject)
+                       return ERR_PTR(-EINVAL);
+
                qp = kmalloc(sizeof (struct mthca_sqp), GFP_KERNEL);
                if (!qp)
                        return ERR_PTR(-ENOMEM);
 
-               qp->sq.max    = init_attr->cap.max_send_wr;
-               qp->rq.max    = init_attr->cap.max_recv_wr;
-               qp->sq.max_gs = init_attr->cap.max_send_sge;
-               qp->rq.max_gs = init_attr->cap.max_recv_sge;
-
                qp->ibqp.qp_num = init_attr->qp_type == IB_QPT_SMI ? 0 : 1;
 
                err = mthca_alloc_sqp(to_mdev(pd->device), to_mpd(pd),
                                      to_mcq(init_attr->send_cq),
                                      to_mcq(init_attr->recv_cq),
-                                     init_attr->sq_sig_type,
+                                     init_attr->sq_sig_type, &init_attr->cap,
                                      qp->ibqp.qp_num, init_attr->port_num,
                                      to_msqp(qp));
                break;
@@ -397,42 +523,115 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
                return ERR_PTR(err);
        }
 
-        init_attr->cap.max_inline_data = 0;
+       init_attr->cap.max_inline_data = 0;
+       init_attr->cap.max_send_wr     = qp->sq.max;
+       init_attr->cap.max_recv_wr     = qp->rq.max;
+       init_attr->cap.max_send_sge    = qp->sq.max_gs;
+       init_attr->cap.max_recv_sge    = qp->rq.max_gs;
 
        return &qp->ibqp;
 }
 
 static int mthca_destroy_qp(struct ib_qp *qp)
 {
+       if (qp->uobject) {
+               mthca_unmap_user_db(to_mdev(qp->device),
+                                   &to_mucontext(qp->uobject->context)->uar,
+                                   to_mucontext(qp->uobject->context)->db_tab,
+                                   to_mqp(qp)->sq.db_index);
+               mthca_unmap_user_db(to_mdev(qp->device),
+                                   &to_mucontext(qp->uobject->context)->uar,
+                                   to_mucontext(qp->uobject->context)->db_tab,
+                                   to_mqp(qp)->rq.db_index);
+       }
        mthca_free_qp(to_mdev(qp->device), to_mqp(qp));
        kfree(qp);
        return 0;
 }
 
-static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries)
+static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries,
+                                    struct ib_ucontext *context,
+                                    struct ib_udata *udata)
 {
+       struct mthca_create_cq ucmd;
        struct mthca_cq *cq;
        int nent;
        int err;
 
+       if (context) {
+               if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
+                       return ERR_PTR(-EFAULT);
+
+               err = mthca_map_user_db(to_mdev(ibdev), &to_mucontext(context)->uar,
+                                       to_mucontext(context)->db_tab,
+                                       ucmd.set_db_index, ucmd.set_db_page);
+               if (err)
+                       return ERR_PTR(err);
+
+               err = mthca_map_user_db(to_mdev(ibdev), &to_mucontext(context)->uar,
+                                       to_mucontext(context)->db_tab,
+                                       ucmd.arm_db_index, ucmd.arm_db_page);
+               if (err)
+                       goto err_unmap_set;
+       }
+
        cq = kmalloc(sizeof *cq, GFP_KERNEL);
-       if (!cq)
-               return ERR_PTR(-ENOMEM);
+       if (!cq) {
+               err = -ENOMEM;
+               goto err_unmap_arm;
+       }
+
+       if (context) {
+               cq->mr.ibmr.lkey    = ucmd.lkey;
+               cq->set_ci_db_index = ucmd.set_db_index;
+               cq->arm_db_index    = ucmd.arm_db_index;
+       }
 
        for (nent = 1; nent <= entries; nent <<= 1)
                ; /* nothing */
 
-       err = mthca_init_cq(to_mdev(ibdev), nent, cq);
-       if (err) {
-               kfree(cq);
-               cq = ERR_PTR(err);
+       err = mthca_init_cq(to_mdev(ibdev), nent,
+                           context ? to_mucontext(context) : NULL,
+                           context ? ucmd.pdn : to_mdev(ibdev)->driver_pd.pd_num,
+                           cq);
+       if (err)
+               goto err_free;
+
+       if (context && ib_copy_to_udata(udata, &cq->cqn, sizeof (__u32))) {
+               mthca_free_cq(to_mdev(ibdev), cq);
+               goto err_free;
        }
 
        return &cq->ibcq;
+
+err_free:
+       kfree(cq);
+
+err_unmap_arm:
+       if (context)
+               mthca_unmap_user_db(to_mdev(ibdev), &to_mucontext(context)->uar,
+                                   to_mucontext(context)->db_tab, ucmd.arm_db_index);
+
+err_unmap_set:
+       if (context)
+               mthca_unmap_user_db(to_mdev(ibdev), &to_mucontext(context)->uar,
+                                   to_mucontext(context)->db_tab, ucmd.set_db_index);
+
+       return ERR_PTR(err);
 }
 
 static int mthca_destroy_cq(struct ib_cq *cq)
 {
+       if (cq->uobject) {
+               mthca_unmap_user_db(to_mdev(cq->device),
+                                   &to_mucontext(cq->uobject->context)->uar,
+                                   to_mucontext(cq->uobject->context)->db_tab,
+                                   to_mcq(cq)->arm_db_index);
+               mthca_unmap_user_db(to_mdev(cq->device),
+                                   &to_mucontext(cq->uobject->context)->uar,
+                                   to_mucontext(cq->uobject->context)->db_tab,
+                                   to_mcq(cq)->set_ci_db_index);
+       }
        mthca_free_cq(to_mdev(cq->device), to_mcq(cq));
        kfree(cq);
 
@@ -568,6 +767,87 @@ static struct ib_mr *mthca_reg_phys_mr(struct ib_pd       *pd,
        return &mr->ibmr;
 }
 
+static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, struct ib_umem *region,
+                                      int acc, struct ib_udata *udata)
+{
+       struct mthca_dev *dev = to_mdev(pd->device);
+       struct ib_umem_chunk *chunk;
+       struct mthca_mr *mr;
+       u64 *pages;
+       int shift, n, len;
+       int i, j, k;
+       int err = 0;
+
+       shift = ffs(region->page_size) - 1;
+
+       mr = kmalloc(sizeof *mr, GFP_KERNEL);
+       if (!mr)
+               return ERR_PTR(-ENOMEM);
+
+       n = 0;
+       list_for_each_entry(chunk, &region->chunk_list, list)
+               n += chunk->nents;
+
+       mr->mtt = mthca_alloc_mtt(dev, n);
+       if (IS_ERR(mr->mtt)) {
+               err = PTR_ERR(mr->mtt);
+               goto err;
+       }
+
+       pages = (u64 *) __get_free_page(GFP_KERNEL);
+       if (!pages) {
+               err = -ENOMEM;
+               goto err_mtt;
+       }
+
+       i = n = 0;
+
+       list_for_each_entry(chunk, &region->chunk_list, list)
+               for (j = 0; j < chunk->nmap; ++j) {
+                       len = sg_dma_len(&chunk->page_list[j]) >> shift;
+                       for (k = 0; k < len; ++k) {
+                               pages[i++] = sg_dma_address(&chunk->page_list[j]) +
+                                       region->page_size * k;
+                               /*
+                                * Be friendly to WRITE_MTT command
+                                * and leave two empty slots for the
+                                * index and reserved fields of the
+                                * mailbox.
+                                */
+                               if (i == PAGE_SIZE / sizeof (u64) - 2) {
+                                       err = mthca_write_mtt(dev, mr->mtt,
+                                                             n, pages, i);
+                                       if (err)
+                                               goto mtt_done;
+                                       n += i;
+                                       i = 0;
+                               }
+                       }
+               }
+
+       if (i)
+               err = mthca_write_mtt(dev, mr->mtt, n, pages, i);
+mtt_done:
+       free_page((unsigned long) pages);
+       if (err)
+               goto err_mtt;
+
+       err = mthca_mr_alloc(dev, to_mpd(pd)->pd_num, shift, region->virt_base,
+                            region->length, convert_access(acc), mr);
+
+       if (err)
+               goto err_mtt;
+
+       return &mr->ibmr;
+
+err_mtt:
+       mthca_free_mtt(dev, mr->mtt);
+
+err:
+       kfree(mr);
+       return ERR_PTR(err);
+}
+
 static int mthca_dereg_mr(struct ib_mr *mr)
 {
        struct mthca_mr *mmr = to_mmr(mr);
@@ -692,6 +972,8 @@ int mthca_register_device(struct mthca_dev *dev)
        int i;
 
        strlcpy(dev->ib_dev.name, "mthca%d", IB_DEVICE_NAME_MAX);
+       dev->ib_dev.owner                = THIS_MODULE;
+
        dev->ib_dev.node_type            = IB_NODE_CA;
        dev->ib_dev.phys_port_cnt        = dev->limits.num_ports;
        dev->ib_dev.dma_device           = &dev->pdev->dev;
@@ -701,6 +983,9 @@ int mthca_register_device(struct mthca_dev *dev)
        dev->ib_dev.modify_port          = mthca_modify_port;
        dev->ib_dev.query_pkey           = mthca_query_pkey;
        dev->ib_dev.query_gid            = mthca_query_gid;
+       dev->ib_dev.alloc_ucontext       = mthca_alloc_ucontext;
+       dev->ib_dev.dealloc_ucontext     = mthca_dealloc_ucontext;
+       dev->ib_dev.mmap                 = mthca_mmap_uar;
        dev->ib_dev.alloc_pd             = mthca_alloc_pd;
        dev->ib_dev.dealloc_pd           = mthca_dealloc_pd;
        dev->ib_dev.create_ah            = mthca_ah_create;
@@ -713,6 +998,7 @@ int mthca_register_device(struct mthca_dev *dev)
        dev->ib_dev.poll_cq              = mthca_poll_cq;
        dev->ib_dev.get_dma_mr           = mthca_get_dma_mr;
        dev->ib_dev.reg_phys_mr          = mthca_reg_phys_mr;
+       dev->ib_dev.reg_user_mr          = mthca_reg_user_mr;
        dev->ib_dev.dereg_mr             = mthca_dereg_mr;
 
        if (dev->mthca_flags & MTHCA_FLAG_FMR) {
index 4d976cccb1a8126acd97096821d92808b698a114..1d032791cc8b67a3ad217dc3a235ead72dab1f6b 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -54,6 +55,14 @@ struct mthca_uar {
        int           index;
 };
 
+struct mthca_user_db_table;
+
+struct mthca_ucontext {
+       struct ib_ucontext          ibucontext;
+       struct mthca_uar            uar;
+       struct mthca_user_db_table *db_tab;
+};
+
 struct mthca_mtt;
 
 struct mthca_mr {
@@ -83,6 +92,7 @@ struct mthca_pd {
        u32             pd_num;
        atomic_t        sqp_count;
        struct mthca_mr ntmr;
+       int             privileged;
 };
 
 struct mthca_eq {
@@ -167,6 +177,7 @@ struct mthca_cq {
        int                    cqn;
        u32                    cons_index;
        int                    is_direct;
+       int                    is_kernel;
 
        /* Next fields are Arbel only */
        int                    set_ci_db_index;
@@ -236,6 +247,11 @@ struct mthca_sqp {
        dma_addr_t      header_dma;
 };
 
+static inline struct mthca_ucontext *to_mucontext(struct ib_ucontext *ibucontext)
+{
+       return container_of(ibucontext, struct mthca_ucontext, ibucontext);
+}
+
 static inline struct mthca_fmr *to_mfmr(struct ib_fmr *ibmr)
 {
        return container_of(ibmr, struct mthca_fmr, ibmr);
index 163a8ef4186f690b94f58f9f6600bfb12ac780b3..f7126b14d5aeac2ac06f7d91bd2c0b3523375ff9 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Cisco Systems. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -46,7 +47,9 @@ enum {
        MTHCA_MAX_DIRECT_QP_SIZE = 4 * PAGE_SIZE,
        MTHCA_ACK_REQ_FREQ       = 10,
        MTHCA_FLIGHT_LIMIT       = 9,
-       MTHCA_UD_HEADER_SIZE     = 72 /* largest UD header possible */
+       MTHCA_UD_HEADER_SIZE     = 72, /* largest UD header possible */
+       MTHCA_INLINE_HEADER_SIZE = 4,  /* data segment overhead for inline */
+       MTHCA_INLINE_CHUNK_SIZE  = 16  /* inline data segment chunk */
 };
 
 enum {
@@ -689,7 +692,11 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
 
        /* leave arbel_sched_queue as 0 */
 
-       qp_context->usr_page   = cpu_to_be32(dev->driver_uar.index);
+       if (qp->ibqp.uobject)
+               qp_context->usr_page =
+                       cpu_to_be32(to_mucontext(qp->ibqp.uobject->context)->uar.index);
+       else
+               qp_context->usr_page = cpu_to_be32(dev->driver_uar.index);
        qp_context->local_qpn  = cpu_to_be32(qp->qpn);
        if (attr_mask & IB_QP_DEST_QPN) {
                qp_context->remote_qpn = cpu_to_be32(attr->dest_qp_num);
@@ -954,6 +961,15 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev,
 
        qp->send_wqe_offset = ALIGN(qp->rq.max << qp->rq.wqe_shift,
                                    1 << qp->sq.wqe_shift);
+
+       /*
+        * If this is a userspace QP, we don't actually have to
+        * allocate anything.  All we need is to calculate the WQE
+        * sizes and the send_wqe_offset, so we're done now.
+        */
+       if (pd->ibpd.uobject)
+               return 0;
+
        size = PAGE_ALIGN(qp->send_wqe_offset +
                          (qp->sq.max << qp->sq.wqe_shift));
 
@@ -1053,10 +1069,32 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev,
        return err;
 }
 
-static int mthca_alloc_memfree(struct mthca_dev *dev,
+static void mthca_free_wqe_buf(struct mthca_dev *dev,
                               struct mthca_qp *qp)
 {
-       int ret = 0;
+       int i;
+       int size = PAGE_ALIGN(qp->send_wqe_offset +
+                             (qp->sq.max << qp->sq.wqe_shift));
+
+       if (qp->is_direct) {
+               dma_free_coherent(&dev->pdev->dev, size, qp->queue.direct.buf,
+                                 pci_unmap_addr(&qp->queue.direct, mapping));
+       } else {
+               for (i = 0; i < size / PAGE_SIZE; ++i) {
+                       dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
+                                         qp->queue.page_list[i].buf,
+                                         pci_unmap_addr(&qp->queue.page_list[i],
+                                                        mapping));
+               }
+       }
+
+       kfree(qp->wrid);
+}
+
+static int mthca_map_memfree(struct mthca_dev *dev,
+                            struct mthca_qp *qp)
+{
+       int ret;
 
        if (mthca_is_memfree(dev)) {
                ret = mthca_table_get(dev, dev->qp_table.qp_table, qp->qpn);
@@ -1067,35 +1105,15 @@ static int mthca_alloc_memfree(struct mthca_dev *dev,
                if (ret)
                        goto err_qpc;
 
-               ret = mthca_table_get(dev, dev->qp_table.rdb_table,
-                                     qp->qpn << dev->qp_table.rdb_shift);
-               if (ret)
-                       goto err_eqpc;
-
-               qp->rq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_RQ,
-                                                qp->qpn, &qp->rq.db);
-               if (qp->rq.db_index < 0) {
-                       ret = -ENOMEM;
-                       goto err_rdb;
-               }
+               ret = mthca_table_get(dev, dev->qp_table.rdb_table,
+                                     qp->qpn << dev->qp_table.rdb_shift);
+               if (ret)
+                       goto err_eqpc;
 
-               qp->sq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_SQ,
-                                                qp->qpn, &qp->sq.db);
-               if (qp->sq.db_index < 0) {
-                       ret = -ENOMEM;
-                       goto err_rq_db;
-               }
        }
 
        return 0;
 
-err_rq_db:
-       mthca_free_db(dev, MTHCA_DB_TYPE_RQ, qp->rq.db_index);
-
-err_rdb:
-       mthca_table_put(dev, dev->qp_table.rdb_table,
-                       qp->qpn << dev->qp_table.rdb_shift);
-
 err_eqpc:
        mthca_table_put(dev, dev->qp_table.eqp_table, qp->qpn);
 
@@ -1105,6 +1123,35 @@ err_qpc:
        return ret;
 }
 
+static void mthca_unmap_memfree(struct mthca_dev *dev,
+                               struct mthca_qp *qp)
+{
+       mthca_table_put(dev, dev->qp_table.rdb_table,
+                       qp->qpn << dev->qp_table.rdb_shift);
+       mthca_table_put(dev, dev->qp_table.eqp_table, qp->qpn);
+       mthca_table_put(dev, dev->qp_table.qp_table, qp->qpn);
+}
+
+static int mthca_alloc_memfree(struct mthca_dev *dev,
+                              struct mthca_qp *qp)
+{
+       int ret = 0;
+
+       if (mthca_is_memfree(dev)) {
+               qp->rq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_RQ,
+                                                qp->qpn, &qp->rq.db);
+               if (qp->rq.db_index < 0)
+                       return ret;
+
+               qp->sq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_SQ,
+                                                qp->qpn, &qp->sq.db);
+               if (qp->sq.db_index < 0)
+                       mthca_free_db(dev, MTHCA_DB_TYPE_RQ, qp->rq.db_index);
+       }
+
+       return ret;
+}
+
 static void mthca_free_memfree(struct mthca_dev *dev,
                               struct mthca_qp *qp)
 {
@@ -1112,11 +1159,6 @@ static void mthca_free_memfree(struct mthca_dev *dev,
                mthca_free_db(dev, MTHCA_DB_TYPE_SQ, qp->sq.db_index);
                mthca_free_db(dev, MTHCA_DB_TYPE_RQ, qp->rq.db_index);
        }
-
-       mthca_table_put(dev, dev->qp_table.rdb_table,
-                       qp->qpn << dev->qp_table.rdb_shift);
-       mthca_table_put(dev, dev->qp_table.eqp_table, qp->qpn);
-       mthca_table_put(dev, dev->qp_table.qp_table, qp->qpn);
 }
 
 static void mthca_wq_init(struct mthca_wq* wq)
@@ -1147,13 +1189,28 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
        mthca_wq_init(&qp->sq);
        mthca_wq_init(&qp->rq);
 
-       ret = mthca_alloc_memfree(dev, qp);
+       ret = mthca_map_memfree(dev, qp);
        if (ret)
                return ret;
 
        ret = mthca_alloc_wqe_buf(dev, pd, qp);
        if (ret) {
-               mthca_free_memfree(dev, qp);
+               mthca_unmap_memfree(dev, qp);
+               return ret;
+       }
+
+       /*
+        * If this is a userspace QP, we're done now.  The doorbells
+        * will be allocated and buffers will be initialized in
+        * userspace.
+        */
+       if (pd->ibpd.uobject)
+               return 0;
+
+       ret = mthca_alloc_memfree(dev, qp);
+       if (ret) {
+               mthca_free_wqe_buf(dev, qp);
+               mthca_unmap_memfree(dev, qp);
                return ret;
        }
 
@@ -1186,22 +1243,39 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
        return 0;
 }
 
-static void mthca_align_qp_size(struct mthca_dev *dev, struct mthca_qp *qp)
+static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap,
+                            struct mthca_qp *qp)
 {
-       int i;
-
-       if (!mthca_is_memfree(dev))
-               return;
+       /* Sanity check QP size before proceeding */
+       if (cap->max_send_wr  > 65536 || cap->max_recv_wr  > 65536 ||
+           cap->max_send_sge > 64    || cap->max_recv_sge > 64)
+               return -EINVAL;
 
-       for (i = 0; 1 << i < qp->rq.max; ++i)
-               ; /* nothing */
+       if (mthca_is_memfree(dev)) {
+               qp->rq.max = cap->max_recv_wr ?
+                       roundup_pow_of_two(cap->max_recv_wr) : 0;
+               qp->sq.max = cap->max_send_wr ?
+                       roundup_pow_of_two(cap->max_send_wr) : 0;
+       } else {
+               qp->rq.max = cap->max_recv_wr;
+               qp->sq.max = cap->max_send_wr;
+       }
 
-       qp->rq.max = 1 << i;
+       qp->rq.max_gs = cap->max_recv_sge;
+       qp->sq.max_gs = max_t(int, cap->max_send_sge,
+                             ALIGN(cap->max_inline_data + MTHCA_INLINE_HEADER_SIZE,
+                                   MTHCA_INLINE_CHUNK_SIZE) /
+                             sizeof (struct mthca_data_seg));
 
-       for (i = 0; 1 << i < qp->sq.max; ++i)
-               ; /* nothing */
+       /*
+        * For MLX transport we need 2 extra S/G entries:
+        * one for the header and one for the checksum at the end
+        */
+       if ((qp->transport == MLX && qp->sq.max_gs + 2 > dev->limits.max_sg) ||
+           qp->sq.max_gs > dev->limits.max_sg || qp->rq.max_gs > dev->limits.max_sg)
+               return -EINVAL;
 
-       qp->sq.max = 1 << i;
+       return 0;
 }
 
 int mthca_alloc_qp(struct mthca_dev *dev,
@@ -1210,11 +1284,14 @@ int mthca_alloc_qp(struct mthca_dev *dev,
                   struct mthca_cq *recv_cq,
                   enum ib_qp_type type,
                   enum ib_sig_type send_policy,
+                  struct ib_qp_cap *cap,
                   struct mthca_qp *qp)
 {
        int err;
 
-       mthca_align_qp_size(dev, qp);
+       err = mthca_set_qp_size(dev, cap, qp);
+       if (err)
+               return err;
 
        switch (type) {
        case IB_QPT_RC: qp->transport = RC; break;
@@ -1247,14 +1324,17 @@ int mthca_alloc_sqp(struct mthca_dev *dev,
                    struct mthca_cq *send_cq,
                    struct mthca_cq *recv_cq,
                    enum ib_sig_type send_policy,
+                   struct ib_qp_cap *cap,
                    int qpn,
                    int port,
                    struct mthca_sqp *sqp)
 {
-       int err = 0;
        u32 mqpn = qpn * 2 + dev->qp_table.sqp_start + port - 1;
+       int err;
 
-       mthca_align_qp_size(dev, &sqp->qp);
+       err = mthca_set_qp_size(dev, cap, &sqp->qp);
+       if (err)
+               return err;
 
        sqp->header_buf_size = sqp->qp.sq.max * MTHCA_UD_HEADER_SIZE;
        sqp->header_buf = dma_alloc_coherent(&dev->pdev->dev, sqp->header_buf_size,
@@ -1313,8 +1393,6 @@ void mthca_free_qp(struct mthca_dev *dev,
                   struct mthca_qp *qp)
 {
        u8 status;
-       int size;
-       int i;
        struct mthca_cq *send_cq;
        struct mthca_cq *recv_cq;
 
@@ -1344,31 +1422,22 @@ void mthca_free_qp(struct mthca_dev *dev,
        if (qp->state != IB_QPS_RESET)
                mthca_MODIFY_QP(dev, MTHCA_TRANS_ANY2RST, qp->qpn, 0, NULL, 0, &status);
 
-       mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, qp->qpn);
-       if (qp->ibqp.send_cq != qp->ibqp.recv_cq)
-               mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq)->cqn, qp->qpn);
-
-       mthca_free_mr(dev, &qp->mr);
-
-       size = PAGE_ALIGN(qp->send_wqe_offset +
-                         (qp->sq.max << qp->sq.wqe_shift));
+       /*
+        * If this is a userspace QP, the buffers, MR, CQs and so on
+        * will be cleaned up in userspace, so all we have to do is
+        * unref the mem-free tables and free the QPN in our table.
+        */
+       if (!qp->ibqp.uobject) {
+               mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, qp->qpn);
+               if (qp->ibqp.send_cq != qp->ibqp.recv_cq)
+                       mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq)->cqn, qp->qpn);
 
-       if (qp->is_direct) {
-               pci_free_consistent(dev->pdev, size,
-                                   qp->queue.direct.buf,
-                                   pci_unmap_addr(&qp->queue.direct, mapping));
-       } else {
-               for (i = 0; i < size / PAGE_SIZE; ++i) {
-                       pci_free_consistent(dev->pdev, PAGE_SIZE,
-                                           qp->queue.page_list[i].buf,
-                                           pci_unmap_addr(&qp->queue.page_list[i],
-                                                          mapping));
-               }
+               mthca_free_mr(dev, &qp->mr);
+               mthca_free_memfree(dev, qp);
+               mthca_free_wqe_buf(dev, qp);
        }
 
-       kfree(qp->wrid);
-
-       mthca_free_memfree(dev, qp);
+       mthca_unmap_memfree(dev, qp);
 
        if (is_sqp(dev, qp)) {
                atomic_dec(&(to_mpd(qp->ibqp.pd)->sqp_count));
diff --git a/drivers/infiniband/hw/mthca/mthca_user.h b/drivers/infiniband/hw/mthca/mthca_user.h
new file mode 100644 (file)
index 0000000..3024c1b
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * 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 MTHCA_USER_H
+#define MTHCA_USER_H
+
+#include <linux/types.h>
+
+/*
+ * Make sure that all structs defined in this file remain laid out so
+ * that they pack the same way on 32-bit and 64-bit architectures (to
+ * avoid incompatibility between 32-bit userspace and 64-bit kernels).
+ * In particular do not use pointer types -- pass pointers in __u64
+ * instead.
+ */
+
+struct mthca_alloc_ucontext_resp {
+       __u32 qp_tab_size;
+       __u32 uarc_size;
+};
+
+struct mthca_alloc_pd_resp {
+       __u32 pdn;
+       __u32 reserved;
+};
+
+struct mthca_create_cq {
+       __u32 lkey;
+       __u32 pdn;
+       __u64 arm_db_page;
+       __u64 set_db_page;
+       __u32 arm_db_index;
+       __u32 set_db_index;
+};
+
+struct mthca_create_cq_resp {
+       __u32 cqn;
+       __u32 reserved;
+};
+
+struct mthca_create_qp {
+       __u32 lkey;
+       __u32 reserved;
+       __u64 sq_db_page;
+       __u64 rq_db_page;
+       __u32 sq_db_index;
+       __u32 rq_db_index;
+};
+
+#endif /* MTHCA_USER_H */
diff --git a/drivers/infiniband/include/ib_user_verbs.h b/drivers/infiniband/include/ib_user_verbs.h
new file mode 100644 (file)
index 0000000..7c61370
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * 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.
+ *
+ * $Id: ib_user_verbs.h 2708 2005-06-24 17:27:21Z roland $
+ */
+
+#ifndef IB_USER_VERBS_H
+#define IB_USER_VERBS_H
+
+#include <linux/types.h>
+
+/*
+ * Increment this value if any changes that break userspace ABI
+ * compatibility are made.
+ */
+#define IB_USER_VERBS_ABI_VERSION      1
+
+enum {
+       IB_USER_VERBS_CMD_QUERY_PARAMS,
+       IB_USER_VERBS_CMD_GET_CONTEXT,
+       IB_USER_VERBS_CMD_QUERY_DEVICE,
+       IB_USER_VERBS_CMD_QUERY_PORT,
+       IB_USER_VERBS_CMD_QUERY_GID,
+       IB_USER_VERBS_CMD_QUERY_PKEY,
+       IB_USER_VERBS_CMD_ALLOC_PD,
+       IB_USER_VERBS_CMD_DEALLOC_PD,
+       IB_USER_VERBS_CMD_CREATE_AH,
+       IB_USER_VERBS_CMD_MODIFY_AH,
+       IB_USER_VERBS_CMD_QUERY_AH,
+       IB_USER_VERBS_CMD_DESTROY_AH,
+       IB_USER_VERBS_CMD_REG_MR,
+       IB_USER_VERBS_CMD_REG_SMR,
+       IB_USER_VERBS_CMD_REREG_MR,
+       IB_USER_VERBS_CMD_QUERY_MR,
+       IB_USER_VERBS_CMD_DEREG_MR,
+       IB_USER_VERBS_CMD_ALLOC_MW,
+       IB_USER_VERBS_CMD_BIND_MW,
+       IB_USER_VERBS_CMD_DEALLOC_MW,
+       IB_USER_VERBS_CMD_CREATE_CQ,
+       IB_USER_VERBS_CMD_RESIZE_CQ,
+       IB_USER_VERBS_CMD_DESTROY_CQ,
+       IB_USER_VERBS_CMD_POLL_CQ,
+       IB_USER_VERBS_CMD_PEEK_CQ,
+       IB_USER_VERBS_CMD_REQ_NOTIFY_CQ,
+       IB_USER_VERBS_CMD_CREATE_QP,
+       IB_USER_VERBS_CMD_QUERY_QP,
+       IB_USER_VERBS_CMD_MODIFY_QP,
+       IB_USER_VERBS_CMD_DESTROY_QP,
+       IB_USER_VERBS_CMD_POST_SEND,
+       IB_USER_VERBS_CMD_POST_RECV,
+       IB_USER_VERBS_CMD_ATTACH_MCAST,
+       IB_USER_VERBS_CMD_DETACH_MCAST
+};
+
+/*
+ * Make sure that all structs defined in this file remain laid out so
+ * that they pack the same way on 32-bit and 64-bit architectures (to
+ * avoid incompatibility between 32-bit userspace and 64-bit kernels).
+ * In particular do not use pointer types -- pass pointers in __u64
+ * instead.
+ */
+
+struct ib_uverbs_async_event_desc {
+       __u64 element;
+       __u32 event_type;       /* enum ib_event_type */
+       __u32 reserved;
+};
+
+struct ib_uverbs_comp_event_desc {
+       __u64 cq_handle;
+};
+
+/*
+ * All commands from userspace should start with a __u32 command field
+ * followed by __u16 in_words and out_words fields (which give the
+ * length of the command block and response buffer if any in 32-bit
+ * words).  The kernel driver will read these fields first and read
+ * the rest of the command struct based on these value.
+ */
+
+struct ib_uverbs_cmd_hdr {
+       __u32 command;
+       __u16 in_words;
+       __u16 out_words;
+};
+
+/*
+ * No driver_data for "query params" command, since this is intended
+ * to be a core function with no possible device dependence.
+ */
+struct ib_uverbs_query_params {
+       __u64 response;
+};
+
+struct ib_uverbs_query_params_resp {
+       __u32 num_cq_events;
+};
+
+struct ib_uverbs_get_context {
+       __u64 response;
+       __u64 cq_fd_tab;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_get_context_resp {
+       __u32 async_fd;
+       __u32 reserved;
+};
+
+struct ib_uverbs_query_device {
+       __u64 response;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_query_device_resp {
+       __u64 fw_ver;
+       __u64 node_guid;
+       __u64 sys_image_guid;
+       __u64 max_mr_size;
+       __u64 page_size_cap;
+       __u32 vendor_id;
+       __u32 vendor_part_id;
+       __u32 hw_ver;
+       __u32 max_qp;
+       __u32 max_qp_wr;
+       __u32 device_cap_flags;
+       __u32 max_sge;
+       __u32 max_sge_rd;
+       __u32 max_cq;
+       __u32 max_cqe;
+       __u32 max_mr;
+       __u32 max_pd;
+       __u32 max_qp_rd_atom;
+       __u32 max_ee_rd_atom;
+       __u32 max_res_rd_atom;
+       __u32 max_qp_init_rd_atom;
+       __u32 max_ee_init_rd_atom;
+       __u32 atomic_cap;
+       __u32 max_ee;
+       __u32 max_rdd;
+       __u32 max_mw;
+       __u32 max_raw_ipv6_qp;
+       __u32 max_raw_ethy_qp;
+       __u32 max_mcast_grp;
+       __u32 max_mcast_qp_attach;
+       __u32 max_total_mcast_qp_attach;
+       __u32 max_ah;
+       __u32 max_fmr;
+       __u32 max_map_per_fmr;
+       __u32 max_srq;
+       __u32 max_srq_wr;
+       __u32 max_srq_sge;
+       __u16 max_pkeys;
+       __u8  local_ca_ack_delay;
+       __u8  phys_port_cnt;
+       __u8  reserved[4];
+};
+
+struct ib_uverbs_query_port {
+       __u64 response;
+       __u8  port_num;
+       __u8  reserved[7];
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_query_port_resp {
+       __u32 port_cap_flags;
+       __u32 max_msg_sz;
+       __u32 bad_pkey_cntr;
+       __u32 qkey_viol_cntr;
+       __u32 gid_tbl_len;
+       __u16 pkey_tbl_len;
+       __u16 lid;
+       __u16 sm_lid;
+       __u8  state;
+       __u8  max_mtu;
+       __u8  active_mtu;
+       __u8  lmc;
+       __u8  max_vl_num;
+       __u8  sm_sl;
+       __u8  subnet_timeout;
+       __u8  init_type_reply;
+       __u8  active_width;
+       __u8  active_speed;
+       __u8  phys_state;
+       __u8  reserved[3];
+};
+
+struct ib_uverbs_query_gid {
+       __u64 response;
+       __u8  port_num;
+       __u8  index;
+       __u8  reserved[6];
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_query_gid_resp {
+       __u8  gid[16];
+};
+
+struct ib_uverbs_query_pkey {
+       __u64 response;
+       __u8  port_num;
+       __u8  index;
+       __u8  reserved[6];
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_query_pkey_resp {
+       __u16 pkey;
+       __u16 reserved;
+};
+
+struct ib_uverbs_alloc_pd {
+       __u64 response;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_alloc_pd_resp {
+       __u32 pd_handle;
+};
+
+struct ib_uverbs_dealloc_pd {
+       __u32 pd_handle;
+};
+
+struct ib_uverbs_reg_mr {
+       __u64 response;
+       __u64 start;
+       __u64 length;
+       __u64 hca_va;
+       __u32 pd_handle;
+       __u32 access_flags;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_reg_mr_resp {
+       __u32 mr_handle;
+       __u32 lkey;
+       __u32 rkey;
+};
+
+struct ib_uverbs_dereg_mr {
+       __u32 mr_handle;
+};
+
+struct ib_uverbs_create_cq {
+       __u64 response;
+       __u64 user_handle;
+       __u32 cqe;
+       __u32 event_handler;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_create_cq_resp {
+       __u32 cq_handle;
+       __u32 cqe;
+};
+
+struct ib_uverbs_destroy_cq {
+       __u32 cq_handle;
+};
+
+struct ib_uverbs_create_qp {
+       __u64 response;
+       __u64 user_handle;
+       __u32 pd_handle;
+       __u32 send_cq_handle;
+       __u32 recv_cq_handle;
+       __u32 srq_handle;
+       __u32 max_send_wr;
+       __u32 max_recv_wr;
+       __u32 max_send_sge;
+       __u32 max_recv_sge;
+       __u32 max_inline_data;
+       __u8  sq_sig_all;
+       __u8  qp_type;
+       __u8  is_srq;
+       __u8  reserved;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_create_qp_resp {
+       __u32 qp_handle;
+       __u32 qpn;
+};
+
+/*
+ * This struct needs to remain a multiple of 8 bytes to keep the
+ * alignment of the modify QP parameters.
+ */
+struct ib_uverbs_qp_dest {
+       __u8  dgid[16];
+       __u32 flow_label;
+       __u16 dlid;
+       __u16 reserved;
+       __u8  sgid_index;
+       __u8  hop_limit;
+       __u8  traffic_class;
+       __u8  sl;
+       __u8  src_path_bits;
+       __u8  static_rate;
+       __u8  is_global;
+       __u8  port_num;
+};
+
+struct ib_uverbs_modify_qp {
+       struct ib_uverbs_qp_dest dest;
+       struct ib_uverbs_qp_dest alt_dest;
+       __u32 qp_handle;
+       __u32 attr_mask;
+       __u32 qkey;
+       __u32 rq_psn;
+       __u32 sq_psn;
+       __u32 dest_qp_num;
+       __u32 qp_access_flags;
+       __u16 pkey_index;
+       __u16 alt_pkey_index;
+       __u8  qp_state;
+       __u8  cur_qp_state;
+       __u8  path_mtu;
+       __u8  path_mig_state;
+       __u8  en_sqd_async_notify;
+       __u8  max_rd_atomic;
+       __u8  max_dest_rd_atomic;
+       __u8  min_rnr_timer;
+       __u8  port_num;
+       __u8  timeout;
+       __u8  retry_cnt;
+       __u8  rnr_retry;
+       __u8  alt_port_num;
+       __u8  alt_timeout;
+       __u8  reserved[2];
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_modify_qp_resp {
+};
+
+struct ib_uverbs_destroy_qp {
+       __u32 qp_handle;
+};
+
+struct ib_uverbs_attach_mcast {
+       __u8  gid[16];
+       __u32 qp_handle;
+       __u16 mlid;
+       __u16 reserved;
+       __u64 driver_data[0];
+};
+
+struct ib_uverbs_detach_mcast {
+       __u8  gid[16];
+       __u32 qp_handle;
+       __u16 mlid;
+       __u16 reserved;
+       __u64 driver_data[0];
+};
+
+#endif /* IB_USER_VERBS_H */
index cf01f044a223086ca0d5d27f043c878a6c2e0dc3..e5bd9a10c20137a06e712624de51a1de30bf8235 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (c) 2004 Intel Corporation.  All rights reserved.
  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
  * Copyright (c) 2004 Voltaire Corporation.  All rights reserved.
+ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
 
 #include <linux/types.h>
 #include <linux/device.h>
+
 #include <asm/atomic.h>
+#include <asm/scatterlist.h>
+#include <asm/uaccess.h>
 
 union ib_gid {
        u8      raw[16];
@@ -544,7 +548,7 @@ struct ib_send_wr {
        int                     num_sge;
        enum ib_wr_opcode       opcode;
        int                     send_flags;
-       u32                     imm_data;
+       __be32                  imm_data;
        union {
                struct {
                        u64     remote_addr;
@@ -618,29 +622,86 @@ struct ib_fmr_attr {
        u8      page_size;
 };
 
+struct ib_ucontext {
+       struct ib_device       *device;
+       struct list_head        pd_list;
+       struct list_head        mr_list;
+       struct list_head        mw_list;
+       struct list_head        cq_list;
+       struct list_head        qp_list;
+       struct list_head        srq_list;
+       struct list_head        ah_list;
+       spinlock_t              lock;
+};
+
+struct ib_uobject {
+       u64                     user_handle;    /* handle given to us by userspace */
+       struct ib_ucontext     *context;        /* associated user context */
+       struct list_head        list;           /* link to context's list */
+       u32                     id;             /* index into kernel idr */
+};
+
+struct ib_umem {
+       unsigned long           user_base;
+       unsigned long           virt_base;
+       size_t                  length;
+       int                     offset;
+       int                     page_size;
+       int                     writable;
+       struct list_head        chunk_list;
+};
+
+struct ib_umem_chunk {
+       struct list_head        list;
+       int                     nents;
+       int                     nmap;
+       struct scatterlist      page_list[0];
+};
+
+struct ib_udata {
+       void __user *inbuf;
+       void __user *outbuf;
+       size_t       inlen;
+       size_t       outlen;
+};
+
+#define IB_UMEM_MAX_PAGE_CHUNK                                         \
+       ((PAGE_SIZE - offsetof(struct ib_umem_chunk, page_list)) /      \
+        ((void *) &((struct ib_umem_chunk *) 0)->page_list[1] -        \
+         (void *) &((struct ib_umem_chunk *) 0)->page_list[0]))
+
+struct ib_umem_object {
+       struct ib_uobject       uobject;
+       struct ib_umem          umem;
+};
+
 struct ib_pd {
-       struct ib_device *device;
-       atomic_t          usecnt; /* count all resources */
+       struct ib_device       *device;
+       struct ib_uobject      *uobject;
+       atomic_t                usecnt; /* count all resources */
 };
 
 struct ib_ah {
        struct ib_device        *device;
        struct ib_pd            *pd;
+       struct ib_uobject       *uobject;
 };
 
 typedef void (*ib_comp_handler)(struct ib_cq *cq, void *cq_context);
 
 struct ib_cq {
-       struct ib_device *device;
-       ib_comp_handler   comp_handler;
-       void             (*event_handler)(struct ib_event *, void *);
-       void *            cq_context;
-       int               cqe;
-       atomic_t          usecnt; /* count number of work queues */
+       struct ib_device       *device;
+       struct ib_uobject      *uobject;
+       ib_comp_handler         comp_handler;
+       void                  (*event_handler)(struct ib_event *, void *);
+       void *                  cq_context;
+       int                     cqe;
+       atomic_t                usecnt; /* count number of work queues */
 };
 
 struct ib_srq {
        struct ib_device        *device;
+       struct ib_uobject       *uobject;
        struct ib_pd            *pd;
        void                    *srq_context;
        atomic_t                usecnt;
@@ -652,6 +713,7 @@ struct ib_qp {
        struct ib_cq           *send_cq;
        struct ib_cq           *recv_cq;
        struct ib_srq          *srq;
+       struct ib_uobject      *uobject;
        void                  (*event_handler)(struct ib_event *, void *);
        void                   *qp_context;
        u32                     qp_num;
@@ -659,16 +721,18 @@ struct ib_qp {
 };
 
 struct ib_mr {
-       struct ib_device *device;
-       struct ib_pd     *pd;
-       u32               lkey;
-       u32               rkey;
-       atomic_t          usecnt; /* count number of MWs */
+       struct ib_device  *device;
+       struct ib_pd      *pd;
+       struct ib_uobject *uobject;
+       u32                lkey;
+       u32                rkey;
+       atomic_t           usecnt; /* count number of MWs */
 };
 
 struct ib_mw {
        struct ib_device        *device;
        struct ib_pd            *pd;
+       struct ib_uobject       *uobject;
        u32                     rkey;
 };
 
@@ -737,7 +801,14 @@ struct ib_device {
        int                        (*modify_port)(struct ib_device *device,
                                                  u8 port_num, int port_modify_mask,
                                                  struct ib_port_modify *port_modify);
-       struct ib_pd *             (*alloc_pd)(struct ib_device *device);
+       struct ib_ucontext *       (*alloc_ucontext)(struct ib_device *device,
+                                                    struct ib_udata *udata);
+       int                        (*dealloc_ucontext)(struct ib_ucontext *context);
+       int                        (*mmap)(struct ib_ucontext *context,
+                                          struct vm_area_struct *vma);
+       struct ib_pd *             (*alloc_pd)(struct ib_device *device,
+                                              struct ib_ucontext *context,
+                                              struct ib_udata *udata);
        int                        (*dealloc_pd)(struct ib_pd *pd);
        struct ib_ah *             (*create_ah)(struct ib_pd *pd,
                                                struct ib_ah_attr *ah_attr);
@@ -747,7 +818,8 @@ struct ib_device {
                                               struct ib_ah_attr *ah_attr);
        int                        (*destroy_ah)(struct ib_ah *ah);
        struct ib_qp *             (*create_qp)(struct ib_pd *pd,
-                                               struct ib_qp_init_attr *qp_init_attr);
+                                               struct ib_qp_init_attr *qp_init_attr,
+                                               struct ib_udata *udata);
        int                        (*modify_qp)(struct ib_qp *qp,
                                                struct ib_qp_attr *qp_attr,
                                                int qp_attr_mask);
@@ -762,8 +834,9 @@ struct ib_device {
        int                        (*post_recv)(struct ib_qp *qp,
                                                struct ib_recv_wr *recv_wr,
                                                struct ib_recv_wr **bad_recv_wr);
-       struct ib_cq *             (*create_cq)(struct ib_device *device,
-                                               int cqe);
+       struct ib_cq *             (*create_cq)(struct ib_device *device, int cqe,
+                                               struct ib_ucontext *context,
+                                               struct ib_udata *udata);
        int                        (*destroy_cq)(struct ib_cq *cq);
        int                        (*resize_cq)(struct ib_cq *cq, int *cqe);
        int                        (*poll_cq)(struct ib_cq *cq, int num_entries,
@@ -780,6 +853,10 @@ struct ib_device {
                                                  int num_phys_buf,
                                                  int mr_access_flags,
                                                  u64 *iova_start);
+       struct ib_mr *             (*reg_user_mr)(struct ib_pd *pd,
+                                                 struct ib_umem *region,
+                                                 int mr_access_flags,
+                                                 struct ib_udata *udata);
        int                        (*query_mr)(struct ib_mr *mr,
                                               struct ib_mr_attr *mr_attr);
        int                        (*dereg_mr)(struct ib_mr *mr);
@@ -817,6 +894,7 @@ struct ib_device {
                                                  struct ib_mad *in_mad,
                                                  struct ib_mad *out_mad);
 
+       struct module               *owner;
        struct class_device          class_dev;
        struct kobject               ports_parent;
        struct list_head             port_list;
@@ -852,6 +930,16 @@ void *ib_get_client_data(struct ib_device *device, struct ib_client *client);
 void  ib_set_client_data(struct ib_device *device, struct ib_client *client,
                         void *data);
 
+static inline int ib_copy_from_udata(void *dest, struct ib_udata *udata, size_t len)
+{
+       return copy_from_user(dest, udata->inbuf, len) ? -EFAULT : 0;
+}
+
+static inline int ib_copy_to_udata(struct ib_udata *udata, void *src, size_t len)
+{
+       return copy_to_user(udata->outbuf, src, len) ? -EFAULT : 0;
+}
+
 int ib_register_event_handler  (struct ib_event_handler *event_handler);
 int ib_unregister_event_handler(struct ib_event_handler *event_handler);
 void ib_dispatch_event(struct ib_event *event);
index ee750e9456dd4908a3f48487f1c148a18f1ca118..db9bad2b3d165cec9aab180cbe50bdd5697651dc 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -161,11 +160,6 @@ static dev_link_t *avmcs_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask =
-       CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-       CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-       CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &avmcs_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -500,6 +494,7 @@ static struct pcmcia_driver avmcs_driver = {
                .name   = "avm_cs",
        },
        .attach = avmcs_attach,
+       .event  = avmcs_event,
        .detach = avmcs_detach,
        .id_table = avmcs_ids,
 };
index 67c60e04a37bdb38f6e5108164b0c8c5a9ab30ee..0e22991635e7510ddd6f91f6fcd090ca213bce4a 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -183,11 +182,6 @@ static dev_link_t *avma1cs_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask =
-       CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-       CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-       CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &avma1cs_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -514,6 +508,7 @@ static struct pcmcia_driver avma1cs_driver = {
                .name   = "avma1_cs",
        },
        .attach         = avma1cs_attach,
+       .event          = avma1cs_event,
        .detach         = avma1cs_detach,
        .id_table       = avma1cs_ids,
 };
index 9146be547044a071fd3d6ebc6cb6eb32eff22ae4..6fc6868de0b03191626de7203d8ae2aa5cec70cd 100644 (file)
@@ -47,7 +47,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -212,11 +211,6 @@ static dev_link_t *elsa_cs_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask =
-        CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-        CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-        CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &elsa_cs_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -521,6 +515,7 @@ static struct pcmcia_driver elsa_cs_driver = {
                .name   = "elsa_cs",
        },
        .attach         = elsa_cs_attach,
+       .event          = elsa_cs_event,
        .detach         = elsa_cs_detach,
        .id_table       = elsa_ids,
 };
index ac899503a74f1ee49b117de3b0d12d670a5a7ab0..bab356886483e257b7c718e4bde5fe6c7e3ae9f7 100644 (file)
@@ -279,7 +279,8 @@ BChannel_proc_xmt(struct BCState *bcs)
        if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags))
                st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
        if (!test_bit(BC_FLG_ACTIV, &bcs->Flag)) {
-               if (!test_bit(BC_FLG_BUSY, &bcs->Flag) && (!skb_queue_len(&bcs->squeue))) {
+               if (!test_bit(BC_FLG_BUSY, &bcs->Flag) &&
+                   skb_queue_empty(&bcs->squeue)) {
                        st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL);
                }
        }
index 9022583fd6a06e97b76a6c44dddcc0b7d7eacf8b..1615c1a76ab8ace39682e503a41059f2de671d18 100644 (file)
@@ -108,7 +108,8 @@ static int l2addrsize(struct Layer2 *l2);
 static void
 set_peer_busy(struct Layer2 *l2) {
        test_and_set_bit(FLG_PEER_BUSY, &l2->flag);
-       if (skb_queue_len(&l2->i_queue) || skb_queue_len(&l2->ui_queue))
+       if (!skb_queue_empty(&l2->i_queue) ||
+           !skb_queue_empty(&l2->ui_queue))
                test_and_set_bit(FLG_L2BLOCK, &l2->flag);
 }
 
@@ -754,7 +755,7 @@ l2_restart_multi(struct FsmInst *fi, int event, void *arg)
                st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL);
 
        if ((ST_L2_7==state) || (ST_L2_8 == state))
-               if (skb_queue_len(&st->l2.i_queue) && cansend(st))
+               if (!skb_queue_empty(&st->l2.i_queue) && cansend(st))
                        st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 }
 
@@ -810,7 +811,7 @@ l2_connected(struct FsmInst *fi, int event, void *arg)
        if (pr != -1)
                st->l2.l2l3(st, pr, NULL);
 
-       if (skb_queue_len(&st->l2.i_queue) && cansend(st))
+       if (!skb_queue_empty(&st->l2.i_queue) && cansend(st))
                st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 }
 
@@ -1014,7 +1015,7 @@ l2_st7_got_super(struct FsmInst *fi, int event, void *arg)
                        if(typ != RR) FsmDelTimer(&st->l2.t203, 9);
                        restart_t200(st, 12);
                }
-               if (skb_queue_len(&st->l2.i_queue) && (typ == RR))
+               if (!skb_queue_empty(&st->l2.i_queue) && (typ == RR))
                        st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
        } else
                nrerrorrecovery(fi);
@@ -1120,7 +1121,7 @@ l2_got_iframe(struct FsmInst *fi, int event, void *arg)
                return;
        }
 
-       if (skb_queue_len(&st->l2.i_queue) && (fi->state == ST_L2_7))
+       if (!skb_queue_empty(&st->l2.i_queue) && (fi->state == ST_L2_7))
                st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
        if (test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag))
                enquiry_cr(st, RR, RSP, 0);
@@ -1138,7 +1139,7 @@ l2_got_tei(struct FsmInst *fi, int event, void *arg)
                test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
        } else
                FsmChangeState(fi, ST_L2_4);
-       if (skb_queue_len(&st->l2.ui_queue))
+       if (!skb_queue_empty(&st->l2.ui_queue))
                tx_ui(st);
 }
 
@@ -1301,7 +1302,7 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
                FsmDelTimer(&st->l2.t203, 13);
                FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 11);
        }
-       if (skb_queue_len(&l2->i_queue) && cansend(st))
+       if (!skb_queue_empty(&l2->i_queue) && cansend(st))
                st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 }
 
@@ -1347,7 +1348,7 @@ l2_st8_got_super(struct FsmInst *fi, int event, void *arg)
                        }
                        invoke_retransmission(st, nr);
                        FsmChangeState(fi, ST_L2_7);
-                       if (skb_queue_len(&l2->i_queue) && cansend(st))
+                       if (!skb_queue_empty(&l2->i_queue) && cansend(st))
                                st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
                } else
                        nrerrorrecovery(fi);
index abcc9530eb347b007b74ea1f5a774c361e2c9902..c9917cd2132b74e0fb311447aaa66c1b03cdd395 100644 (file)
@@ -302,7 +302,7 @@ release_l3_process(struct l3_process *p)
                                !test_bit(FLG_PTP, &p->st->l2.flag)) {
                                if (p->debug)
                                        l3_debug(p->st, "release_l3_process: last process");
-                               if (!skb_queue_len(&p->st->l3.squeue)) {
+                               if (skb_queue_empty(&p->st->l3.squeue)) {
                                        if (p->debug)
                                                l3_debug(p->st, "release_l3_process: release link");
                                        if (p->st->protocol != ISDN_PTYPE_NI1)
index 058147a6957624fbe434735541386cfa8f50a1cc..c6b5bf7d2acaf32544f6a502de70693f9cd0fb3a 100644 (file)
@@ -47,7 +47,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -226,11 +225,6 @@ static dev_link_t *sedlbauer_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask =
-       CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-       CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-       CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &sedlbauer_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -634,6 +628,7 @@ static struct pcmcia_driver sedlbauer_driver = {
                .name   = "sedlbauer_cs",
        },
        .attach         = sedlbauer_attach,
+       .event          = sedlbauer_event,
        .detach         = sedlbauer_detach,
        .id_table       = sedlbauer_ids,
 };
index 107376ff5b9b53a61683cc0a5d116740e35fb8a3..0ddef1bf778bd67130be130778ec6653f473d843 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -193,11 +192,6 @@ static dev_link_t *teles_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask =
-        CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-        CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-        CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &teles_cs_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -501,6 +495,7 @@ static struct pcmcia_driver teles_cs_driver = {
                .name   = "teles_cs",
        },
        .attach         = teles_attach,
+       .event          = teles_cs_event,
        .detach         = teles_detach,
        .id_table       = teles_ids,
 };
index ad5aa38fb5a6eb6001b4b97d1f8154037f3836e3..b37ef1f06b3dffa55e36c313f7dd7238a1b6ceb0 100644 (file)
@@ -1223,7 +1223,7 @@ isdn_tty_write(struct tty_struct *tty, const u_char * buf, int count)
                total += c;
        }
        atomic_dec(&info->xmit_lock);
-       if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue))) {
+       if ((info->xmit_count) || !skb_queue_empty(&info->xmit_queue)) {
                if (m->mdmreg[REG_DXMT] & BIT_DXMT) {
                        isdn_tty_senddown(info);
                        isdn_tty_tint(info);
@@ -1284,7 +1284,7 @@ isdn_tty_flush_chars(struct tty_struct *tty)
 
        if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_flush_chars"))
                return;
-       if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue)))
+       if ((info->xmit_count) || !skb_queue_empty(&info->xmit_queue))
                isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
 }
 
index 9fc0c1e037321d6a295165e731cfc41a5b54cbd4..e0d1b01cc74c5b5badfa64cd2ca1a4a1457b7c68 100644 (file)
@@ -304,12 +304,12 @@ icn_pollbchan_send(int channel, icn_card * card)
        isdn_ctrl cmd;
 
        if (!(card->sndcount[channel] || card->xskb[channel] ||
-             skb_queue_len(&card->spqueue[channel])))
+             !skb_queue_empty(&card->spqueue[channel])))
                return;
        if (icn_trymaplock_channel(card, mch)) {
                while (sbfree && 
                       (card->sndcount[channel] ||
-                       skb_queue_len(&card->spqueue[channel]) ||
+                       !skb_queue_empty(&card->spqueue[channel]) ||
                        card->xskb[channel])) {
                        spin_lock_irqsave(&card->lock, flags);
                        if (card->xmit_lock[channel]) {
index 6e3cf7e134515c1540ba4409ee2eedf5cf4ba094..12031c9d3f1e1394379ee211ae49bf61ff093949 100644 (file)
@@ -1060,6 +1060,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        }
 
        ti->private = ms;
+       ti->split_io = ms->rh.region_size;
 
        r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client);
        if (r) {
index 50e8b865401883331741896bea4eae2afc739f99..cd5828b5e9e346ad2199ef18d542f31ebc0413ec 100644 (file)
@@ -62,13 +62,15 @@ void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data)
 int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop)
 {
        unsigned long start;
+       int err;
 
        /* wait for registers to be programmed */
        start = jiffies;
        while (1) {
-                if (saa7146_read(dev, MC2) & 2)
-                        break;
-               if (time_after(jiffies, start + HZ/20)) {
+               err = time_after(jiffies, start + HZ/20);
+               if (saa7146_read(dev, MC2) & 2)
+                       break;
+               if (err) {
                        DEB_S(("timed out while waiting for registers getting programmed\n"));
                        return -ETIMEDOUT;
                }
@@ -79,10 +81,11 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop)
        /* wait for transfer to complete */
        start = jiffies;
        while (1) {
+               err = time_after(jiffies, start + HZ/4);
                if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S))
                        break;
                saa7146_read(dev, MC2);
-               if (time_after(jiffies, start + HZ/4)) {
+               if (err) {
                        DEB_S(("timed out while waiting for transfer completion\n"));
                        return -ETIMEDOUT;
                }
@@ -512,7 +515,7 @@ int saa7146_register_extension(struct saa7146_extension* ext)
        ext->driver.remove = saa7146_remove_one;
 
        printk("saa7146: register extension '%s'.\n",ext->name);
-       return pci_module_init(&ext->driver);
+       return pci_register_driver(&ext->driver);
 }
 
 int saa7146_unregister_extension(struct saa7146_extension* ext)
index 01387f883cdff2e1d1bbe774674ab42cd2ff352e..3f0ec6be03ae353811b264f83283e5f5a86721de 100644 (file)
@@ -40,6 +40,10 @@ comment "Supported BT878 Adapters"
        depends on DVB_CORE && PCI
 source "drivers/media/dvb/bt8xx/Kconfig"
 
+comment "Supported Pluto2 Adapters"
+       depends on DVB_CORE && PCI
+source "drivers/media/dvb/pluto2/Kconfig"
+
 comment "Supported DVB Frontends"
        depends on DVB_CORE
 source "drivers/media/dvb/frontends/Kconfig"
index 3c6ff16191033ab1943dafaac7b61f28870eacb7..a7ad0841e6fc049a662965718373c7bd468ef97f 100644 (file)
@@ -2,4 +2,4 @@
 # Makefile for the kernel multimedia device drivers.
 #
 
-obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/
+obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/
index fafd0ab3a28fc90f8828d24a8c51e546322f62ac..d7417eac2abad01c54f16bcfa3f2e3af28d89599 100644 (file)
@@ -35,17 +35,3 @@ config DVB_B2C2_FLEXCOP_DEBUG
        help
          Say Y if you want to enable the module option to control debug messages
          of all B2C2 FlexCop drivers.
-
-config DVB_B2C2_SKYSTAR
-       tristate "B2C2/Technisat Air/Sky/CableStar 2 PCI"
-       depends on DVB_CORE && PCI
-       select DVB_STV0299
-       select DVB_MT352
-       select DVB_MT312
-       select DVB_NXT2002
-       help
-         Support for the Skystar2 PCI DVB card by Technisat, which
-         is equipped with the FlexCopII chipset by B2C2, and
-         for the B2C2/BBTI Air2PC-ATSC card.
-
-         Say Y if you own such a device and want to use it.
index 7703812af34f9f9001de8fcb9820bf83350e4a53..1a1c3bca55fa33a96bccbb9ab7879b17df71e0df 100644 (file)
@@ -9,6 +9,4 @@ obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o
 b2c2-flexcop-usb-objs = flexcop-usb.o
 obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
 
-obj-$(CONFIG_DVB_B2C2_SKYSTAR) += skystar2.o
-
 EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
index 773d158032dfb4cf26ef4cf7aea8a1ef51dc23ea..a94912ac1872797384b53f3f4a1e4cba24e476a8 100644 (file)
@@ -108,6 +108,8 @@ void flexcop_device_kfree(struct flexcop_device*);
 int  flexcop_device_initialize(struct flexcop_device*);
 void flexcop_device_exit(struct flexcop_device *fc);
 
+void flexcop_reset_block_300(struct flexcop_device *fc);
+
 /* from flexcop-dma.c */
 int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size);
 void flexcop_dma_free(struct flexcop_dma *dma);
@@ -115,7 +117,8 @@ void flexcop_dma_free(struct flexcop_dma *dma);
 int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
 int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
 int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
-int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx,flexcop_dma_addr_index_t index);
+int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx);
+int flexcop_dma_xfer_control(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index, int onoff);
 int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles);
 int flexcop_dma_config_packet_count(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 packets);
 
@@ -151,6 +154,7 @@ int flexcop_sram_init(struct flexcop_device *fc);
 /* from flexcop-misc.c */
 void flexcop_determine_revision(struct flexcop_device *fc);
 void flexcop_device_name(struct flexcop_device *fc,const char *prefix,const char *suffix);
+void flexcop_dump_reg(struct flexcop_device *fc, flexcop_ibi_register reg, int num);
 
 /* from flexcop-hw-filter.c */
 int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *dvbdmxfeed, int onoff);
index 8d27060753604954a406a1e8dfc6e669f5679a47..cf4ed1df60862b96a1d5750e2b4d867fdcb8e0df 100644 (file)
@@ -37,22 +37,90 @@ void flexcop_dma_free(struct flexcop_dma *dma)
 }
 EXPORT_SYMBOL(flexcop_dma_free);
 
-int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff)
+int flexcop_dma_config(struct flexcop_device *fc,
+               struct flexcop_dma *dma,
+               flexcop_dma_index_t dma_idx)
 {
-       flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
+       flexcop_ibi_value v0x0,v0x4,v0xc;
+       v0x0.raw = v0x4.raw = v0xc.raw = 0;
 
-       if (no & FC_DMA_1)
-               v.ctrl_208.DMA1_Timer_Enable_sig = onoff;
+       v0x0.dma_0x0.dma_address0        = dma->dma_addr0 >> 2;
+       v0xc.dma_0xc.dma_address1        = dma->dma_addr1 >> 2;
+       v0x4.dma_0x4_write.dma_addr_size = dma->size / 4;
 
-       if (no & FC_DMA_2)
-               v.ctrl_208.DMA2_Timer_Enable_sig = onoff;
+       if ((dma_idx & FC_DMA_1) == dma_idx) {
+               fc->write_ibi_reg(fc,dma1_000,v0x0);
+               fc->write_ibi_reg(fc,dma1_004,v0x4);
+               fc->write_ibi_reg(fc,dma1_00c,v0xc);
+       } else if ((dma_idx & FC_DMA_2) == dma_idx) {
+               fc->write_ibi_reg(fc,dma2_010,v0x0);
+               fc->write_ibi_reg(fc,dma2_014,v0x4);
+               fc->write_ibi_reg(fc,dma2_01c,v0xc);
+       } else {
+               err("either DMA1 or DMA2 can be configured at the within one flexcop_dma_config call.");
+               return -EINVAL;
+       }
 
-       fc->write_ibi_reg(fc,ctrl_208,v);
        return 0;
 }
-EXPORT_SYMBOL(flexcop_dma_control_timer_irq);
+EXPORT_SYMBOL(flexcop_dma_config);
+
+/* start the DMA transfers, but not the DMA IRQs */
+int flexcop_dma_xfer_control(struct flexcop_device *fc,
+               flexcop_dma_index_t dma_idx,
+               flexcop_dma_addr_index_t index,
+               int onoff)
+{
+       flexcop_ibi_value v0x0,v0xc;
+       flexcop_ibi_register r0x0,r0xc;
+
+       if ((dma_idx & FC_DMA_1) == dma_idx) {
+               r0x0 = dma1_000;
+               r0xc = dma1_00c;
+       } else if ((dma_idx & FC_DMA_2) == dma_idx) {
+               r0x0 = dma2_010;
+               r0xc = dma2_01c;
+       } else {
+               err("either transfer DMA1 or DMA2 can be started within one flexcop_dma_xfer_control call.");
+               return -EINVAL;
+       }
+
+       v0x0 = fc->read_ibi_reg(fc,r0x0);
+       v0xc = fc->read_ibi_reg(fc,r0xc);
+
+       deb_rdump("reg: %03x: %x\n",r0x0,v0x0.raw);
+       deb_rdump("reg: %03x: %x\n",r0xc,v0xc.raw);
+
+       if (index & FC_DMA_SUBADDR_0)
+               v0x0.dma_0x0.dma_0start = onoff;
+
+       if (index & FC_DMA_SUBADDR_1)
+               v0xc.dma_0xc.dma_1start = onoff;
+
+       fc->write_ibi_reg(fc,r0x0,v0x0);
+       fc->write_ibi_reg(fc,r0xc,v0xc);
+
+       deb_rdump("reg: %03x: %x\n",r0x0,v0x0.raw);
+       deb_rdump("reg: %03x: %x\n",r0xc,v0xc.raw);
+       return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_xfer_control);
+
+static int flexcop_dma_remap(struct flexcop_device *fc,
+               flexcop_dma_index_t dma_idx,
+               int onoff)
+{
+       flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c;
+       flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
+       deb_info("%s\n",__FUNCTION__);
+       v.dma_0xc.remap_enable = onoff;
+       fc->write_ibi_reg(fc,r,v);
+       return 0;
+}
 
-int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff)
+int flexcop_dma_control_size_irq(struct flexcop_device *fc,
+               flexcop_dma_index_t no,
+               int onoff)
 {
        flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
 
@@ -67,75 +135,64 @@ int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t
 }
 EXPORT_SYMBOL(flexcop_dma_control_size_irq);
 
-int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff)
+int flexcop_dma_control_timer_irq(struct flexcop_device *fc,
+               flexcop_dma_index_t no,
+               int onoff)
 {
        flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
 
        if (no & FC_DMA_1)
-               v.ctrl_208.DMA1_Size_IRQ_Enable_sig = onoff;
+               v.ctrl_208.DMA1_Timer_Enable_sig = onoff;
 
        if (no & FC_DMA_2)
-               v.ctrl_208.DMA2_Size_IRQ_Enable_sig = onoff;
+               v.ctrl_208.DMA2_Timer_Enable_sig = onoff;
 
        fc->write_ibi_reg(fc,ctrl_208,v);
        return 0;
 }
-EXPORT_SYMBOL(flexcop_dma_control_packet_irq);
+EXPORT_SYMBOL(flexcop_dma_control_timer_irq);
 
-int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx,flexcop_dma_addr_index_t index)
+/* 1 cycles = 1.97 msec */
+int flexcop_dma_config_timer(struct flexcop_device *fc,
+               flexcop_dma_index_t dma_idx,
+               u8 cycles)
 {
+       flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
+       flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
 
-       flexcop_ibi_value v0x0,v0x4,v0xc;
-       v0x0.raw = v0x4.raw = v0xc.raw = 0;
-
-       v0x0.dma_0x0.dma_address0        = dma->dma_addr0 >> 2;
-       v0xc.dma_0xc.dma_address1        = dma->dma_addr1 >> 2;
-       v0x4.dma_0x4_write.dma_addr_size = dma->size / 4;
-
-       if (index & FC_DMA_SUBADDR_0)
-               v0x0.dma_0x0.dma_0start = 1;
-
-       if (index & FC_DMA_SUBADDR_1)
-               v0xc.dma_0xc.dma_1start = 1;
-
-       if (dma_idx & FC_DMA_1) {
-               fc->write_ibi_reg(fc,dma1_000,v0x0);
-               fc->write_ibi_reg(fc,dma1_004,v0x4);
-               fc->write_ibi_reg(fc,dma1_00c,v0xc);
-       } else { /* (dma_idx & FC_DMA_2) */
-               fc->write_ibi_reg(fc,dma2_010,v0x0);
-               fc->write_ibi_reg(fc,dma2_014,v0x4);
-               fc->write_ibi_reg(fc,dma2_01c,v0xc);
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(flexcop_dma_config);
+       flexcop_dma_remap(fc,dma_idx,0);
 
-static int flexcop_dma_remap(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, int onoff)
-{
-       flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c;
-       flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
-       v.dma_0xc.remap_enable = onoff;
+       deb_info("%s\n",__FUNCTION__);
+       v.dma_0x4_write.dmatimer = cycles;
        fc->write_ibi_reg(fc,r,v);
        return 0;
 }
+EXPORT_SYMBOL(flexcop_dma_config_timer);
 
-/* 1 cycles = 1.97 msec */
-int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles)
+/* packet IRQ does not exist in FCII or FCIIb - according to data book and tests */
+int flexcop_dma_control_packet_irq(struct flexcop_device *fc,
+               flexcop_dma_index_t no,
+               int onoff)
 {
-       flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
-       flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
+       flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
 
-       flexcop_dma_remap(fc,dma_idx,0);
+       deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw);
+       if (no & FC_DMA_1)
+               v.ctrl_208.DMA1_Size_IRQ_Enable_sig = onoff;
+
+       if (no & FC_DMA_2)
+               v.ctrl_208.DMA2_Size_IRQ_Enable_sig = onoff;
+
+       fc->write_ibi_reg(fc,ctrl_208,v);
+       deb_rdump("reg: %03x: %x\n",ctrl_208,v.raw);
 
-       v.dma_0x4_write.dmatimer = cycles >> 1;
-       fc->write_ibi_reg(fc,r,v);
        return 0;
 }
-EXPORT_SYMBOL(flexcop_dma_config_timer);
+EXPORT_SYMBOL(flexcop_dma_control_packet_irq);
 
-int flexcop_dma_config_packet_count(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 packets)
+int flexcop_dma_config_packet_count(struct flexcop_device *fc,
+               flexcop_dma_index_t dma_idx,
+               u8 packets)
 {
        flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
        flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
index 2baf43d3ce8ffdcce73d556b107c12e36208f08d..75cf237196eb85203a9b8306cebd38850290d643 100644 (file)
@@ -10,6 +10,8 @@
 static void flexcop_rcv_data_ctrl(struct flexcop_device *fc, int onoff)
 {
        flexcop_set_ibi_value(ctrl_208,Rcv_Data_sig,onoff);
+
+       deb_ts("rcv_data is now: '%s'\n",onoff ? "on" : "off");
 }
 
 void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff)
@@ -151,7 +153,7 @@ int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *d
 {
        int max_pid_filter = 6 + fc->has_32_hw_pid_filter*32;
 
-       fc->feedcount += onoff ? 1 : -1;
+       fc->feedcount += onoff ? 1 : -1; /* the number of PIDs/Feed currently requested */
        if (dvbdmxfeed->index >= max_pid_filter)
                fc->extra_feedcount += onoff ? 1 : -1;
 
@@ -178,8 +180,14 @@ int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *d
        /* if it was the first or last feed request change the stream-status */
        if (fc->feedcount == onoff) {
                flexcop_rcv_data_ctrl(fc,onoff);
-               if (fc->stream_control)
+               if (fc->stream_control) /* device specific stream control */
                        fc->stream_control(fc,onoff);
+
+               /* feeding stopped -> reset the flexcop filter*/
+               if (onoff == 0) {
+                       flexcop_reset_block_300(fc);
+                       flexcop_hw_filter_init(fc);
+               }
        }
 
        return 0;
index 23082545651fd2e36d6d5424bf15954b97779675..3a08d38b318a94b8007840cf004df498ac8f7af2 100644 (file)
@@ -65,3 +65,15 @@ void flexcop_device_name(struct flexcop_device *fc,const char *prefix,const
                        flexcop_device_names[fc->dev_type],flexcop_bus_names[fc->bus_type],
                        flexcop_revision_names[fc->rev],suffix);
 }
+
+void flexcop_dump_reg(struct flexcop_device *fc, flexcop_ibi_register reg, int num)
+{
+       flexcop_ibi_value v;
+       int i;
+       for (i = 0; i < num; i++) {
+               v = fc->read_ibi_reg(fc,reg+4*i);
+               deb_rdump("0x%03x: %08x, ",reg+4*i, v.raw);
+       }
+       deb_rdump("\n");
+}
+EXPORT_SYMBOL(flexcop_dump_reg);
index ed717c0073d5d63db1b3e1cf39011d51b9236db4..2f76eb3fea40c2d81d6a91ad310fd65e14134c8d 100644 (file)
@@ -13,6 +13,10 @@ static int enable_pid_filtering = 1;
 module_param(enable_pid_filtering, int, 0444);
 MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1");
 
+static int irq_chk_intv;
+module_param(irq_chk_intv, int, 0644);
+MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently just debugging).");
+
 #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
 #define dprintk(level,args...) \
        do { if ((debug & level)) printk(args); } while (0)
@@ -26,6 +30,7 @@ MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported
 #define deb_reg(args...)   dprintk(0x02,args)
 #define deb_ts(args...)    dprintk(0x04,args)
 #define deb_irq(args...)   dprintk(0x08,args)
+#define deb_chk(args...)   dprintk(0x10,args)
 
 static int debug = 0;
 module_param(debug, int, 0644);
@@ -56,6 +61,10 @@ struct flexcop_pci {
 
        spinlock_t irq_lock;
 
+       unsigned long last_irq;
+
+       struct work_struct irq_check_work;
+
        struct flexcop_device *fc_dev;
 };
 
@@ -88,18 +97,55 @@ static int flexcop_pci_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_regi
        return 0;
 }
 
+static void flexcop_pci_irq_check_work(void *data)
+{
+       struct flexcop_pci *fc_pci = data;
+       struct flexcop_device *fc = fc_pci->fc_dev;
+
+       flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714);
+
+       flexcop_dump_reg(fc_pci->fc_dev,dma1_000,4);
+
+       if (v.sram_dest_reg_714.net_ovflow_error)
+               deb_chk("sram net_ovflow_error\n");
+       if (v.sram_dest_reg_714.media_ovflow_error)
+               deb_chk("sram media_ovflow_error\n");
+       if (v.sram_dest_reg_714.cai_ovflow_error)
+               deb_chk("sram cai_ovflow_error\n");
+       if (v.sram_dest_reg_714.cai_ovflow_error)
+               deb_chk("sram cai_ovflow_error\n");
+
+       schedule_delayed_work(&fc_pci->irq_check_work,
+                       msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv));
+}
+
 /* When PID filtering is turned on, we use the timer IRQ, because small amounts
  * of data need to be passed to the user space instantly as well. When PID
  * filtering is turned off, we use the page-change-IRQ */
-static irqreturn_t flexcop_pci_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t flexcop_pci_isr(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct flexcop_pci *fc_pci = dev_id;
        struct flexcop_device *fc = fc_pci->fc_dev;
-       flexcop_ibi_value v = fc->read_ibi_reg(fc,irq_20c);
+       flexcop_ibi_value v;
        irqreturn_t ret = IRQ_HANDLED;
 
        spin_lock_irq(&fc_pci->irq_lock);
 
+       v = fc->read_ibi_reg(fc,irq_20c);
+
+   /* errors */
+       if (v.irq_20c.Data_receiver_error)
+               deb_chk("data receiver error\n");
+       if (v.irq_20c.Continuity_error_flag)
+               deb_chk("Contunuity error flag is set\n");
+       if (v.irq_20c.LLC_SNAP_FLAG_set)
+               deb_chk("LLC_SNAP_FLAG_set is set\n");
+       if (v.irq_20c.Transport_Error)
+               deb_chk("Transport error\n");
+
+       if ((fc_pci->count % 1000) == 0)
+               deb_chk("%d valid irq took place so far\n",fc_pci->count);
+
        if (v.irq_20c.DMA1_IRQ_Status == 1) {
                if (fc_pci->active_dma1_addr == 0)
                        flexcop_pass_dmx_packets(fc_pci->fc_dev,fc_pci->dma[0].cpu_addr0,fc_pci->dma[0].size / 188);
@@ -115,8 +161,9 @@ static irqreturn_t flexcop_pci_irq(int irq, void *dev_id, struct pt_regs *regs)
                        fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2;
                u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0;
 
-               deb_irq("irq: %08x cur_addr: %08x: cur_pos: %08x, last_cur_pos: %08x ",
-                               v.raw,cur_addr,cur_pos,fc_pci->last_dma1_cur_pos);
+               deb_irq("%u irq: %08x cur_addr: %08x: cur_pos: %08x, last_cur_pos: %08x ",
+                               jiffies_to_usecs(jiffies - fc_pci->last_irq),v.raw,cur_addr,cur_pos,fc_pci->last_dma1_cur_pos);
+               fc_pci->last_irq = jiffies;
 
                /* buffer end was reached, restarted from the beginning
                 * pass the data from last_cur_pos to the buffer end to the demux
@@ -127,7 +174,6 @@ static irqreturn_t flexcop_pci_irq(int irq, void *dev_id, struct pt_regs *regs)
                                        fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos,
                                        (fc_pci->dma[0].size*2) - fc_pci->last_dma1_cur_pos);
                        fc_pci->last_dma1_cur_pos = 0;
-                       fc_pci->count = 0;
                }
 
                if (cur_pos > fc_pci->last_dma1_cur_pos) {
@@ -139,16 +185,14 @@ static irqreturn_t flexcop_pci_irq(int irq, void *dev_id, struct pt_regs *regs)
                deb_irq("\n");
 
                fc_pci->last_dma1_cur_pos = cur_pos;
-       } else
+               fc_pci->count++;
+       } else {
+               deb_irq("isr for flexcop called, apparently without reason (%08x)\n",v.raw);
                ret = IRQ_NONE;
+       }
 
        spin_unlock_irq(&fc_pci->irq_lock);
 
-/* packet count would be ideal for hw filtering, but it isn't working. Either
- * the data book is wrong, or I'm unable to read it correctly */
-
-/*     if (v.irq_20c.DMA1_Size_IRQ_Status == 1) { packet counter */
-
        return ret;
 }
 
@@ -156,30 +200,35 @@ static int flexcop_pci_stream_control(struct flexcop_device *fc, int onoff)
 {
        struct flexcop_pci *fc_pci = fc->bus_specific;
        if (onoff) {
-               flexcop_dma_config(fc,&fc_pci->dma[0],FC_DMA_1,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1);
-               flexcop_dma_config(fc,&fc_pci->dma[1],FC_DMA_2,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1);
-               flexcop_dma_config_timer(fc,FC_DMA_1,1);
+               flexcop_dma_config(fc,&fc_pci->dma[0],FC_DMA_1);
+               flexcop_dma_config(fc,&fc_pci->dma[1],FC_DMA_2);
 
-               if (fc_pci->fc_dev->pid_filtering) {
-                       fc_pci->last_dma1_cur_pos = 0;
-                       flexcop_dma_control_timer_irq(fc,FC_DMA_1,1);
-               } else {
-                       fc_pci->active_dma1_addr = 0;
-                       flexcop_dma_control_size_irq(fc,FC_DMA_1,1);
-               }
+               flexcop_dma_config_timer(fc,FC_DMA_1,0);
 
-/*             flexcop_dma_config_packet_count(fc,FC_DMA_1,0xc0);
-               flexcop_dma_control_packet_irq(fc,FC_DMA_1,1); */
+               flexcop_dma_xfer_control(fc,FC_DMA_1,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1,1);
+               deb_irq("DMA xfer enabled\n");
 
-               deb_irq("irqs enabled\n");
+               fc_pci->last_dma1_cur_pos = 0;
+               flexcop_dma_control_timer_irq(fc,FC_DMA_1,1);
+               deb_irq("IRQ enabled\n");
+
+//             fc_pci->active_dma1_addr = 0;
+//             flexcop_dma_control_size_irq(fc,FC_DMA_1,1);
+
+               if (irq_chk_intv > 0)
+                       schedule_delayed_work(&fc_pci->irq_check_work,
+                                       msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv));
        } else {
-               if (fc_pci->fc_dev->pid_filtering)
-                       flexcop_dma_control_timer_irq(fc,FC_DMA_1,0);
-               else
-                       flexcop_dma_control_size_irq(fc,FC_DMA_1,0);
+               if (irq_chk_intv > 0)
+                       cancel_delayed_work(&fc_pci->irq_check_work);
+
+               flexcop_dma_control_timer_irq(fc,FC_DMA_1,0);
+               deb_irq("IRQ disabled\n");
 
-//             flexcop_dma_control_packet_irq(fc,FC_DMA_1,0);
-               deb_irq("irqs disabled\n");
+//             flexcop_dma_control_size_irq(fc,FC_DMA_1,0);
+
+               flexcop_dma_xfer_control(fc,FC_DMA_1,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1,0);
+               deb_irq("DMA xfer disabled\n");
        }
 
        return 0;
@@ -198,6 +247,7 @@ static int flexcop_pci_dma_init(struct flexcop_pci *fc_pci)
        flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_CAO   | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2);
 
        fc_pci->init_state |= FC_PCI_DMA_INIT;
+
        goto success;
 dma1_free:
        flexcop_dma_free(&fc_pci->dma[0]);
@@ -244,7 +294,7 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci)
 
        pci_set_drvdata(fc_pci->pdev, fc_pci);
 
-       if ((ret = request_irq(fc_pci->pdev->irq, flexcop_pci_irq,
+       if ((ret = request_irq(fc_pci->pdev->irq, flexcop_pci_isr,
                                        SA_SHIRQ, DRIVER_NAME, fc_pci)) != 0)
                goto err_pci_iounmap;
 
@@ -324,6 +374,8 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        if ((ret = flexcop_pci_dma_init(fc_pci)) != 0)
                goto err_fc_exit;
 
+       INIT_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work, fc_pci);
+
        goto success;
 err_fc_exit:
        flexcop_device_exit(fc);
@@ -350,17 +402,17 @@ static void flexcop_pci_remove(struct pci_dev *pdev)
 
 static struct pci_device_id flexcop_pci_tbl[] = {
        { PCI_DEVICE(0x13d0, 0x2103) },
-/*     { PCI_DEVICE(0x13d0, 0x2200) }, PCI FlexCopIII ? */
+/*     { PCI_DEVICE(0x13d0, 0x2200) }, ? */
        { },
 };
 
 MODULE_DEVICE_TABLE(pci, flexcop_pci_tbl);
 
 static struct pci_driver flexcop_pci_driver = {
-       .name = "Technisat/B2C2 FlexCop II/IIb/III PCI",
+       .name     = "b2c2_flexcop_pci",
        .id_table = flexcop_pci_tbl,
-       .probe = flexcop_pci_probe,
-       .remove = flexcop_pci_remove,
+       .probe    = flexcop_pci_probe,
+       .remove   = flexcop_pci_remove,
 };
 
 static int __init flexcop_pci_module_init(void)
index 75b50f21afe65eab15d11404d5f6bd0aca389dfd..4ae1eb5bfe98002a7826ac4f5ad0676a6e190474 100644 (file)
@@ -36,555 +36,21 @@ typedef enum {
 extern const char *flexcop_device_names[];
 
 /* FlexCop IBI Registers */
+#if defined(__LITTLE_ENDIAN)
+       #include "flexcop_ibi_value_le.h"
+#elif defined(__BIG_ENDIAN)
+       #include "flexcop_ibi_value_be.h"
+#else
+       #error no endian defined
+#endif
 
-/* flexcop_ibi_reg - a huge union representing the register structure */
-typedef union {
-       u32 raw;
-
-/* DMA 0x000 to 0x01c
- * DMA1 0x000 to 0x00c
- * DMA2 0x010 to 0x01c
- */
-       struct {
-               u32 dma_0start        : 1;   /* set: data will be delivered to dma1_address0 */
-        u32 dma_0No_update    : 1;   /* set: dma1_cur_address will be updated, unset: no update */
-        u32 dma_address0      :30;   /* physical/virtual host memory address0 DMA */
-       } dma_0x0;
-
-       struct {
-               u32 DMA_maxpackets    : 8;   /* (remapped) PCI DMA1 Packet Count Interrupt. This variable
-                                                                               is able to be read and written while bit(1) of register
-                                                                               0x00c (remap_enable) is set. This variable represents
-                                                                               the number of packets that will be transmitted to the PCI
-                                                                               host using PCI DMA1 before an interrupt to the PCI is
-                                                                               asserted. This functionality may be enabled using bit(20)
-                                                                               of register 0x208. N=0 disables the IRQ. */
-               u32 dma_addr_size     :24;   /* size of memory buffer in DWORDs (bytesize / 4) for DMA */
-       } dma_0x4_remap;
-
-       struct {
-               u32 dma1timer         : 7;   /* reading PCI DMA1 timer ... when remap_enable is 0 */
-               u32 unused            : 1;
-               u32 dma_addr_size     :24;
-       } dma_0x4_read;
-
-       struct {
-               u32 unused            : 1;
-               u32 dmatimer          : 7;   /* writing PCI DMA1 timer ... when remap_enable is 0 */
-               u32 dma_addr_size     :24;
-       } dma_0x4_write;
-
-       struct {
-               u32 unused            : 2;
-               u32 dma_cur_addr      :30;   /* current physical host memory address pointer for DMA */
-       } dma_0x8;
-
-       struct {
-               u32 dma_1start        : 1;   /* set: data will be delivered to dma_address1, when dma_address0 is full */
-               u32 remap_enable      : 1;   /* remap enable for 0x0x4(7:0) */
-               u32 dma_address1      :30;   /* Physical/virtual address 1 on DMA */
-       } dma_0xc;
-
-/* Two-wire Serial Master and Clock 0x100-0x110 */
-       struct {
-//             u32 slave_transmitter : 1;   /* ???*/
-               u32 chipaddr          : 7;   /* two-line serial address of the target slave */
-               u32 reserved1         : 1;
-               u32 baseaddr          : 8;   /* address of the location of the read/write operation */
-               u32 data1_reg         : 8;   /* first byte in two-line serial read/write operation */
-               u32 working_start     : 1;  /* when doing a write operation this indicator is 0 when ready
-                                                                         * set to 1 when doing a write operation */
-               u32 twoWS_rw          : 1;   /* read/write indicator (1 = read, 0 write) */
-               u32 total_bytes       : 2;   /* number of data bytes in each two-line serial transaction (0 = 1 byte, 11 = 4byte)*/
-               u32 twoWS_port_reg    : 2;   /* port selection: 01 - Front End/Demod, 10 - EEPROM, 11 - Tuner */
-               u32 no_base_addr_ack_error : 1;   /* writing: write-req: frame is produced w/o baseaddr, read-req: read-cycles w/o
-                                                                         * preceding address assignment write frame
-                                                                         * ACK_ERROR = 1 when no ACK from slave in the last transaction */
-               u32 st_done           : 1;   /* indicator for transaction is done */
-       } tw_sm_c_100;
-
-       struct {
-               u32 data2_reg         : 8;   /* 2nd data byte */
-               u32 data3_reg         : 8;   /* 3rd data byte */
-               u32 data4_reg         : 8;   /* 4th data byte */
-               u32 exlicit_stops     : 1;   /* when set, transactions are produced w/o trailing STOP flag, then send isolated STOP flags */
-               u32 force_stop        : 1;   /* isolated stop flag */
-               u32 unused            : 6;
-       } tw_sm_c_104;
-
-/* Clock. The register allows the FCIII to convert an incoming Master clock
- * (MCLK) signal into a lower frequency clock through the use of a LowCounter
- * (TLO) and a High- Counter (THI). The time counts for THI and TLO are
- * measured in MCLK; each count represents 4 MCLK input clock cycles.
- *
- * The default output for port #1 is set for Front End Demod communication. (0x108)
- * The default output for port #2 is set for EEPROM communication. (0x10c)
- * The default output for port #3 is set for Tuner communication. (0x110)
- */
-       struct {
-               u32 thi1              : 6;   /* Thi for port #1 (def: 100110b; 38) */
-               u32 reserved1         : 2;
-               u32 tlo1              : 5;   /* Tlo for port #1 (def: 11100b; 28) */
-               u32 reserved2         :19;
-       } tw_sm_c_108;
-
-       struct {
-               u32 thi1              : 6;   /* Thi for port #2 (def: 111001b; 57) */
-               u32 reserved1         : 2;
-               u32 tlo1              : 5;   /* Tlo for port #2 (def: 11100b; 28) */
-               u32 reserved2         :19;
-       } tw_sm_c_10c;
-
-       struct {
-               u32 thi1              : 6;   /* Thi for port #3 (def: 111001b; 57) */
-               u32 reserved1         : 2;
-               u32 tlo1              : 5;   /* Tlo for port #3 (def: 11100b; 28) */
-               u32 reserved2         :19;
-       } tw_sm_c_110;
-
-/* LNB Switch Frequency 0x200
- * Clock that creates the LNB switch tone. The default is set to have a fixed
- * low output (not oscillating) to the LNB_CTL line.
- */
-       struct {
-               u32 LNB_CTLHighCount_sig :15; /* It is the number of pre-scaled clock cycles that will be low. */
-               u32 LNB_CTLLowCount_sig  :15; /* For example, to obtain a 22KHz output given a 45 Mhz Master
-                                                                               Clock signal (MCLK), set PreScalar=01 and LowCounter value to 0x1ff. */
-               u32 LNB_CTLPrescaler_sig : 2; /* pre-scaler divides MCLK: 00 (no division), 01 by 2, 10 by 4, 11 by 12 */
-       } lnb_switch_freq_200;
-
-/* ACPI, Peripheral Reset, LNB Polarity
- * ACPI power conservation mode, LNB polarity selection (low or high voltage),
- * and peripheral reset.
- */
-       struct {
-               u32 ACPI1_sig         : 1;   /* turn of the power of tuner and LNB, not implemented in FCIII */
-               u32 ACPI3_sig         : 1;   /* turn of power of the complete satelite receiver board (except FCIII) */
-               u32 LNB_L_H_sig       : 1;   /* low or high voltage for LNB. (0 = low, 1 = high) */
-               u32 Per_reset_sig     : 1;   /* misc. init reset (default: 1), to reset set to low and back to high */
-               u32 reserved          :20;
-               u32 Rev_N_sig_revision_hi : 4;/* 0xc in case of FCIII */
-               u32 Rev_N_sig_reserved1 : 2;
-               u32 Rev_N_sig_caps    : 1;   /* if 1, FCIII has 32 PID- and MAC-filters and is capable of IP multicast */
-               u32 Rev_N_sig_reserved2 : 1;
-       } misc_204;
-
-/* Control and Status 0x208 to 0x21c */
-/* Gross enable and disable control */
-       struct {
-               u32 Stream1_filter_sig : 1;  /* Stream1 PID filtering */
-               u32 Stream2_filter_sig : 1;  /* Stream2 PID filtering */
-               u32 PCR_filter_sig    : 1;   /* PCR PID filter */
-               u32 PMT_filter_sig    : 1;   /* PMT PID filter */
-
-               u32 EMM_filter_sig    : 1;   /* EMM PID filter */
-               u32 ECM_filter_sig    : 1;   /* ECM PID filter */
-               u32 Null_filter_sig   : 1;   /* Filters null packets, PID=0x1fff. */
-               u32 Mask_filter_sig   : 1;   /* mask PID filter */
-
-               u32 WAN_Enable_sig    : 1;   /* WAN output line through V8 memory space is activated. */
-               u32 WAN_CA_Enable_sig : 1;   /* not in FCIII */
-               u32 CA_Enable_sig     : 1;   /* not in FCIII */
-               u32 SMC_Enable_sig    : 1;   /* CI stream data (CAI) goes directly to the smart card intf (opposed IBI 0x600 or SC-cmd buf). */
-
-               u32 Per_CA_Enable_sig : 1;   /* not in FCIII */
-               u32 Multi2_Enable_sig : 1;   /* ? */
-               u32 MAC_filter_Mode_sig : 1; /* (MAC_filter_enable) Globally enables MAC filters for Net PID filteres. */
-               u32 Rcv_Data_sig      : 1;   /* PID filtering module enable. When this bit is a one, the PID filter will
-                                                                               examine and process packets according to all other (individual) PID
-                                                                               filtering controls. If it a zero, no packet processing of any kind will
-                                                                               take place. All data from the tuner will be thrown away. */
-
-               u32 DMA1_IRQ_Enable_sig : 1; /* When set, a DWORD counter is enabled on PCI DMA1 that asserts the PCI
-                                                                         * interrupt after the specified count for filling the buffer. */
-               u32 DMA1_Timer_Enable_sig : 1; /* When set, a timer is enabled on PCI DMA1 that asserts the PCI interrupt
-                                                                                       after a specified amount of time. */
-               u32 DMA2_IRQ_Enable_sig : 1;   /* same as DMA1_IRQ_Enable_sig but for DMA2 */
-               u32 DMA2_Timer_Enable_sig : 1;   /* same as DMA1_Timer_Enable_sig but for DMA2 */
-
-               u32 DMA1_Size_IRQ_Enable_sig : 1; /* When set, a packet count detector is enabled on PCI DMA1 that asserts the PCI interrupt. */
-               u32 DMA2_Size_IRQ_Enable_sig : 1; /* When set, a packet count detector is enabled on PCI DMA2 that asserts the PCI interrupt. */
-               u32 Mailbox_from_V8_Enable_sig: 1; /* When set, writes to the mailbox register produce an interrupt to the
-                                                                                       PCI host to indicate that mailbox data is available. */
-
-               u32 unused            : 9;
-       } ctrl_208;
-
-/* General status. When a PCI interrupt occurs, this register is read to
- * discover the reason for the interrupt.
- */
-       struct {
-               u32 DMA1_IRQ_Status   : 1;   /* When set(1) the DMA1 counter had generated an IRQ. Read Only. */
-               u32 DMA1_Timer_Status : 1;   /* When set(1) the DMA1 timer had generated an IRQ. Read Only. */
-               u32 DMA2_IRQ_Status   : 1;   /* When set(1) the DMA2 counter had generated an IRQ. Read Only. */
-               u32 DMA2_Timer_Status : 1;   /* When set(1) the DMA2 timer had generated an IRQ. Read Only. */
-               u32 DMA1_Size_IRQ_Status : 1; /* (Read only). This register is read after an interrupt to */
-               u32 DMA2_Size_IRQ_Status : 1; /* find out why we had an IRQ. Reading this register will clear this bit. Packet count*/
-               u32 Mailbox_from_V8_Status_sig: 1; /* Same as above. Reading this register will clear this bit. */
-               u32 Data_receiver_error : 1; /* 1 indicate an error in the receiver Front End (Tuner module) */
-               u32 Continuity_error_flag : 1;   /* 1 indicates a continuity error in the TS stream. */
-               u32 LLC_SNAP_FLAG_set : 1;   /* 1 indicates that the LCC_SNAP_FLAG was set. */
-               u32 Transport_Error   : 1;   /*  When set indicates that an unexpected packet was received. */
-               u32 reserved          :21;
-       } irq_20c;
-
-
-/* Software reset register */
-       struct {
-               u32 reset_blocks      : 8;   /* Enabled when Block_reset_enable = 0xB2 and 0x208 bits 15:8 = 0x00.
-                                                                               Each bit location represents a 0x100 block of registers. Writing
-                                                                               a one in a bit location resets that block of registers and the logic
-                                                                               that it controls. */
-               u32 Block_reset_enable : 8;  /* This variable is set to 0xB2 when the register is written. */
-               u32 Special_controls  :16;   /* Asserts Reset_V8 => 0xC258; Turns on pci encryption => 0xC25A;
-                                                                               Turns off pci encryption => 0xC259 Note: pci_encryption default
-                                                                               at power-up is ON. */
-       } sw_reset_210;
-
-       struct {
-               u32 vuart_oe_sig      : 1;   /* When clear, the V8 processor has sole control of the serial UART
-                                                                               (RS-232 Smart Card interface). When set, the IBI interface
-                                                                               defined by register 0x600 controls the serial UART. */
-               u32 v2WS_oe_sig       : 1;   /* When clear, the V8 processor has direct control of the Two-line
-                                                                               Serial Master EEPROM target. When set, the Two-line Serial Master
-                                                                               EEPROM target interface is controlled by IBI register 0x100. */
-               u32 halt_V8_sig       : 1;   /* When set, contiguous wait states are applied to the V8-space
-                                                                               bus masters. Once this signal is cleared, normal V8-space
-                                                                               operations resume. */
-               u32 section_pkg_enable_sig: 1; /* When set, this signal enables the front end translation circuitry
-                                                                                 to process section packed transport streams. */
-               u32 s2p_sel_sig       : 1;   /* Serial to parallel conversion. When set, polarized transport data
-                                                                               within the FlexCop3 front end circuitry is converted from a serial
-                                                                               stream into parallel data before downstream processing otherwise
-                                                                               interprets the data. */
-               u32 unused1           : 3;
-               u32 polarity_PS_CLK_sig: 1;  /* This signal is used to invert the input polarity of the tranport
-                                                                               stream CLOCK signal before any processing occurs on the transport
-                                                                               stream within FlexCop3. */
-               u32 polarity_PS_VALID_sig: 1; /* This signal is used to invert the input polarity of the tranport
-                                                                               stream VALID signal before any processing occurs on the transport
-                                                                               stream within FlexCop3. */
-               u32 polarity_PS_SYNC_sig: 1; /* This signal is used to invert the input polarity of the tranport
-                                                                               stream SYNC signal before any processing occurs on the transport
-                                                                               stream within FlexCop3. */
-               u32 polarity_PS_ERR_sig: 1;  /* This signal is used to invert the input polarity of the tranport
-                                                                               stream ERROR signal before any processing occurs on the transport
-                                                                               stream within FlexCop3. */
-               u32 unused2           :20;
-       } misc_214;
-
-/* Mailbox from V8 to host */
-       struct {
-               u32 Mailbox_from_V8   :32;   /* When this register is written by either the V8 processor or by an
-                                                                               end host, an interrupt is generated to the PCI host to indicate
-                                                                               that mailbox data is available. Reading register 20c will clear
-                                                                               the IRQ. */
-       } mbox_v8_to_host_218;
-
-/* Mailbox from host to v8 Mailbox_to_V8
- * Mailbox_to_V8 mailbox storage register
- * used to send messages from PCI to V8. Writing to this register will send an
- * IRQ to the V8. Then it can read the data from here. Reading this register
- * will clear the IRQ. If the V8 is halted and bit 31 of this register is set,
- * then this register is used instead as a direct interface to access the
- * V8space memory.
- */
-       struct {
-               u32 sysramaccess_data : 8;   /* Data byte written or read from the specified address in V8 SysRAM. */
-               u32 sysramaccess_addr :15;   /* 15 bit address used to access V8 Sys-RAM. */
-               u32 unused            : 7;
-               u32 sysramaccess_write: 1;   /* Write flag used to latch data into the V8 SysRAM. */
-               u32 sysramaccess_busmuster: 1; /* Setting this bit when the V8 is halted at 0x214 Bit(2) allows
-                                                                                 this IBI register interface to directly drive the V8-space memory. */
-       } mbox_host_to_v8_21c;
-
-
-/* PIDs, Translation Bit, SMC Filter Select 0x300 to 0x31c */
-       struct {
-               u32 Stream1_PID       :13;   /* Primary use is receiving Net data, so these 13 bits normally
-                                                                               hold the PID value for the desired network stream. */
-               u32 Stream1_trans     : 1;   /* When set, Net translation will take place for Net data ferried in TS packets. */
-               u32 MAC_Multicast_filter : 1;   /* When clear, multicast MAC filtering is not allowed for Stream1 and PID_n filters. */
-               u32 debug_flag_pid_saved : 1;
-               u32 Stream2_PID       :13;   /* 13 bits for Stream 2 PID filter value. General use. */
-               u32 Stream2_trans     : 1;   /* When set Tables/CAI translation will take place for the data ferried in
-                                                                               Stream2_PID TS packets. */
-               u32 debug_flag_write_status00 : 1;
-               u32 debug_fifo_problem : 1;
-       } pid_filter_300;
-
-       struct {
-               u32 PCR_PID           :13;   /* PCR stream PID filter value. Primary use is Program Clock Reference stream filtering. */
-               u32 PCR_trans         : 1;   /* When set, Tables/CAI translation will take place for these packets. */
-               u32 debug_overrun3    : 1;
-               u32 debug_overrun2    : 1;
-               u32 PMT_PID           :13;   /* stream PID filter value. Primary use is Program Management Table segment filtering. */
-               u32 PMT_trans         : 1;   /* When set, Tables/CAI translation will take place for these packets. */
-               u32 reserved          : 2;
-       } pid_filter_304;
-
-       struct {
-               u32 EMM_PID           :13;   /* EMM PID filter value. Primary use is Entitlement Management Messaging for
-                                                                               conditional access-related data. */
-               u32 EMM_trans         : 1;   /* When set, Tables/CAI translation will take place for these packets. */
-               u32 EMM_filter_4      : 1;   /* When set will pass only EMM data possessing the same ID code as the
-                                                                               first four bytes (32 bits) of the end-user s 6-byte Smart Card ID number Select */
-               u32 EMM_filter_6      : 1;   /* When set will pass only EMM data possessing the same 6-byte code as the end-users
-                                                                               complete 6-byte Smart Card ID number. */
-               u32 ECM_PID           :13;   /* ECM PID filter value. Primary use is Entitlement Control Messaging for conditional
-                                                                               access-related data. */
-               u32 ECM_trans         : 1;   /* When set, Tables/CAI translation will take place for these packets. */
-               u32 reserved          : 2;
-       } pid_filter_308;
-
-       struct {
-               u32 Group_PID     :13;   /* PID value for group filtering. */
-               u32 Group_trans   : 1;   /* When set, Tables/CAI translation will take place for these packets. */
-               u32 unused1       : 2;
-               u32 Group_mask    :13;   /* Mask value used in logical "and" equation that defines group filtering */
-               u32 unused2       : 3;
-       } pid_filter_30c_ext_ind_0_7;
-
-       struct {
-               u32 net_master_read :17;
-               u32 unused        :15;
-       } pid_filter_30c_ext_ind_1;
-
-       struct {
-               u32 net_master_write :17;
-               u32 unused        :15;
-       } pid_filter_30c_ext_ind_2;
-
-       struct {
-               u32 next_net_master_write :17;
-               u32 unused        :15;
-       } pid_filter_30c_ext_ind_3;
-
-       struct {
-               u32 unused1       : 1;
-               u32 state_write   :10;
-               u32 reserved1     : 6;   /* default: 000100 */
-               u32 stack_read    :10;
-               u32 reserved2     : 5;   /* default: 00100 */
-       } pid_filter_30c_ext_ind_4;
-
-       struct {
-               u32 stack_cnt     :10;
-               u32 unused        :22;
-       } pid_filter_30c_ext_ind_5;
-
-       struct {
-               u32 pid_fsm_save_reg0 : 2;
-               u32 pid_fsm_save_reg1 : 2;
-               u32 pid_fsm_save_reg2 : 2;
-               u32 pid_fsm_save_reg3 : 2;
-               u32 pid_fsm_save_reg4 : 2;
-               u32 pid_fsm_save_reg300 : 2;
-               u32 write_status1 : 2;
-               u32 write_status4 : 2;
-               u32 data_size_reg :12;
-               u32 unused        : 4;
-       } pid_filter_30c_ext_ind_6;
-
-       struct {
-               u32 index_reg         : 5;   /* (Index pointer) Points at an internal PIDn register. A binary code
-                                                                               representing one of 32 internal PIDn registers as well as its
-                                                                               corresponding internal MAC_lown register. */
-               u32 extra_index_reg   : 3;   /* This vector is used to select between sets of debug signals routed to register 0x30c. */
-               u32 AB_select         : 1;   /* Used in conjunction with 0x31c. read/write to the MAC_highA or MAC_highB register
-                                                                               0=MAC_highB register, 1=MAC_highA */
-               u32 pass_alltables    : 1;   /* 1=Net packets are not filtered against the Network Table ID found in register 0x400.
-                                                                               All types of networks (DVB, ATSC, ISDB) are passed. */
-               u32 unused            :22;
-       } index_reg_310;
-
-       struct {
-               u32 PID               :13;   /* PID value */
-               u32 PID_trans         : 1;   /* translation will take place for packets filtered */
-               u32 PID_enable_bit    : 1;   /* When set this PID filter is enabled */
-               u32 reserved          :17;
-       } pid_n_reg_314;
-
-       struct {
-               u32 A4_byte           : 8;
-               u32 A5_byte           : 8;
-               u32 A6_byte           : 8;
-               u32 Enable_bit        : 1;   /* enabled (1) or disabled (1) */
-               u32 HighAB_bit        : 1;   /* use MAC_highA (1) or MAC_highB (0) as MSB */
-               u32 reserved          : 6;
-       } mac_low_reg_318;
-
-       struct {
-               u32 A1_byte           : 8;
-               u32 A2_byte           : 8;
-               u32 A3_byte           : 8;
-               u32 reserved          : 8;
-       } mac_high_reg_31c;
-
-/* Table, SMCID,MACDestination Filters 0x400 to 0x41c */
-       struct {
-               u32 reserved          :16;
 #define fc_data_Tag_ID_DVB  0x3e
 #define fc_data_Tag_ID_ATSC 0x3f
 #define fc_data_Tag_ID_IDSB 0x8b
-               u32 data_Tag_ID       :16;
-       } data_tag_400;
-
-       struct {
-               u32 Card_IDbyte6      : 8;
-               u32 Card_IDbyte5      : 8;
-               u32 Card_IDbyte4      : 8;
-               u32 Card_IDbyte3      : 8;
-       } card_id_408;
-
-       struct {
-               u32 Card_IDbyte2      : 8;
-               u32 Card_IDbyte1      : 8;
-       } card_id_40c;
-
-       /* holding the unique mac address of the receiver which houses the FlexCopIII */
-       struct {
-               u32 MAC1              : 8;
-               u32 MAC2              : 8;
-               u32 MAC3              : 8;
-               u32 MAC6              : 8;
-       } mac_address_418;
-
-       struct {
-               u32 MAC7              : 8;
-               u32 MAC8              : 8;
-               u32 reserved          : 16;
-       } mac_address_41c;
-
-       struct {
-               u32 transmitter_data_byte : 8;
-               u32 ReceiveDataReady  : 1;
-               u32 ReceiveByteFrameError: 1;
-               u32 txbuffempty       : 1;
-               u32 reserved          :21;
-       } ci_600;
-
-       struct {
-               u32 pi_d              : 8;
-               u32 pi_ha             :20;
-               u32 pi_rw             : 1;
-               u32 pi_component_reg  : 3;
-       } pi_604;
-
-       struct {
-               u32 serialReset       : 1;
-               u32 oncecycle_read    : 1;
-               u32 Timer_Read_req    : 1;
-               u32 Timer_Load_req    : 1;
-               u32 timer_data        : 7;
-               u32 unused            : 1; /* ??? not mentioned in data book */
-               u32 Timer_addr        : 5;
-               u32 reserved          : 3;
-               u32 pcmcia_a_mod_pwr_n : 1;
-               u32 pcmcia_b_mod_pwr_n : 1;
-               u32 config_Done_stat  : 1;
-               u32 config_Init_stat  : 1;
-               u32 config_Prog_n     : 1;
-               u32 config_wr_n       : 1;
-               u32 config_cs_n       : 1;
-               u32 config_cclk       : 1;
-               u32 pi_CiMax_IRQ_n    : 1;
-               u32 pi_timeout_status : 1;
-               u32 pi_wait_n         : 1;
-               u32 pi_busy_n         : 1;
-       } pi_608;
 
-       struct {
-               u32 PID               :13;
-               u32 key_enable        : 1;
 #define fc_key_code_default 0x1
 #define fc_key_code_even    0x2
 #define fc_key_code_odd     0x3
-               u32 key_code          : 2;
-               u32 key_array_col     : 3;
-               u32 key_array_row     : 5;
-               u32 dvb_en            : 1; /* 0=TS bypasses the Descrambler */
-               u32 rw_flag           : 1;
-               u32 reserved          : 6;
-       } dvb_reg_60c;
-
-/* SRAM and Output Destination 0x700 to 0x714 */
-       struct {
-               u32 sram_addr         :15;
-               u32 sram_rw           : 1;   /* 0=write, 1=read */
-               u32 sram_data         : 8;
-               u32 sc_xfer_bit       : 1;
-               u32 reserved1         : 3;
-               u32 oe_pin_reg        : 1;
-               u32 ce_pin_reg        : 1;
-               u32 reserved2         : 1;
-               u32 start_sram_ibi    : 1;
-       } sram_ctrl_reg_700;
-
-       struct {
-               u32 net_addr_read     :16;
-               u32 net_addr_write    :16;
-       } net_buf_reg_704;
-
-       struct {
-               u32 cai_read          :11;
-               u32 reserved1         : 5;
-               u32 cai_write         :11;
-               u32 reserved2         : 6;
-               u32 cai_cnt           : 4;
-       } cai_buf_reg_708;
-
-       struct {
-               u32 cao_read          :11;
-               u32 reserved1         : 5;
-               u32 cap_write         :11;
-               u32 reserved2         : 6;
-               u32 cao_cnt           : 4;
-       } cao_buf_reg_70c;
-
-       struct {
-               u32 media_read        :11;
-               u32 reserved1         : 5;
-               u32 media_write       :11;
-               u32 reserved2         : 6;
-               u32 media_cnt         : 4;
-       } media_buf_reg_710;
-
-       struct {
-               u32 NET_Dest          : 2;
-               u32 CAI_Dest          : 2;
-               u32 CAO_Dest          : 2;
-               u32 MEDIA_Dest        : 2;
-               u32 net_ovflow_error  : 1;
-               u32 media_ovflow_error : 1;
-               u32 cai_ovflow_error  : 1;
-               u32 cao_ovflow_error  : 1;
-               u32 ctrl_usb_wan      : 1;
-               u32 ctrl_sramdma      : 1;
-               u32 ctrl_maximumfill  : 1;
-               u32 reserved          :17;
-       } sram_dest_reg_714;
-
-       struct {
-               u32 net_cnt           :12;
-               u32 reserved1         : 4;
-               u32 net_addr_read     : 1;
-               u32 reserved2         : 3;
-               u32 net_addr_write    : 1;
-               u32 reserved3         :11;
-       } net_buf_reg_718;
-
-       struct {
-               u32 wan_speed_sig     : 2;
-               u32 reserved1         : 6;
-               u32 wan_wait_state    : 8;
-               u32 sram_chip         : 2;
-               u32 sram_memmap       : 2;
-               u32 reserved2         : 4;
-               u32 wan_pkt_frame     : 4;
-               u32 reserved3         : 4;
-       } wan_ctrl_reg_71c;
-} flexcop_ibi_value;
 
 extern flexcop_ibi_value ibi_zero;
 
index 0113449abd15107479b1722308309900f97bb0b5..0a78ba3737a58d85a64a7d902b30e9dfeeae4579 100644 (file)
@@ -545,7 +545,7 @@ static struct usb_device_id flexcop_usb_table [] = {
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver flexcop_usb_driver = {
        .owner          = THIS_MODULE,
-       .name           = "Technisat/B2C2 FlexCop II/IIb/III USB",
+       .name           = "b2c2_flexcop_usb",
        .probe          = flexcop_usb_probe,
        .disconnect = flexcop_usb_disconnect,
        .id_table       = flexcop_usb_table,
index 8b5d14dd36e37deb551dc1341e89143106e902c0..12873d435406cb67023f8d43ac8c65859919cec0 100644 (file)
@@ -46,7 +46,7 @@
 
 int b2c2_flexcop_debug;
 module_param_named(debug, b2c2_flexcop_debug,  int, 0644);
-MODULE_PARM_DESC(debug, "set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram (|-able))." DEBSTATUS);
+MODULE_PARM_DESC(debug, "set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram,32=reg (|-able))." DEBSTATUS);
 #undef DEBSTATUS
 
 /* global zero for ibi values */
@@ -173,9 +173,20 @@ static void flexcop_reset(struct flexcop_device *fc)
        fc->write_ibi_reg(fc,ctrl_208,ibi_zero);
 
        v210.raw = 0;
-       v210.sw_reset_210.reset_blocks = 0xff;
+       v210.sw_reset_210.reset_block_000 = 1;
+       v210.sw_reset_210.reset_block_100 = 1;
+       v210.sw_reset_210.reset_block_200 = 1;
+       v210.sw_reset_210.reset_block_300 = 1;
+       v210.sw_reset_210.reset_block_400 = 1;
+       v210.sw_reset_210.reset_block_500 = 1;
+       v210.sw_reset_210.reset_block_600 = 1;
+       v210.sw_reset_210.reset_block_700 = 1;
        v210.sw_reset_210.Block_reset_enable = 0xb2;
+
+       v210.sw_reset_210.Special_controls = 0xc259;
+
        fc->write_ibi_reg(fc,sw_reset_210,v210);
+       msleep(1);
 
 /* reset the periphical devices */
 
@@ -186,6 +197,25 @@ static void flexcop_reset(struct flexcop_device *fc)
        fc->write_ibi_reg(fc,misc_204,v204);
 }
 
+void flexcop_reset_block_300(struct flexcop_device *fc)
+{
+       flexcop_ibi_value v208_save = fc->read_ibi_reg(fc,ctrl_208),
+                                         v210 = fc->read_ibi_reg(fc,sw_reset_210);
+
+       deb_rdump("208: %08x, 210: %08x\n",v208_save.raw,v210.raw);
+
+       fc->write_ibi_reg(fc,ctrl_208,ibi_zero);
+
+       v210.sw_reset_210.reset_block_300 = 1;
+       v210.sw_reset_210.Block_reset_enable = 0xb2;
+
+       fc->write_ibi_reg(fc,sw_reset_210,v210);
+       msleep(1);
+
+       fc->write_ibi_reg(fc,ctrl_208,v208_save);
+}
+EXPORT_SYMBOL(flexcop_reset_block_300);
+
 struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len)
 {
        void *bus;
index caa343a97bdc578fffaace845285cbefcabd2843..0cebe1d92e0b6fa642efa16882ed99ee83f6b6a7 100644 (file)
@@ -26,5 +26,6 @@ extern int b2c2_flexcop_debug;
 #define deb_i2c(args...)   dprintk(0x04,args)
 #define deb_ts(args...)    dprintk(0x08,args)
 #define deb_sram(args...)  dprintk(0x10,args)
+#define deb_rdump(args...)  dprintk(0x20,args)
 
 #endif
diff --git a/drivers/media/dvb/b2c2/flexcop_ibi_value_be.h b/drivers/media/dvb/b2c2/flexcop_ibi_value_be.h
new file mode 100644 (file)
index 0000000..ed9a675
--- /dev/null
@@ -0,0 +1,458 @@
+/* This file is part of linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * register descriptions
+ *
+ * see flexcop.c for copyright information.
+ */
+
+/* This file is automatically generated, do not edit things here. */
+#ifndef __FLEXCOP_IBI_VALUE_INCLUDED__
+#define __FLEXCOP_IBI_VALUE_INCLUDED__
+
+typedef union {
+       u32 raw;
+
+       struct {
+               u32 dma_address0                   :30;
+               u32 dma_0No_update                 : 1;
+               u32 dma_0start                     : 1;
+       } dma_0x0;
+
+       struct {
+               u32 dma_addr_size                  :24;
+               u32 DMA_maxpackets                 : 8;
+       } dma_0x4_remap;
+
+       struct {
+               u32 dma_addr_size                  :24;
+               u32 unused                         : 1;
+               u32 dma1timer                      : 7;
+       } dma_0x4_read;
+
+       struct {
+               u32 dma_addr_size                  :24;
+               u32 dmatimer                       : 7;
+               u32 unused                         : 1;
+       } dma_0x4_write;
+
+       struct {
+               u32 dma_cur_addr                   :30;
+               u32 unused                         : 2;
+       } dma_0x8;
+
+       struct {
+               u32 dma_address1                   :30;
+               u32 remap_enable                   : 1;
+               u32 dma_1start                     : 1;
+       } dma_0xc;
+
+       struct {
+               u32 st_done                        : 1;
+               u32 no_base_addr_ack_error         : 1;
+               u32 twoWS_port_reg                 : 2;
+               u32 total_bytes                    : 2;
+               u32 twoWS_rw                       : 1;
+               u32 working_start                  : 1;
+               u32 data1_reg                      : 8;
+               u32 baseaddr                       : 8;
+               u32 reserved1                      : 1;
+               u32 chipaddr                       : 7;
+       } tw_sm_c_100;
+
+       struct {
+               u32 unused                         : 6;
+               u32 force_stop                     : 1;
+               u32 exlicit_stops                  : 1;
+               u32 data4_reg                      : 8;
+               u32 data3_reg                      : 8;
+               u32 data2_reg                      : 8;
+       } tw_sm_c_104;
+
+       struct {
+               u32 reserved2                      :19;
+               u32 tlo1                           : 5;
+               u32 reserved1                      : 2;
+               u32 thi1                           : 6;
+       } tw_sm_c_108;
+
+       struct {
+               u32 reserved2                      :19;
+               u32 tlo1                           : 5;
+               u32 reserved1                      : 2;
+               u32 thi1                           : 6;
+       } tw_sm_c_10c;
+
+       struct {
+               u32 reserved2                      :19;
+               u32 tlo1                           : 5;
+               u32 reserved1                      : 2;
+               u32 thi1                           : 6;
+       } tw_sm_c_110;
+
+       struct {
+               u32 LNB_CTLPrescaler_sig           : 2;
+               u32 LNB_CTLLowCount_sig            :15;
+               u32 LNB_CTLHighCount_sig           :15;
+       } lnb_switch_freq_200;
+
+       struct {
+               u32 Rev_N_sig_reserved2            : 1;
+               u32 Rev_N_sig_caps                 : 1;
+               u32 Rev_N_sig_reserved1            : 2;
+               u32 Rev_N_sig_revision_hi          : 4;
+               u32 reserved                       :20;
+               u32 Per_reset_sig                  : 1;
+               u32 LNB_L_H_sig                    : 1;
+               u32 ACPI3_sig                      : 1;
+               u32 ACPI1_sig                      : 1;
+       } misc_204;
+
+       struct {
+               u32 unused                         : 9;
+               u32 Mailbox_from_V8_Enable_sig     : 1;
+               u32 DMA2_Size_IRQ_Enable_sig       : 1;
+               u32 DMA1_Size_IRQ_Enable_sig       : 1;
+               u32 DMA2_Timer_Enable_sig          : 1;
+               u32 DMA2_IRQ_Enable_sig            : 1;
+               u32 DMA1_Timer_Enable_sig          : 1;
+               u32 DMA1_IRQ_Enable_sig            : 1;
+               u32 Rcv_Data_sig                   : 1;
+               u32 MAC_filter_Mode_sig            : 1;
+               u32 Multi2_Enable_sig              : 1;
+               u32 Per_CA_Enable_sig              : 1;
+               u32 SMC_Enable_sig                 : 1;
+               u32 CA_Enable_sig                  : 1;
+               u32 WAN_CA_Enable_sig              : 1;
+               u32 WAN_Enable_sig                 : 1;
+               u32 Mask_filter_sig                : 1;
+               u32 Null_filter_sig                : 1;
+               u32 ECM_filter_sig                 : 1;
+               u32 EMM_filter_sig                 : 1;
+               u32 PMT_filter_sig                 : 1;
+               u32 PCR_filter_sig                 : 1;
+               u32 Stream2_filter_sig             : 1;
+               u32 Stream1_filter_sig             : 1;
+       } ctrl_208;
+
+       struct {
+               u32 reserved                       :21;
+               u32 Transport_Error                : 1;
+               u32 LLC_SNAP_FLAG_set              : 1;
+               u32 Continuity_error_flag          : 1;
+               u32 Data_receiver_error            : 1;
+               u32 Mailbox_from_V8_Status_sig     : 1;
+               u32 DMA2_Size_IRQ_Status           : 1;
+               u32 DMA1_Size_IRQ_Status           : 1;
+               u32 DMA2_Timer_Status              : 1;
+               u32 DMA2_IRQ_Status                : 1;
+               u32 DMA1_Timer_Status              : 1;
+               u32 DMA1_IRQ_Status                : 1;
+       } irq_20c;
+
+       struct {
+               u32 Special_controls               :16;
+               u32 Block_reset_enable             : 8;
+               u32 reset_block_700                : 1;
+               u32 reset_block_600                : 1;
+               u32 reset_block_500                : 1;
+               u32 reset_block_400                : 1;
+               u32 reset_block_300                : 1;
+               u32 reset_block_200                : 1;
+               u32 reset_block_100                : 1;
+               u32 reset_block_000                : 1;
+       } sw_reset_210;
+
+       struct {
+               u32 unused2                        :20;
+               u32 polarity_PS_ERR_sig            : 1;
+               u32 polarity_PS_SYNC_sig           : 1;
+               u32 polarity_PS_VALID_sig          : 1;
+               u32 polarity_PS_CLK_sig            : 1;
+               u32 unused1                        : 3;
+               u32 s2p_sel_sig                    : 1;
+               u32 section_pkg_enable_sig         : 1;
+               u32 halt_V8_sig                    : 1;
+               u32 v2WS_oe_sig                    : 1;
+               u32 vuart_oe_sig                   : 1;
+       } misc_214;
+
+       struct {
+               u32 Mailbox_from_V8                :32;
+       } mbox_v8_to_host_218;
+
+       struct {
+               u32 sysramaccess_busmuster         : 1;
+               u32 sysramaccess_write             : 1;
+               u32 unused                         : 7;
+               u32 sysramaccess_addr              :15;
+               u32 sysramaccess_data              : 8;
+       } mbox_host_to_v8_21c;
+
+       struct {
+               u32 debug_fifo_problem             : 1;
+               u32 debug_flag_write_status00      : 1;
+               u32 Stream2_trans                  : 1;
+               u32 Stream2_PID                    :13;
+               u32 debug_flag_pid_saved           : 1;
+               u32 MAC_Multicast_filter           : 1;
+               u32 Stream1_trans                  : 1;
+               u32 Stream1_PID                    :13;
+       } pid_filter_300;
+
+       struct {
+               u32 reserved                       : 2;
+               u32 PMT_trans                      : 1;
+               u32 PMT_PID                        :13;
+               u32 debug_overrun2                 : 1;
+               u32 debug_overrun3                 : 1;
+               u32 PCR_trans                      : 1;
+               u32 PCR_PID                        :13;
+       } pid_filter_304;
+
+       struct {
+               u32 reserved                       : 2;
+               u32 ECM_trans                      : 1;
+               u32 ECM_PID                        :13;
+               u32 EMM_filter_6                   : 1;
+               u32 EMM_filter_4                   : 1;
+               u32 EMM_trans                      : 1;
+               u32 EMM_PID                        :13;
+       } pid_filter_308;
+
+       struct {
+               u32 unused2                        : 3;
+               u32 Group_mask                     :13;
+               u32 unused1                        : 2;
+               u32 Group_trans                    : 1;
+               u32 Group_PID                      :13;
+       } pid_filter_30c_ext_ind_0_7;
+
+       struct {
+               u32 unused                         :15;
+               u32 net_master_read                :17;
+       } pid_filter_30c_ext_ind_1;
+
+       struct {
+               u32 unused                         :15;
+               u32 net_master_write               :17;
+       } pid_filter_30c_ext_ind_2;
+
+       struct {
+               u32 unused                         :15;
+               u32 next_net_master_write          :17;
+       } pid_filter_30c_ext_ind_3;
+
+       struct {
+               u32 reserved2                      : 5;
+               u32 stack_read                     :10;
+               u32 reserved1                      : 6;
+               u32 state_write                    :10;
+               u32 unused1                        : 1;
+       } pid_filter_30c_ext_ind_4;
+
+       struct {
+               u32 unused                         :22;
+               u32 stack_cnt                      :10;
+       } pid_filter_30c_ext_ind_5;
+
+       struct {
+               u32 unused                         : 4;
+               u32 data_size_reg                  :12;
+               u32 write_status4                  : 2;
+               u32 write_status1                  : 2;
+               u32 pid_fsm_save_reg300            : 2;
+               u32 pid_fsm_save_reg4              : 2;
+               u32 pid_fsm_save_reg3              : 2;
+               u32 pid_fsm_save_reg2              : 2;
+               u32 pid_fsm_save_reg1              : 2;
+               u32 pid_fsm_save_reg0              : 2;
+       } pid_filter_30c_ext_ind_6;
+
+       struct {
+               u32 unused                         :22;
+               u32 pass_alltables                 : 1;
+               u32 AB_select                      : 1;
+               u32 extra_index_reg                : 3;
+               u32 index_reg                      : 5;
+       } index_reg_310;
+
+       struct {
+               u32 reserved                       :17;
+               u32 PID_enable_bit                 : 1;
+               u32 PID_trans                      : 1;
+               u32 PID                            :13;
+       } pid_n_reg_314;
+
+       struct {
+               u32 reserved                       : 6;
+               u32 HighAB_bit                     : 1;
+               u32 Enable_bit                     : 1;
+               u32 A6_byte                        : 8;
+               u32 A5_byte                        : 8;
+               u32 A4_byte                        : 8;
+       } mac_low_reg_318;
+
+       struct {
+               u32 reserved                       : 8;
+               u32 A3_byte                        : 8;
+               u32 A2_byte                        : 8;
+               u32 A1_byte                        : 8;
+       } mac_high_reg_31c;
+
+       struct {
+               u32 data_Tag_ID                    :16;
+               u32 reserved                       :16;
+       } data_tag_400;
+
+       struct {
+               u32 Card_IDbyte3                   : 8;
+               u32 Card_IDbyte4                   : 8;
+               u32 Card_IDbyte5                   : 8;
+               u32 Card_IDbyte6                   : 8;
+       } card_id_408;
+
+       struct {
+               u32 Card_IDbyte1                   : 8;
+               u32 Card_IDbyte2                   : 8;
+       } card_id_40c;
+
+       struct {
+               u32 MAC6                           : 8;
+               u32 MAC3                           : 8;
+               u32 MAC2                           : 8;
+               u32 MAC1                           : 8;
+       } mac_address_418;
+
+       struct {
+               u32 reserved                       :16;
+               u32 MAC8                           : 8;
+               u32 MAC7                           : 8;
+       } mac_address_41c;
+
+       struct {
+               u32 reserved                       :21;
+               u32 txbuffempty                    : 1;
+               u32 ReceiveByteFrameError          : 1;
+               u32 ReceiveDataReady               : 1;
+               u32 transmitter_data_byte          : 8;
+       } ci_600;
+
+       struct {
+               u32 pi_component_reg               : 3;
+               u32 pi_rw                          : 1;
+               u32 pi_ha                          :20;
+               u32 pi_d                           : 8;
+       } pi_604;
+
+       struct {
+               u32 pi_busy_n                      : 1;
+               u32 pi_wait_n                      : 1;
+               u32 pi_timeout_status              : 1;
+               u32 pi_CiMax_IRQ_n                 : 1;
+               u32 config_cclk                    : 1;
+               u32 config_cs_n                    : 1;
+               u32 config_wr_n                    : 1;
+               u32 config_Prog_n                  : 1;
+               u32 config_Init_stat               : 1;
+               u32 config_Done_stat               : 1;
+               u32 pcmcia_b_mod_pwr_n             : 1;
+               u32 pcmcia_a_mod_pwr_n             : 1;
+               u32 reserved                       : 3;
+               u32 Timer_addr                     : 5;
+               u32 unused                         : 1;
+               u32 timer_data                     : 7;
+               u32 Timer_Load_req                 : 1;
+               u32 Timer_Read_req                 : 1;
+               u32 oncecycle_read                 : 1;
+               u32 serialReset                    : 1;
+       } pi_608;
+
+       struct {
+               u32 reserved                       : 6;
+               u32 rw_flag                        : 1;
+               u32 dvb_en                         : 1;
+               u32 key_array_row                  : 5;
+               u32 key_array_col                  : 3;
+               u32 key_code                       : 2;
+               u32 key_enable                     : 1;
+               u32 PID                            :13;
+       } dvb_reg_60c;
+
+       struct {
+               u32 start_sram_ibi                 : 1;
+               u32 reserved2                      : 1;
+               u32 ce_pin_reg                     : 1;
+               u32 oe_pin_reg                     : 1;
+               u32 reserved1                      : 3;
+               u32 sc_xfer_bit                    : 1;
+               u32 sram_data                      : 8;
+               u32 sram_rw                        : 1;
+               u32 sram_addr                      :15;
+       } sram_ctrl_reg_700;
+
+       struct {
+               u32 net_addr_write                 :16;
+               u32 net_addr_read                  :16;
+       } net_buf_reg_704;
+
+       struct {
+               u32 cai_cnt                        : 4;
+               u32 reserved2                      : 6;
+               u32 cai_write                      :11;
+               u32 reserved1                      : 5;
+               u32 cai_read                       :11;
+       } cai_buf_reg_708;
+
+       struct {
+               u32 cao_cnt                        : 4;
+               u32 reserved2                      : 6;
+               u32 cap_write                      :11;
+               u32 reserved1                      : 5;
+               u32 cao_read                       :11;
+       } cao_buf_reg_70c;
+
+       struct {
+               u32 media_cnt                      : 4;
+               u32 reserved2                      : 6;
+               u32 media_write                    :11;
+               u32 reserved1                      : 5;
+               u32 media_read                     :11;
+       } media_buf_reg_710;
+
+       struct {
+               u32 reserved                       :17;
+               u32 ctrl_maximumfill               : 1;
+               u32 ctrl_sramdma                   : 1;
+               u32 ctrl_usb_wan                   : 1;
+               u32 cao_ovflow_error               : 1;
+               u32 cai_ovflow_error               : 1;
+               u32 media_ovflow_error             : 1;
+               u32 net_ovflow_error               : 1;
+               u32 MEDIA_Dest                     : 2;
+               u32 CAO_Dest                       : 2;
+               u32 CAI_Dest                       : 2;
+               u32 NET_Dest                       : 2;
+       } sram_dest_reg_714;
+
+       struct {
+               u32 reserved3                      :11;
+               u32 net_addr_write                 : 1;
+               u32 reserved2                      : 3;
+               u32 net_addr_read                  : 1;
+               u32 reserved1                      : 4;
+               u32 net_cnt                        :12;
+       } net_buf_reg_718;
+
+       struct {
+               u32 reserved3                      : 4;
+               u32 wan_pkt_frame                  : 4;
+               u32 reserved2                      : 4;
+               u32 sram_memmap                    : 2;
+               u32 sram_chip                      : 2;
+               u32 wan_wait_state                 : 8;
+               u32 reserved1                      : 6;
+               u32 wan_speed_sig                  : 2;
+       } wan_ctrl_reg_71c;
+} flexcop_ibi_value;
+
+#endif
diff --git a/drivers/media/dvb/b2c2/flexcop_ibi_value_le.h b/drivers/media/dvb/b2c2/flexcop_ibi_value_le.h
new file mode 100644 (file)
index 0000000..49f2315
--- /dev/null
@@ -0,0 +1,458 @@
+/* This file is part of linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * register descriptions
+ *
+ * see flexcop.c for copyright information.
+ */
+
+/* This file is automatically generated, do not edit things here. */
+#ifndef __FLEXCOP_IBI_VALUE_INCLUDED__
+#define __FLEXCOP_IBI_VALUE_INCLUDED__
+
+typedef union {
+       u32 raw;
+
+       struct {
+               u32 dma_0start                     : 1;
+               u32 dma_0No_update                 : 1;
+               u32 dma_address0                   :30;
+       } dma_0x0;
+
+       struct {
+               u32 DMA_maxpackets                 : 8;
+               u32 dma_addr_size                  :24;
+       } dma_0x4_remap;
+
+       struct {
+               u32 dma1timer                      : 7;
+               u32 unused                         : 1;
+               u32 dma_addr_size                  :24;
+       } dma_0x4_read;
+
+       struct {
+               u32 unused                         : 1;
+               u32 dmatimer                       : 7;
+               u32 dma_addr_size                  :24;
+       } dma_0x4_write;
+
+       struct {
+               u32 unused                         : 2;
+               u32 dma_cur_addr                   :30;
+       } dma_0x8;
+
+       struct {
+               u32 dma_1start                     : 1;
+               u32 remap_enable                   : 1;
+               u32 dma_address1                   :30;
+       } dma_0xc;
+
+       struct {
+               u32 chipaddr                       : 7;
+               u32 reserved1                      : 1;
+               u32 baseaddr                       : 8;
+               u32 data1_reg                      : 8;
+               u32 working_start                  : 1;
+               u32 twoWS_rw                       : 1;
+               u32 total_bytes                    : 2;
+               u32 twoWS_port_reg                 : 2;
+               u32 no_base_addr_ack_error         : 1;
+               u32 st_done                        : 1;
+       } tw_sm_c_100;
+
+       struct {
+               u32 data2_reg                      : 8;
+               u32 data3_reg                      : 8;
+               u32 data4_reg                      : 8;
+               u32 exlicit_stops                  : 1;
+               u32 force_stop                     : 1;
+               u32 unused                         : 6;
+       } tw_sm_c_104;
+
+       struct {
+               u32 thi1                           : 6;
+               u32 reserved1                      : 2;
+               u32 tlo1                           : 5;
+               u32 reserved2                      :19;
+       } tw_sm_c_108;
+
+       struct {
+               u32 thi1                           : 6;
+               u32 reserved1                      : 2;
+               u32 tlo1                           : 5;
+               u32 reserved2                      :19;
+       } tw_sm_c_10c;
+
+       struct {
+               u32 thi1                           : 6;
+               u32 reserved1                      : 2;
+               u32 tlo1                           : 5;
+               u32 reserved2                      :19;
+       } tw_sm_c_110;
+
+       struct {
+               u32 LNB_CTLHighCount_sig           :15;
+               u32 LNB_CTLLowCount_sig            :15;
+               u32 LNB_CTLPrescaler_sig           : 2;
+       } lnb_switch_freq_200;
+
+       struct {
+               u32 ACPI1_sig                      : 1;
+               u32 ACPI3_sig                      : 1;
+               u32 LNB_L_H_sig                    : 1;
+               u32 Per_reset_sig                  : 1;
+               u32 reserved                       :20;
+               u32 Rev_N_sig_revision_hi          : 4;
+               u32 Rev_N_sig_reserved1            : 2;
+               u32 Rev_N_sig_caps                 : 1;
+               u32 Rev_N_sig_reserved2            : 1;
+       } misc_204;
+
+       struct {
+               u32 Stream1_filter_sig             : 1;
+               u32 Stream2_filter_sig             : 1;
+               u32 PCR_filter_sig                 : 1;
+               u32 PMT_filter_sig                 : 1;
+               u32 EMM_filter_sig                 : 1;
+               u32 ECM_filter_sig                 : 1;
+               u32 Null_filter_sig                : 1;
+               u32 Mask_filter_sig                : 1;
+               u32 WAN_Enable_sig                 : 1;
+               u32 WAN_CA_Enable_sig              : 1;
+               u32 CA_Enable_sig                  : 1;
+               u32 SMC_Enable_sig                 : 1;
+               u32 Per_CA_Enable_sig              : 1;
+               u32 Multi2_Enable_sig              : 1;
+               u32 MAC_filter_Mode_sig            : 1;
+               u32 Rcv_Data_sig                   : 1;
+               u32 DMA1_IRQ_Enable_sig            : 1;
+               u32 DMA1_Timer_Enable_sig          : 1;
+               u32 DMA2_IRQ_Enable_sig            : 1;
+               u32 DMA2_Timer_Enable_sig          : 1;
+               u32 DMA1_Size_IRQ_Enable_sig       : 1;
+               u32 DMA2_Size_IRQ_Enable_sig       : 1;
+               u32 Mailbox_from_V8_Enable_sig     : 1;
+               u32 unused                         : 9;
+       } ctrl_208;
+
+       struct {
+               u32 DMA1_IRQ_Status                : 1;
+               u32 DMA1_Timer_Status              : 1;
+               u32 DMA2_IRQ_Status                : 1;
+               u32 DMA2_Timer_Status              : 1;
+               u32 DMA1_Size_IRQ_Status           : 1;
+               u32 DMA2_Size_IRQ_Status           : 1;
+               u32 Mailbox_from_V8_Status_sig     : 1;
+               u32 Data_receiver_error            : 1;
+               u32 Continuity_error_flag          : 1;
+               u32 LLC_SNAP_FLAG_set              : 1;
+               u32 Transport_Error                : 1;
+               u32 reserved                       :21;
+       } irq_20c;
+
+       struct {
+               u32 reset_block_000                : 1;
+               u32 reset_block_100                : 1;
+               u32 reset_block_200                : 1;
+               u32 reset_block_300                : 1;
+               u32 reset_block_400                : 1;
+               u32 reset_block_500                : 1;
+               u32 reset_block_600                : 1;
+               u32 reset_block_700                : 1;
+               u32 Block_reset_enable             : 8;
+               u32 Special_controls               :16;
+       } sw_reset_210;
+
+       struct {
+               u32 vuart_oe_sig                   : 1;
+               u32 v2WS_oe_sig                    : 1;
+               u32 halt_V8_sig                    : 1;
+               u32 section_pkg_enable_sig         : 1;
+               u32 s2p_sel_sig                    : 1;
+               u32 unused1                        : 3;
+               u32 polarity_PS_CLK_sig            : 1;
+               u32 polarity_PS_VALID_sig          : 1;
+               u32 polarity_PS_SYNC_sig           : 1;
+               u32 polarity_PS_ERR_sig            : 1;
+               u32 unused2                        :20;
+       } misc_214;
+
+       struct {
+               u32 Mailbox_from_V8                :32;
+       } mbox_v8_to_host_218;
+
+       struct {
+               u32 sysramaccess_data              : 8;
+               u32 sysramaccess_addr              :15;
+               u32 unused                         : 7;
+               u32 sysramaccess_write             : 1;
+               u32 sysramaccess_busmuster         : 1;
+       } mbox_host_to_v8_21c;
+
+       struct {
+               u32 Stream1_PID                    :13;
+               u32 Stream1_trans                  : 1;
+               u32 MAC_Multicast_filter           : 1;
+               u32 debug_flag_pid_saved           : 1;
+               u32 Stream2_PID                    :13;
+               u32 Stream2_trans                  : 1;
+               u32 debug_flag_write_status00      : 1;
+               u32 debug_fifo_problem             : 1;
+       } pid_filter_300;
+
+       struct {
+               u32 PCR_PID                        :13;
+               u32 PCR_trans                      : 1;
+               u32 debug_overrun3                 : 1;
+               u32 debug_overrun2                 : 1;
+               u32 PMT_PID                        :13;
+               u32 PMT_trans                      : 1;
+               u32 reserved                       : 2;
+       } pid_filter_304;
+
+       struct {
+               u32 EMM_PID                        :13;
+               u32 EMM_trans                      : 1;
+               u32 EMM_filter_4                   : 1;
+               u32 EMM_filter_6                   : 1;
+               u32 ECM_PID                        :13;
+               u32 ECM_trans                      : 1;
+               u32 reserved                       : 2;
+       } pid_filter_308;
+
+       struct {
+               u32 Group_PID                      :13;
+               u32 Group_trans                    : 1;
+               u32 unused1                        : 2;
+               u32 Group_mask                     :13;
+               u32 unused2                        : 3;
+       } pid_filter_30c_ext_ind_0_7;
+
+       struct {
+               u32 net_master_read                :17;
+               u32 unused                         :15;
+       } pid_filter_30c_ext_ind_1;
+
+       struct {
+               u32 net_master_write               :17;
+               u32 unused                         :15;
+       } pid_filter_30c_ext_ind_2;
+
+       struct {
+               u32 next_net_master_write          :17;
+               u32 unused                         :15;
+       } pid_filter_30c_ext_ind_3;
+
+       struct {
+               u32 unused1                        : 1;
+               u32 state_write                    :10;
+               u32 reserved1                      : 6;
+               u32 stack_read                     :10;
+               u32 reserved2                      : 5;
+       } pid_filter_30c_ext_ind_4;
+
+       struct {
+               u32 stack_cnt                      :10;
+               u32 unused                         :22;
+       } pid_filter_30c_ext_ind_5;
+
+       struct {
+               u32 pid_fsm_save_reg0              : 2;
+               u32 pid_fsm_save_reg1              : 2;
+               u32 pid_fsm_save_reg2              : 2;
+               u32 pid_fsm_save_reg3              : 2;
+               u32 pid_fsm_save_reg4              : 2;
+               u32 pid_fsm_save_reg300            : 2;
+               u32 write_status1                  : 2;
+               u32 write_status4                  : 2;
+               u32 data_size_reg                  :12;
+               u32 unused                         : 4;
+       } pid_filter_30c_ext_ind_6;
+
+       struct {
+               u32 index_reg                      : 5;
+               u32 extra_index_reg                : 3;
+               u32 AB_select                      : 1;
+               u32 pass_alltables                 : 1;
+               u32 unused                         :22;
+       } index_reg_310;
+
+       struct {
+               u32 PID                            :13;
+               u32 PID_trans                      : 1;
+               u32 PID_enable_bit                 : 1;
+               u32 reserved                       :17;
+       } pid_n_reg_314;
+
+       struct {
+               u32 A4_byte                        : 8;
+               u32 A5_byte                        : 8;
+               u32 A6_byte                        : 8;
+               u32 Enable_bit                     : 1;
+               u32 HighAB_bit                     : 1;
+               u32 reserved                       : 6;
+       } mac_low_reg_318;
+
+       struct {
+               u32 A1_byte                        : 8;
+               u32 A2_byte                        : 8;
+               u32 A3_byte                        : 8;
+               u32 reserved                       : 8;
+       } mac_high_reg_31c;
+
+       struct {
+               u32 reserved                       :16;
+               u32 data_Tag_ID                    :16;
+       } data_tag_400;
+
+       struct {
+               u32 Card_IDbyte6                   : 8;
+               u32 Card_IDbyte5                   : 8;
+               u32 Card_IDbyte4                   : 8;
+               u32 Card_IDbyte3                   : 8;
+       } card_id_408;
+
+       struct {
+               u32 Card_IDbyte2                   : 8;
+               u32 Card_IDbyte1                   : 8;
+       } card_id_40c;
+
+       struct {
+               u32 MAC1                           : 8;
+               u32 MAC2                           : 8;
+               u32 MAC3                           : 8;
+               u32 MAC6                           : 8;
+       } mac_address_418;
+
+       struct {
+               u32 MAC7                           : 8;
+               u32 MAC8                           : 8;
+               u32 reserved                       :16;
+       } mac_address_41c;
+
+       struct {
+               u32 transmitter_data_byte          : 8;
+               u32 ReceiveDataReady               : 1;
+               u32 ReceiveByteFrameError          : 1;
+               u32 txbuffempty                    : 1;
+               u32 reserved                       :21;
+       } ci_600;
+
+       struct {
+               u32 pi_d                           : 8;
+               u32 pi_ha                          :20;
+               u32 pi_rw                          : 1;
+               u32 pi_component_reg               : 3;
+       } pi_604;
+
+       struct {
+               u32 serialReset                    : 1;
+               u32 oncecycle_read                 : 1;
+               u32 Timer_Read_req                 : 1;
+               u32 Timer_Load_req                 : 1;
+               u32 timer_data                     : 7;
+               u32 unused                         : 1;
+               u32 Timer_addr                     : 5;
+               u32 reserved                       : 3;
+               u32 pcmcia_a_mod_pwr_n             : 1;
+               u32 pcmcia_b_mod_pwr_n             : 1;
+               u32 config_Done_stat               : 1;
+               u32 config_Init_stat               : 1;
+               u32 config_Prog_n                  : 1;
+               u32 config_wr_n                    : 1;
+               u32 config_cs_n                    : 1;
+               u32 config_cclk                    : 1;
+               u32 pi_CiMax_IRQ_n                 : 1;
+               u32 pi_timeout_status              : 1;
+               u32 pi_wait_n                      : 1;
+               u32 pi_busy_n                      : 1;
+       } pi_608;
+
+       struct {
+               u32 PID                            :13;
+               u32 key_enable                     : 1;
+               u32 key_code                       : 2;
+               u32 key_array_col                  : 3;
+               u32 key_array_row                  : 5;
+               u32 dvb_en                         : 1;
+               u32 rw_flag                        : 1;
+               u32 reserved                       : 6;
+       } dvb_reg_60c;
+
+       struct {
+               u32 sram_addr                      :15;
+               u32 sram_rw                        : 1;
+               u32 sram_data                      : 8;
+               u32 sc_xfer_bit                    : 1;
+               u32 reserved1                      : 3;
+               u32 oe_pin_reg                     : 1;
+               u32 ce_pin_reg                     : 1;
+               u32 reserved2                      : 1;
+               u32 start_sram_ibi                 : 1;
+       } sram_ctrl_reg_700;
+
+       struct {
+               u32 net_addr_read                  :16;
+               u32 net_addr_write                 :16;
+       } net_buf_reg_704;
+
+       struct {
+               u32 cai_read                       :11;
+               u32 reserved1                      : 5;
+               u32 cai_write                      :11;
+               u32 reserved2                      : 6;
+               u32 cai_cnt                        : 4;
+       } cai_buf_reg_708;
+
+       struct {
+               u32 cao_read                       :11;
+               u32 reserved1                      : 5;
+               u32 cap_write                      :11;
+               u32 reserved2                      : 6;
+               u32 cao_cnt                        : 4;
+       } cao_buf_reg_70c;
+
+       struct {
+               u32 media_read                     :11;
+               u32 reserved1                      : 5;
+               u32 media_write                    :11;
+               u32 reserved2                      : 6;
+               u32 media_cnt                      : 4;
+       } media_buf_reg_710;
+
+       struct {
+               u32 NET_Dest                       : 2;
+               u32 CAI_Dest                       : 2;
+               u32 CAO_Dest                       : 2;
+               u32 MEDIA_Dest                     : 2;
+               u32 net_ovflow_error               : 1;
+               u32 media_ovflow_error             : 1;
+               u32 cai_ovflow_error               : 1;
+               u32 cao_ovflow_error               : 1;
+               u32 ctrl_usb_wan                   : 1;
+               u32 ctrl_sramdma                   : 1;
+               u32 ctrl_maximumfill               : 1;
+               u32 reserved                       :17;
+       } sram_dest_reg_714;
+
+       struct {
+               u32 net_cnt                        :12;
+               u32 reserved1                      : 4;
+               u32 net_addr_read                  : 1;
+               u32 reserved2                      : 3;
+               u32 net_addr_write                 : 1;
+               u32 reserved3                      :11;
+       } net_buf_reg_718;
+
+       struct {
+               u32 wan_speed_sig                  : 2;
+               u32 reserved1                      : 6;
+               u32 wan_wait_state                 : 8;
+               u32 sram_chip                      : 2;
+               u32 sram_memmap                    : 2;
+               u32 reserved2                      : 4;
+               u32 wan_pkt_frame                  : 4;
+               u32 reserved3                      : 4;
+       } wan_ctrl_reg_71c;
+} flexcop_ibi_value;
+
+#endif
diff --git a/drivers/media/dvb/b2c2/skystar2.c b/drivers/media/dvb/b2c2/skystar2.c
deleted file mode 100644 (file)
index acbc4c3..0000000
+++ /dev/null
@@ -1,2644 +0,0 @@
-/*
- * skystar2.c - driver for the Technisat SkyStar2 PCI DVB card
- *              based on the FlexCopII by B2C2,Inc.
- *
- * Copyright (C) 2003  Vadim Catana, skystar@moldova.cc
- *
- * FIX: DISEQC Tone Burst in flexcop_diseqc_ioctl()
- * FIX: FULL soft DiSEqC for skystar2 (FlexCopII rev 130) VP310 equipped
- *     Vincenzo Di Massa, hawk.it at tiscalinet.it
- *
- * Converted to Linux coding style
- * Misc reorganization, polishing, restyling
- *     Roberto Ragusa, skystar2-c5b8 at robertoragusa dot it
- *
- * Added hardware filtering support,
- *     Niklas Peinecke, peinecke at gdv.uni-hannover.de
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser 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/module.h>
-#include <linux/moduleparam.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/version.h>
-
-#include <asm/io.h>
-
-#include "dvb_frontend.h"
-
-#include <linux/dvb/frontend.h>
-#include <linux/dvb/dmx.h>
-#include "dvb_demux.h"
-#include "dmxdev.h"
-#include "dvb_filter.h"
-#include "dvbdev.h"
-#include "demux.h"
-#include "dvb_net.h"
-#include "stv0299.h"
-#include "mt352.h"
-#include "mt312.h"
-#include "nxt2002.h"
-
-static int debug;
-static int enable_hw_filters = 2;
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Set debugging level (0 = default, 1 = most messages, 2 = all messages).");
-module_param(enable_hw_filters, int, 0444);
-MODULE_PARM_DESC(enable_hw_filters, "enable hardware filters: supported values: 0 (none), 1, 2");
-
-#define dprintk(x...)  do { if (debug>=1) printk(x); } while (0)
-#define ddprintk(x...) do { if (debug>=2) printk(x); } while (0)
-
-#define SIZE_OF_BUF_DMA1       0x3ac00
-#define SIZE_OF_BUF_DMA2       0x758
-
-#define MAX_N_HW_FILTERS       (6+32)
-#define N_PID_SLOTS            256
-
-struct dmaq {
-       u32 bus_addr;
-       u32 head;
-       u32 tail;
-       u32 buffer_size;
-       u8 *buffer;
-};
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)
-#define __iomem
-#endif
-
-struct adapter {
-       struct pci_dev *pdev;
-
-       u8 card_revision;
-       u32 b2c2_revision;
-       u32 pid_filter_max;
-       u32 mac_filter_max;
-       u32 irq;
-       void __iomem *io_mem;
-       unsigned long io_port;
-       u8 mac_addr[8];
-       u32 dw_sram_type;
-
-       struct dvb_adapter dvb_adapter;
-       struct dvb_demux demux;
-       struct dmxdev dmxdev;
-       struct dmx_frontend hw_frontend;
-       struct dmx_frontend mem_frontend;
-       struct i2c_adapter i2c_adap;
-       struct dvb_net dvbnet;
-
-       struct semaphore i2c_sem;
-
-       struct dmaq dmaq1;
-       struct dmaq dmaq2;
-
-       u32 dma_ctrl;
-       u32 dma_status;
-
-       int capturing;
-
-       spinlock_t lock;
-
-       int useable_hw_filters;
-       u16 hw_pids[MAX_N_HW_FILTERS];
-       u16 pid_list[N_PID_SLOTS];
-       int pid_rc[N_PID_SLOTS];        // ref counters for the pids
-       int pid_count;
-       int whole_bandwidth_count;
-       u32 mac_filter;
-
-       struct dvb_frontend* fe;
-       int (*fe_sleep)(struct dvb_frontend* fe);
-};
-
-#define write_reg_dw(adapter,reg,value) writel(value, adapter->io_mem + reg)
-#define read_reg_dw(adapter,reg) readl(adapter->io_mem + reg)
-
-static void write_reg_bitfield(struct adapter *adapter, u32 reg, u32 zeromask, u32 orvalue)
-{
-       u32 tmp;
-
-       tmp = read_reg_dw(adapter, reg);
-       tmp = (tmp & ~zeromask) | orvalue;
-       write_reg_dw(adapter, reg, tmp);
-}
-
-/* i2c functions */
-static int i2c_main_write_for_flex2(struct adapter *adapter, u32 command, u8 *buf, int retries)
-{
-       int i;
-       u32 value;
-
-       write_reg_dw(adapter, 0x100, 0);
-       write_reg_dw(adapter, 0x100, command);
-
-       for (i = 0; i < retries; i++) {
-               value = read_reg_dw(adapter, 0x100);
-
-               if ((value & 0x40000000) == 0) {
-                       if ((value & 0x81000000) == 0x80000000) {
-                               if (buf != 0)
-                                       *buf = (value >> 0x10) & 0xff;
-
-                               return 1;
-                       }
-               } else {
-                       write_reg_dw(adapter, 0x100, 0);
-                       write_reg_dw(adapter, 0x100, command);
-               }
-       }
-
-       return 0;
-}
-
-/* device = 0x10000000 for tuner, 0x20000000 for eeprom */
-static void i2c_main_setup(u32 device, u32 chip_addr, u8 op, u8 addr, u32 value, u32 len, u32 *command)
-{
-       *command = device | ((len - 1) << 26) | (value << 16) | (addr << 8) | chip_addr;
-
-       if (op != 0)
-               *command = *command | 0x03000000;
-       else
-               *command = *command | 0x01000000;
-}
-
-static int flex_i2c_read4(struct adapter *adapter, u32 device, u32 chip_addr, u16 addr, u8 *buf, u8 len)
-{
-       u32 command;
-       u32 value;
-
-       int result, i;
-
-       i2c_main_setup(device, chip_addr, 1, addr, 0, len, &command);
-
-       result = i2c_main_write_for_flex2(adapter, command, buf, 100000);
-
-       if ((result & 0xff) != 0) {
-               if (len > 1) {
-                       value = read_reg_dw(adapter, 0x104);
-
-                       for (i = 1; i < len; i++) {
-                               buf[i] = value & 0xff;
-                               value = value >> 8;
-                       }
-               }
-       }
-
-       return result;
-}
-
-static int flex_i2c_write4(struct adapter *adapter, u32 device, u32 chip_addr, u32 addr, u8 *buf, u8 len)
-{
-       u32 command;
-       u32 value;
-       int i;
-
-       if (len > 1) {
-               value = 0;
-
-               for (i = len; i > 1; i--) {
-                       value = value << 8;
-                       value = value | buf[i - 1];
-               }
-
-               write_reg_dw(adapter, 0x104, value);
-       }
-
-       i2c_main_setup(device, chip_addr, 0, addr, buf[0], len, &command);
-
-       return i2c_main_write_for_flex2(adapter, command, NULL, 100000);
-}
-
-static void fixchipaddr(u32 device, u32 bus, u32 addr, u32 *ret)
-{
-       if (device == 0x20000000)
-               *ret = bus | ((addr >> 8) & 3);
-       else
-               *ret = bus;
-}
-
-static u32 flex_i2c_read(struct adapter *adapter, u32 device, u32 bus, u32 addr, u8 *buf, u32 len)
-{
-       u32 chipaddr;
-       u32 bytes_to_transfer;
-       u8 *start;
-
-       ddprintk("%s:\n", __FUNCTION__);
-
-       start = buf;
-
-       while (len != 0) {
-               bytes_to_transfer = len;
-
-               if (bytes_to_transfer > 4)
-                       bytes_to_transfer = 4;
-
-               fixchipaddr(device, bus, addr, &chipaddr);
-
-               if (flex_i2c_read4(adapter, device, chipaddr, addr, buf, bytes_to_transfer) == 0)
-                       return buf - start;
-
-               buf = buf + bytes_to_transfer;
-               addr = addr + bytes_to_transfer;
-               len = len - bytes_to_transfer;
-       };
-
-       return buf - start;
-}
-
-static u32 flex_i2c_write(struct adapter *adapter, u32 device, u32 bus, u32 addr, u8 *buf, u32 len)
-{
-       u32 chipaddr;
-       u32 bytes_to_transfer;
-       u8 *start;
-
-       ddprintk("%s:\n", __FUNCTION__);
-
-       start = buf;
-
-       while (len != 0) {
-               bytes_to_transfer = len;
-
-               if (bytes_to_transfer > 4)
-                       bytes_to_transfer = 4;
-
-               fixchipaddr(device, bus, addr, &chipaddr);
-
-               if (flex_i2c_write4(adapter, device, chipaddr, addr, buf, bytes_to_transfer) == 0)
-                       return buf - start;
-
-               buf = buf + bytes_to_transfer;
-               addr = addr + bytes_to_transfer;
-               len = len - bytes_to_transfer;
-       }
-
-       return buf - start;
-}
-
-static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msgs, int num)
-{
-       struct adapter *tmp = i2c_get_adapdata(adapter);
-       int i, ret = 0;
-
-       if (down_interruptible(&tmp->i2c_sem))
-               return -ERESTARTSYS;
-
-       ddprintk("%s: %d messages to transfer\n", __FUNCTION__, num);
-
-               for (i = 0; i < num; i++) {
-               ddprintk("message %d: flags=0x%x, addr=0x%x, buf=0x%x, len=%d \n", i,
-                        msgs[i].flags, msgs[i].addr, msgs[i].buf[0], msgs[i].len);
-       }
-
-       // read command
-       if ((num == 2) && (msgs[0].flags == 0) && (msgs[1].flags == I2C_M_RD) && (msgs[0].buf != NULL) && (msgs[1].buf != NULL)) {
-
-               ret = flex_i2c_read(tmp, 0x10000000, msgs[0].addr, msgs[0].buf[0], msgs[1].buf, msgs[1].len);
-
-               up(&tmp->i2c_sem);
-
-               if (ret != msgs[1].len) {
-                       dprintk("%s: read error !\n", __FUNCTION__);
-
-                       for (i = 0; i < 2; i++) {
-                               dprintk("message %d: flags=0x%x, addr=0x%x, buf=0x%x, len=%d \n", i,
-                                      msgs[i].flags, msgs[i].addr, msgs[i].buf[0], msgs[i].len);
-               }
-
-                       return -EREMOTEIO;
-               }
-
-               return num;
-       }
-       // write command
-       for (i = 0; i < num; i++) {
-
-               if ((msgs[i].flags != 0) || (msgs[i].buf == NULL) || (msgs[i].len < 2))
-                       return -EINVAL;
-
-               ret = flex_i2c_write(tmp, 0x10000000, msgs[i].addr, msgs[i].buf[0], &msgs[i].buf[1], msgs[i].len - 1);
-
-               up(&tmp->i2c_sem);
-
-               if (ret != msgs[0].len - 1) {
-                       dprintk("%s: write error %i !\n", __FUNCTION__, ret);
-
-                       dprintk("message %d: flags=0x%x, addr=0x%x, buf[0]=0x%x, len=%d \n", i,
-                              msgs[i].flags, msgs[i].addr, msgs[i].buf[0], msgs[i].len);
-
-                       return -EREMOTEIO;
-               }
-
-               return num;
-       }
-
-       printk("%s: unknown command format !\n", __FUNCTION__);
-
-       return -EINVAL;
-}
-
-/* SRAM (Skystar2 rev2.3 has one "ISSI IS61LV256" chip on board,
-   but it seems that FlexCopII can work with more than one chip) */
-static void sram_set_net_dest(struct adapter *adapter, u8 dest)
-{
-       u32 tmp;
-
-       udelay(1000);
-
-       tmp = (read_reg_dw(adapter, 0x714) & 0xfffffffc) | (dest & 3);
-
-       udelay(1000);
-
-       write_reg_dw(adapter, 0x714, tmp);
-       write_reg_dw(adapter, 0x714, tmp);
-
-       udelay(1000);
-
-       /* return value is never used? */
-/*     return tmp; */
-}
-
-static void sram_set_cai_dest(struct adapter *adapter, u8 dest)
-{
-       u32 tmp;
-
-       udelay(1000);
-
-       tmp = (read_reg_dw(adapter, 0x714) & 0xfffffff3) | ((dest & 3) << 2);
-
-       udelay(1000);
-       udelay(1000);
-
-       write_reg_dw(adapter, 0x714, tmp);
-       write_reg_dw(adapter, 0x714, tmp);
-
-       udelay(1000);
-
-       /* return value is never used? */
-/*     return tmp; */
-}
-
-static void sram_set_cao_dest(struct adapter *adapter, u8 dest)
-{
-       u32 tmp;
-
-       udelay(1000);
-
-       tmp = (read_reg_dw(adapter, 0x714) & 0xffffffcf) | ((dest & 3) << 4);
-
-       udelay(1000);
-       udelay(1000);
-
-       write_reg_dw(adapter, 0x714, tmp);
-       write_reg_dw(adapter, 0x714, tmp);
-
-       udelay(1000);
-
-       /* return value is never used? */
-/*     return tmp; */
-}
-
-static void sram_set_media_dest(struct adapter *adapter, u8 dest)
-{
-       u32 tmp;
-
-       udelay(1000);
-
-       tmp = (read_reg_dw(adapter, 0x714) & 0xffffff3f) | ((dest & 3) << 6);
-
-       udelay(1000);
-       udelay(1000);
-
-       write_reg_dw(adapter, 0x714, tmp);
-       write_reg_dw(adapter, 0x714, tmp);
-
-       udelay(1000);
-
-       /* return value is never used? */
-/*     return tmp; */
-}
-
-/* SRAM memory is accessed through a buffer register in the FlexCop
-   chip (0x700). This register has the following structure:
-    bits 0-14  : address
-    bit  15    : read/write flag
-    bits 16-23 : 8-bit word to write
-    bits 24-27 : = 4
-    bits 28-29 : memory bank selector
-    bit  31    : busy flag
-*/
-static void flex_sram_write(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len)
-{
-       int i, retries;
-       u32 command;
-
-       for (i = 0; i < len; i++) {
-               command = bank | addr | 0x04000000 | (*buf << 0x10);
-
-               retries = 2;
-
-               while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
-                       mdelay(1);
-                       retries--;
-               };
-
-               if (retries == 0)
-                       printk("%s: SRAM timeout\n", __FUNCTION__);
-
-               write_reg_dw(adapter, 0x700, command);
-
-               buf++;
-               addr++;
-       }
-}
-
-static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len)
-{
-       int i, retries;
-       u32 command, value;
-
-       for (i = 0; i < len; i++) {
-               command = bank | addr | 0x04008000;
-
-               retries = 10000;
-
-               while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
-                       mdelay(1);
-                       retries--;
-               };
-
-               if (retries == 0)
-                       printk("%s: SRAM timeout\n", __FUNCTION__);
-
-               write_reg_dw(adapter, 0x700, command);
-
-               retries = 10000;
-
-               while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
-                       mdelay(1);
-                       retries--;
-               };
-
-               if (retries == 0)
-                       printk("%s: SRAM timeout\n", __FUNCTION__);
-
-               value = read_reg_dw(adapter, 0x700) >> 0x10;
-
-               *buf = (value & 0xff);
-
-               addr++;
-               buf++;
-       }
-}
-
-static void sram_write_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len)
-{
-       u32 bank;
-
-       bank = 0;
-
-       if (adapter->dw_sram_type == 0x20000) {
-               bank = (addr & 0x18000) << 0x0d;
-       }
-
-       if (adapter->dw_sram_type == 0x00000) {
-               if ((addr >> 0x0f) == 0)
-                       bank = 0x20000000;
-               else
-                       bank = 0x10000000;
-       }
-
-       flex_sram_write(adapter, bank, addr & 0x7fff, buf, len);
-}
-
-static void sram_read_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len)
-{
-       u32 bank;
-
-       bank = 0;
-
-       if (adapter->dw_sram_type == 0x20000) {
-               bank = (addr & 0x18000) << 0x0d;
-       }
-
-       if (adapter->dw_sram_type == 0x00000) {
-               if ((addr >> 0x0f) == 0)
-                       bank = 0x20000000;
-               else
-                       bank = 0x10000000;
-       }
-
-       flex_sram_read(adapter, bank, addr & 0x7fff, buf, len);
-}
-
-static void sram_read(struct adapter *adapter, u32 addr, u8 *buf, u32 len)
-{
-       u32 length;
-
-       while (len != 0) {
-               length = len;
-
-               // check if the address range belongs to the same 
-               // 32K memory chip. If not, the data is read from 
-               // one chip at a time.
-               if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) {
-                       length = (((addr >> 0x0f) + 1) << 0x0f) - addr;
-               }
-
-               sram_read_chunk(adapter, addr, buf, length);
-
-               addr = addr + length;
-               buf = buf + length;
-               len = len - length;
-       }
-}
-
-static void sram_write(struct adapter *adapter, u32 addr, u8 *buf, u32 len)
-{
-       u32 length;
-
-       while (len != 0) {
-               length = len;
-
-               // check if the address range belongs to the same 
-               // 32K memory chip. If not, the data is written to
-               // one chip at a time.
-               if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) {
-                       length = (((addr >> 0x0f) + 1) << 0x0f) - addr;
-               }
-
-               sram_write_chunk(adapter, addr, buf, length);
-
-               addr = addr + length;
-               buf = buf + length;
-               len = len - length;
-       }
-}
-
-static void sram_set_size(struct adapter *adapter, u32 mask)
-{
-       write_reg_dw(adapter, 0x71c, (mask | (~0x30000 & read_reg_dw(adapter, 0x71c))));
-}
-
-static void sram_init(struct adapter *adapter)
-{
-       u32 tmp;
-
-       tmp = read_reg_dw(adapter, 0x71c);
-
-       write_reg_dw(adapter, 0x71c, 1);
-
-       if (read_reg_dw(adapter, 0x71c) != 0) {
-               write_reg_dw(adapter, 0x71c, tmp);
-
-               adapter->dw_sram_type = tmp & 0x30000;
-
-               ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
-
-       } else {
-
-               adapter->dw_sram_type = 0x10000;
-
-               ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
-       }
-
-       /* return value is never used? */
-/*     return adapter->dw_sram_type; */
-}
-
-static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
-{
-       u8 tmp1, tmp2;
-
-       dprintk("%s: mask = %x, addr = %x\n", __FUNCTION__, mask, addr);
-
-       sram_set_size(adapter, mask);
-       sram_init(adapter);
-
-       tmp2 = 0xa5;
-       tmp1 = 0x4f;
-
-       sram_write(adapter, addr, &tmp2, 1);
-       sram_write(adapter, addr + 4, &tmp1, 1);
-
-       tmp2 = 0;
-
-       mdelay(20);
-
-       sram_read(adapter, addr, &tmp2, 1);
-       sram_read(adapter, addr, &tmp2, 1);
-
-       dprintk("%s: wrote 0xa5, read 0x%2x\n", __FUNCTION__, tmp2);
-
-       if (tmp2 != 0xa5)
-               return 0;
-
-       tmp2 = 0x5a;
-       tmp1 = 0xf4;
-
-       sram_write(adapter, addr, &tmp2, 1);
-       sram_write(adapter, addr + 4, &tmp1, 1);
-
-       tmp2 = 0;
-
-       mdelay(20);
-
-       sram_read(adapter, addr, &tmp2, 1);
-       sram_read(adapter, addr, &tmp2, 1);
-
-       dprintk("%s: wrote 0x5a, read 0x%2x\n", __FUNCTION__, tmp2);
-
-       if (tmp2 != 0x5a)
-               return 0;
-
-       return 1;
-}
-
-static u32 sram_length(struct adapter *adapter)
-{
-       if (adapter->dw_sram_type == 0x10000)
-               return 32768;   //  32K
-       if (adapter->dw_sram_type == 0x00000)
-               return 65536;   //  64K        
-       if (adapter->dw_sram_type == 0x20000)
-               return 131072;  // 128K
-
-       return 32768;           // 32K
-}
-
-/* FlexcopII can work with 32K, 64K or 128K of external SRAM memory.
-    - for 128K there are 4x32K chips at bank 0,1,2,3.
-    - for  64K there are 2x32K chips at bank 1,2.
-    - for  32K there is one 32K chip at bank 0.
-
-   FlexCop works only with one bank at a time. The bank is selected
-   by bits 28-29 of the 0x700 register.
-  
-   bank 0 covers addresses 0x00000-0x07fff
-   bank 1 covers addresses 0x08000-0x0ffff
-   bank 2 covers addresses 0x10000-0x17fff
-   bank 3 covers addresses 0x18000-0x1ffff
-*/
-static int sram_detect_for_flex2(struct adapter *adapter)
-{
-       u32 tmp, tmp2, tmp3;
-
-       dprintk("%s:\n", __FUNCTION__);
-
-       tmp = read_reg_dw(adapter, 0x208);
-       write_reg_dw(adapter, 0x208, 0);
-
-       tmp2 = read_reg_dw(adapter, 0x71c);
-
-       dprintk("%s: tmp2 = %x\n", __FUNCTION__, tmp2);
-
-       write_reg_dw(adapter, 0x71c, 1);
-
-       tmp3 = read_reg_dw(adapter, 0x71c);
-
-       dprintk("%s: tmp3 = %x\n", __FUNCTION__, tmp3);
-
-       write_reg_dw(adapter, 0x71c, tmp2);
-
-       // check for internal SRAM ???
-       tmp3--;
-       if (tmp3 != 0) {
-               sram_set_size(adapter, 0x10000);
-               sram_init(adapter);
-               write_reg_dw(adapter, 0x208, tmp);
-
-               dprintk("%s: sram size = 32K\n", __FUNCTION__);
-
-               return 32;
-       }
-
-       if (sram_test_location(adapter, 0x20000, 0x18000) != 0) {
-               sram_set_size(adapter, 0x20000);
-               sram_init(adapter);
-               write_reg_dw(adapter, 0x208, tmp);
-
-               dprintk("%s: sram size = 128K\n", __FUNCTION__);
-
-               return 128;
-       }
-
-       if (sram_test_location(adapter, 0x00000, 0x10000) != 0) {
-               sram_set_size(adapter, 0x00000);
-               sram_init(adapter);
-               write_reg_dw(adapter, 0x208, tmp);
-
-               dprintk("%s: sram size = 64K\n", __FUNCTION__);
-
-               return 64;
-       }
-
-       if (sram_test_location(adapter, 0x10000, 0x00000) != 0) {
-               sram_set_size(adapter, 0x10000);
-               sram_init(adapter);
-               write_reg_dw(adapter, 0x208, tmp);
-
-               dprintk("%s: sram size = 32K\n", __FUNCTION__);
-
-               return 32;
-       }
-
-       sram_set_size(adapter, 0x10000);
-       sram_init(adapter);
-       write_reg_dw(adapter, 0x208, tmp);
-
-       dprintk("%s: SRAM detection failed. Set to 32K \n", __FUNCTION__);
-
-       return 0;
-}
-
-static void sll_detect_sram_size(struct adapter *adapter)
-{
-       sram_detect_for_flex2(adapter);
-}
-
-/* EEPROM (Skystar2 has one "24LC08B" chip on board) */
-/*
-static int eeprom_write(struct adapter *adapter, u16 addr, u8 *buf, u16 len)
-{
-       return flex_i2c_write(adapter, 0x20000000, 0x50, addr, buf, len);
-}
-*/
-
-static int eeprom_read(struct adapter *adapter, u16 addr, u8 *buf, u16 len)
-{
-       return flex_i2c_read(adapter, 0x20000000, 0x50, addr, buf, len);
-}
-
-static u8 calc_lrc(u8 *buf, int len)
-{
-       int i;
-       u8 sum;
-
-       sum = 0;
-
-       for (i = 0; i < len; i++)
-               sum = sum ^ buf[i];
-
-       return sum;
-}
-
-static int eeprom_lrc_read(struct adapter *adapter, u32 addr, u32 len, u8 *buf, int retries)
-{
-       int i;
-
-       for (i = 0; i < retries; i++) {
-               if (eeprom_read(adapter, addr, buf, len) == len) {
-                       if (calc_lrc(buf, len - 1) == buf[len - 1])
-                               return 1;
-               }
-       }
-
-       return 0;
-}
-
-/*
-static int eeprom_lrc_write(struct adapter *adapter, u32 addr, u32 len, u8 *wbuf, u8 *rbuf, int retries)
-{
-       int i;
-
-       for (i = 0; i < retries; i++) {
-               if (eeprom_write(adapter, addr, wbuf, len) == len) {
-                       if (eeprom_lrc_read(adapter, addr, len, rbuf, retries) == 1)
-                               return 1;
-               }
-       }
-
-       return 0;
-}
-*/
-
-
-/* These functions could be used to unlock SkyStar2 cards. */
-
-/*
-static int eeprom_writeKey(struct adapter *adapter, u8 *key, u32 len)
-{
-       u8 rbuf[20];
-       u8 wbuf[20];
-
-       if (len != 16)
-               return 0;
-
-       memcpy(wbuf, key, len);
-
-       wbuf[16] = 0;
-       wbuf[17] = 0;
-       wbuf[18] = 0;
-       wbuf[19] = calc_lrc(wbuf, 19);
-
-       return eeprom_lrc_write(adapter, 0x3e4, 20, wbuf, rbuf, 4);
-}
-
-static int eeprom_readKey(struct adapter *adapter, u8 *key, u32 len)
-{
-       u8 buf[20];
-
-       if (len != 16)
-               return 0;
-
-       if (eeprom_lrc_read(adapter, 0x3e4, 20, buf, 4) == 0)
-               return 0;
-
-       memcpy(key, buf, len);
-
-       return 1;
-}
-*/
-
-static int eeprom_get_mac_addr(struct adapter *adapter, char type, u8 *mac)
-{
-       u8 tmp[8];
-
-       if (eeprom_lrc_read(adapter, 0x3f8, 8, tmp, 4) != 0) {
-               if (type != 0) {
-                       mac[0] = tmp[0];
-                       mac[1] = tmp[1];
-                       mac[2] = tmp[2];
-                       mac[3] = 0xfe;
-                       mac[4] = 0xff;
-                       mac[5] = tmp[3];
-                       mac[6] = tmp[4];
-                       mac[7] = tmp[5];
-
-               } else {
-
-                       mac[0] = tmp[0];
-                       mac[1] = tmp[1];
-                       mac[2] = tmp[2];
-                       mac[3] = tmp[3];
-                       mac[4] = tmp[4];
-                       mac[5] = tmp[5];
-               }
-
-               return 1;
-
-       } else {
-
-               if (type == 0) {
-                       memset(mac, 0, 6);
-
-               } else {
-
-                       memset(mac, 0, 8);
-               }
-
-               return 0;
-       }
-}
-
-/*
-static char eeprom_set_mac_addr(struct adapter *adapter, char type, u8 *mac)
-{
-       u8 tmp[8];
-
-       if (type != 0) {
-               tmp[0] = mac[0];
-               tmp[1] = mac[1];
-               tmp[2] = mac[2];
-               tmp[3] = mac[5];
-               tmp[4] = mac[6];
-               tmp[5] = mac[7];
-
-       } else {
-
-               tmp[0] = mac[0];
-               tmp[1] = mac[1];
-               tmp[2] = mac[2];
-               tmp[3] = mac[3];
-               tmp[4] = mac[4];
-               tmp[5] = mac[5];
-       }
-
-       tmp[6] = 0;
-       tmp[7] = calc_lrc(tmp, 7);
-
-       if (eeprom_write(adapter, 0x3f8, tmp, 8) == 8)
-               return 1;
-
-       return 0;
-}
-*/
-
-/* PID filter */
-
-/* every flexcop has 6 "lower" hw PID filters     */
-/* these are enabled by setting bits 0-5 of 0x208 */
-/* for the 32 additional filters we have to select one */
-/* of them through 0x310 and modify through 0x314 */
-/* op: 0=disable, 1=enable */
-static void filter_enable_hw_filter(struct adapter *adapter, int id, u8 op)
-{
-       dprintk("%s: id=%d op=%d\n", __FUNCTION__, id, op);
-       if (id <= 5) {
-               u32 mask = (0x00000001 << id);
-               write_reg_bitfield(adapter, 0x208, mask, op ? mask : 0);
-       } else {
-               /* select */
-               write_reg_bitfield(adapter, 0x310, 0x1f, (id - 6) & 0x1f);
-               /* modify */
-               write_reg_bitfield(adapter, 0x314, 0x00006000, op ? 0x00004000 : 0);
-       }
-}
-
-/* this sets the PID that should pass the specified filter */
-static void pid_set_hw_pid(struct adapter *adapter, int id, u16 pid)
-{
-       dprintk("%s: id=%d  pid=%d\n", __FUNCTION__, id, pid);
-       if (id <= 5) {
-               u32 adr = 0x300 + ((id & 6) << 1);
-               int shift = (id & 1) ? 16 : 0;
-               dprintk("%s: id=%d  addr=%x %c  pid=%d\n", __FUNCTION__, id, adr, (id & 1) ? 'h' : 'l', pid);
-               write_reg_bitfield(adapter, adr, (0x7fff) << shift, (pid & 0x1fff) << shift);
-       } else {
-               /* select */
-               write_reg_bitfield(adapter, 0x310, 0x1f, (id - 6) & 0x1f);
-               /* modify */
-               write_reg_bitfield(adapter, 0x314, 0x1fff, pid & 0x1fff);
-       }
-}
-
-
-/*
-static void filter_enable_null_filter(struct adapter *adapter, u32 op)
-{
-       dprintk("%s: op=%x\n", __FUNCTION__, op);
-
-       write_reg_bitfield(adapter, 0x208, 0x00000040, op?0x00000040:0);
-}
-*/
-
-static void filter_enable_mask_filter(struct adapter *adapter, u32 op)
-{
-       dprintk("%s: op=%x\n", __FUNCTION__, op);
-
-       write_reg_bitfield(adapter, 0x208, 0x00000080, op ? 0x00000080 : 0);
-}
-
-
-static void ctrl_enable_mac(struct adapter *adapter, u32 op)
-{
-       write_reg_bitfield(adapter, 0x208, 0x00004000, op ? 0x00004000 : 0);
-}
-
-static int ca_set_mac_dst_addr_filter(struct adapter *adapter, u8 *mac)
-{
-       u32 tmp1, tmp2;
-
-       tmp1 = (mac[3] << 0x18) | (mac[2] << 0x10) | (mac[1] << 0x08) | mac[0];
-       tmp2 = (mac[5] << 0x08) | mac[4];
-
-       write_reg_dw(adapter, 0x418, tmp1);
-       write_reg_dw(adapter, 0x41c, tmp2);
-
-       return 0;
-}
-
-/*
-static void set_ignore_mac_filter(struct adapter *adapter, u8 op)
-{
-       if (op != 0) {
-               write_reg_bitfield(adapter, 0x208, 0x00004000, 0);
-               adapter->mac_filter = 1;
-       } else {
-               if (adapter->mac_filter != 0) {
-                       adapter->mac_filter = 0;
-                       write_reg_bitfield(adapter, 0x208, 0x00004000, 0x00004000);
-               }
-       }
-}
-*/
-
-/*
-static void check_null_filter_enable(struct adapter *adapter)
-{
-       filter_enable_null_filter(adapter, 1);
-       filter_enable_mask_filter(adapter, 1);
-}
-*/
-
-static void pid_set_group_pid(struct adapter *adapter, u16 pid)
-{
-       u32 value;
-
-       dprintk("%s: pid=%x\n", __FUNCTION__, pid);
-       value = (pid & 0x3fff) | (read_reg_dw(adapter, 0x30c) & 0xffff0000);
-       write_reg_dw(adapter, 0x30c, value);
-}
-
-static void pid_set_group_mask(struct adapter *adapter, u16 pid)
-{
-       u32 value;
-
-       dprintk("%s: pid=%x\n", __FUNCTION__, pid);
-       value = ((pid & 0x3fff) << 0x10) | (read_reg_dw(adapter, 0x30c) & 0xffff);
-       write_reg_dw(adapter, 0x30c, value);
-}
-
-/*
-static int pid_get_group_pid(struct adapter *adapter)
-{
-       return read_reg_dw(adapter, 0x30c) & 0x00001fff;
-}
-
-static int pid_get_group_mask(struct adapter *adapter)
-{
-       return (read_reg_dw(adapter, 0x30c) >> 0x10)& 0x00001fff;
-}
-*/
-
-/*
-static void reset_hardware_pid_filter(struct adapter *adapter)
-{
-       pid_set_stream1_pid(adapter, 0x1fff);
-
-       pid_set_stream2_pid(adapter, 0x1fff);
-       filter_enable_stream2_filter(adapter, 0);
-
-       pid_set_pcr_pid(adapter, 0x1fff);
-       filter_enable_pcr_filter(adapter, 0);
-
-       pid_set_pmt_pid(adapter, 0x1fff);
-       filter_enable_pmt_filter(adapter, 0);
-
-       pid_set_ecm_pid(adapter, 0x1fff);
-       filter_enable_ecm_filter(adapter, 0);
-
-       pid_set_emm_pid(adapter, 0x1fff);
-       filter_enable_emm_filter(adapter, 0);
-}
-*/
-
-static void init_pids(struct adapter *adapter)
-{
-       int i;
-
-       adapter->pid_count = 0;
-       adapter->whole_bandwidth_count = 0;
-       for (i = 0; i < adapter->useable_hw_filters; i++) {
-               dprintk("%s: setting filter %d to 0x1fff\n", __FUNCTION__, i);
-               adapter->hw_pids[i] = 0x1fff;
-               pid_set_hw_pid(adapter, i, 0x1fff);
-}
-
-       pid_set_group_pid(adapter, 0);
-       pid_set_group_mask(adapter, 0x1fe0);
-}
-
-static void open_whole_bandwidth(struct adapter *adapter)
-{
-       dprintk("%s:\n", __FUNCTION__);
-       pid_set_group_pid(adapter, 0);
-       pid_set_group_mask(adapter, 0);
-/*
-       filter_enable_mask_filter(adapter, 1);
-*/
-}
-
-static void close_whole_bandwidth(struct adapter *adapter)
-{
-       dprintk("%s:\n", __FUNCTION__);
-       pid_set_group_pid(adapter, 0);
-       pid_set_group_mask(adapter, 0x1fe0);
-/*
-       filter_enable_mask_filter(adapter, 1);
-*/
-}
-
-static void whole_bandwidth_inc(struct adapter *adapter)
-{
-       if (adapter->whole_bandwidth_count++ == 0)
-               open_whole_bandwidth(adapter);
-}
-
-static void whole_bandwidth_dec(struct adapter *adapter)
-{
-       if (--adapter->whole_bandwidth_count <= 0)
-               close_whole_bandwidth(adapter);
-}
-
-/* The specified PID has to be let through the
-   hw filters.
-   We try to allocate an hardware filter and open whole
-   bandwidth when allocation is impossible.
-   All pids<=0x1f pass through the group filter.
-   Returns 1 on success, -1 on error */
-static int add_hw_pid(struct adapter *adapter, u16 pid)
-{
-       int i;
-
-       dprintk("%s: pid=%d\n", __FUNCTION__, pid);
-
-       if (pid <= 0x1f)
-               return 1;
-
-       /* we can't use a filter for 0x2000, so no search */
-       if (pid != 0x2000) {
-               /* find an unused hardware filter */
-               for (i = 0; i < adapter->useable_hw_filters; i++) {
-                       dprintk("%s: pid=%d searching slot=%d\n", __FUNCTION__, pid, i);
-                       if (adapter->hw_pids[i] == 0x1fff) {
-                               dprintk("%s: pid=%d slot=%d\n", __FUNCTION__, pid, i);
-                               adapter->hw_pids[i] = pid;
-                               pid_set_hw_pid(adapter, i, pid);
-                               filter_enable_hw_filter(adapter, i, 1);
-               return 1;
-       }
-       }
-       }
-       /* if we have not used a filter, this pid depends on whole bandwidth */
-       dprintk("%s: pid=%d whole_bandwidth\n", __FUNCTION__, pid);
-       whole_bandwidth_inc(adapter);
-               return 1;
-       }
-
-/* returns -1 if the pid was not present in the filters */
-static int remove_hw_pid(struct adapter *adapter, u16 pid)
-{
-       int i;
-
-       dprintk("%s: pid=%d\n", __FUNCTION__, pid);
-
-       if (pid <= 0x1f)
-               return 1;
-
-       /* we can't use a filter for 0x2000, so no search */
-       if (pid != 0x2000) {
-               for (i = 0; i < adapter->useable_hw_filters; i++) {
-                       dprintk("%s: pid=%d searching slot=%d\n", __FUNCTION__, pid, i);
-                       if (adapter->hw_pids[i] == pid) {       // find the pid slot
-                               dprintk("%s: pid=%d slot=%d\n", __FUNCTION__, pid, i);
-                               adapter->hw_pids[i] = 0x1fff;
-                               pid_set_hw_pid(adapter, i, 0x1fff);
-                               filter_enable_hw_filter(adapter, i, 0);
-               return 1;
-       }
-       }
-       }
-       /* if we have not used a filter, this pid depended on whole bandwith */
-       dprintk("%s: pid=%d whole_bandwidth\n", __FUNCTION__, pid);
-       whole_bandwidth_dec(adapter);
-               return 1;
-       }
-
-/* Adds a PID to the filters.
-   Adding a pid more than once is possible, we keep reference counts.
-   Whole stream available through pid==0x2000.
-   Returns 1 on success, -1 on error */
-static int add_pid(struct adapter *adapter, u16 pid)
-{
-       int i;
-
-       dprintk("%s: pid=%d\n", __FUNCTION__, pid);
-
-       if (pid > 0x1ffe && pid != 0x2000)
-               return -1;
-
-       // check if the pid is already present
-       for (i = 0; i < adapter->pid_count; i++)
-               if (adapter->pid_list[i] == pid) {
-                       adapter->pid_rc[i]++;   // increment ref counter
-               return 1;
-               }
-
-       if (adapter->pid_count == N_PID_SLOTS)
-               return -1;      // no more pids can be added
-       adapter->pid_list[adapter->pid_count] = pid;    // register pid
-       adapter->pid_rc[adapter->pid_count] = 1;
-       adapter->pid_count++;
-       // hardware setting
-       add_hw_pid(adapter, pid);
-
-                       return 1;
-               }
-
-/* Removes a PID from the filters. */
-static int remove_pid(struct adapter *adapter, u16 pid)
-{
-       int i;
-
-       dprintk("%s: pid=%d\n", __FUNCTION__, pid);
-
-       if (pid > 0x1ffe && pid != 0x2000)
-               return -1;
-
-       // check if the pid is present (it must be!)
-       for (i = 0; i < adapter->pid_count; i++) {
-               if (adapter->pid_list[i] == pid) {
-                       adapter->pid_rc[i]--;
-                       if (adapter->pid_rc[i] <= 0) {
-                               // remove from the list
-                               adapter->pid_count--;
-                               adapter->pid_list[i]=adapter->pid_list[adapter->pid_count];
-                               adapter->pid_rc[i] = adapter->pid_rc[adapter->pid_count];
-                               // hardware setting
-                               remove_hw_pid(adapter, pid);
-                       }
-                       return 1;
-               }
-       }
-
-       return -1;
-}
-
-
-/* dma & irq */
-static void ctrl_enable_smc(struct adapter *adapter, u32 op)
-{
-       write_reg_bitfield(adapter, 0x208, 0x00000800, op ? 0x00000800 : 0);
-}
-
-static void dma_enable_disable_irq(struct adapter *adapter, u32 flag1, u32 flag2, u32 flag3)
-{
-       adapter->dma_ctrl = adapter->dma_ctrl & 0x000f0000;
-
-       if (flag1 == 0) {
-               if (flag2 == 0)
-                       adapter->dma_ctrl = adapter->dma_ctrl & ~0x00010000;
-               else
-                       adapter->dma_ctrl = adapter->dma_ctrl | 0x00010000;
-
-               if (flag3 == 0)
-                       adapter->dma_ctrl = adapter->dma_ctrl & ~0x00020000;
-               else
-                       adapter->dma_ctrl = adapter->dma_ctrl | 0x00020000;
-
-       } else {
-
-               if (flag2 == 0)
-                       adapter->dma_ctrl = adapter->dma_ctrl & ~0x00040000;
-               else
-                       adapter->dma_ctrl = adapter->dma_ctrl | 0x00040000;
-
-               if (flag3 == 0)
-                       adapter->dma_ctrl = adapter->dma_ctrl & ~0x00080000;
-               else
-                       adapter->dma_ctrl = adapter->dma_ctrl | 0x00080000;
-       }
-}
-
-static void irq_dma_enable_disable_irq(struct adapter *adapter, u32 op)
-{
-       u32 value;
-
-       value = read_reg_dw(adapter, 0x208) & 0xfff0ffff;
-
-       if (op != 0)
-               value = value | (adapter->dma_ctrl & 0x000f0000);
-
-       write_reg_dw(adapter, 0x208, value);
-}
-
-/* FlexCopII has 2 dma channels. DMA1 is used to transfer TS data to
-   system memory.
-
-   The DMA1 buffer is divided in 2 subbuffers of equal size.
-   FlexCopII will transfer TS data to one subbuffer, signal an interrupt
-   when the subbuffer is full and continue fillig the second subbuffer.
-
-   For DMA1:
-       subbuffer size in 32-bit words is stored in the first 24 bits of
-       register 0x004. The last 8 bits of register 0x004 contain the number
-       of subbuffers.
-       
-       the first 30 bits of register 0x000 contain the address of the first
-       subbuffer. The last 2 bits contain 0, when dma1 is disabled and 1,
-       when dma1 is enabled.
-
-       the first 30 bits of register 0x00c contain the address of the second
-       subbuffer. the last 2 bits contain 1.
-
-       register 0x008 will contain the address of the subbuffer that was filled
-       with TS data, when FlexCopII will generate an interrupt.
-
-   For DMA2:
-       subbuffer size in 32-bit words is stored in the first 24 bits of
-       register 0x014. The last 8 bits of register 0x014 contain the number
-       of subbuffers.
-       
-       the first 30 bits of register 0x010 contain the address of the first
-       subbuffer.  The last 2 bits contain 0, when dma1 is disabled and 1,
-       when dma1 is enabled.
-
-       the first 30 bits of register 0x01c contain the address of the second
-       subbuffer. the last 2 bits contain 1.
-
-       register 0x018 contains the address of the subbuffer that was filled
-       with TS data, when FlexCopII generates an interrupt.
-*/
-static int dma_init_dma(struct adapter *adapter, u32 dma_channel)
-{
-       u32 subbuffers, subbufsize, subbuf0, subbuf1;
-
-       if (dma_channel == 0) {
-               dprintk("%s: Initializing DMA1 channel\n", __FUNCTION__);
-
-               subbuffers = 2;
-
-               subbufsize = (((adapter->dmaq1.buffer_size / 2) / 4) << 8) | subbuffers;
-
-               subbuf0 = adapter->dmaq1.bus_addr & 0xfffffffc;
-
-               subbuf1 = ((adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) & 0xfffffffc) | 1;
-
-               dprintk("%s: first subbuffer address = 0x%x\n", __FUNCTION__, subbuf0);
-               udelay(1000);
-               write_reg_dw(adapter, 0x000, subbuf0);
-
-               dprintk("%s: subbuffer size = 0x%x\n", __FUNCTION__, (subbufsize >> 8) * 4);
-               udelay(1000);
-               write_reg_dw(adapter, 0x004, subbufsize);
-
-               dprintk("%s: second subbuffer address = 0x%x\n", __FUNCTION__, subbuf1);
-               udelay(1000);
-               write_reg_dw(adapter, 0x00c, subbuf1);
-
-               dprintk("%s: counter = 0x%x\n", __FUNCTION__, adapter->dmaq1.bus_addr & 0xfffffffc);
-               write_reg_dw(adapter, 0x008, adapter->dmaq1.bus_addr & 0xfffffffc);
-               udelay(1000);
-
-               dma_enable_disable_irq(adapter, 0, 1, subbuffers ? 1 : 0);
-
-               irq_dma_enable_disable_irq(adapter, 1);
-
-               sram_set_media_dest(adapter, 1);
-               sram_set_net_dest(adapter, 1);
-               sram_set_cai_dest(adapter, 2);
-               sram_set_cao_dest(adapter, 2);
-       }
-
-       if (dma_channel == 1) {
-               dprintk("%s: Initializing DMA2 channel\n", __FUNCTION__);
-
-               subbuffers = 2;
-
-               subbufsize = (((adapter->dmaq2.buffer_size / 2) / 4) << 8) | subbuffers;
-
-               subbuf0 = adapter->dmaq2.bus_addr & 0xfffffffc;
-
-               subbuf1 = ((adapter->dmaq2.bus_addr + adapter->dmaq2.buffer_size / 2) & 0xfffffffc) | 1;
-
-               dprintk("%s: first subbuffer address = 0x%x\n", __FUNCTION__, subbuf0);
-               udelay(1000);
-               write_reg_dw(adapter, 0x010, subbuf0);
-
-               dprintk("%s: subbuffer size = 0x%x\n", __FUNCTION__, (subbufsize >> 8) * 4);
-               udelay(1000);
-               write_reg_dw(adapter, 0x014, subbufsize);
-
-               dprintk("%s: second buffer address = 0x%x\n", __FUNCTION__, subbuf1);
-               udelay(1000);
-               write_reg_dw(adapter, 0x01c, subbuf1);
-
-               sram_set_cai_dest(adapter, 2);
-       }
-
-       return 0;
-}
-
-static void ctrl_enable_receive_data(struct adapter *adapter, u32 op)
-{
-       if (op == 0) {
-               write_reg_bitfield(adapter, 0x208, 0x00008000, 0);
-               adapter->dma_status = adapter->dma_status & ~0x00000004;
-       } else {
-               write_reg_bitfield(adapter, 0x208, 0x00008000, 0x00008000);
-               adapter->dma_status = adapter->dma_status | 0x00000004;
-       }
-}
-
-/* bit 0 of dma_mask is set to 1 if dma1 channel has to be enabled/disabled
-   bit 1 of dma_mask is set to 1 if dma2 channel has to be enabled/disabled
-*/
-static void dma_start_stop(struct adapter *adapter, u32 dma_mask, int start_stop)
-{
-       u32 dma_enable, dma1_enable, dma2_enable;
-
-       dprintk("%s: dma_mask=%x\n", __FUNCTION__, dma_mask);
-
-       if (start_stop == 1) {
-               dprintk("%s: starting dma\n", __FUNCTION__);
-
-               dma1_enable = 0;
-               dma2_enable = 0;
-
-               if (((dma_mask & 1) != 0) && ((adapter->dma_status & 1) == 0) && (adapter->dmaq1.bus_addr != 0)) {
-                       adapter->dma_status = adapter->dma_status | 1;
-                       dma1_enable = 1;
-               }
-
-               if (((dma_mask & 2) != 0) && ((adapter->dma_status & 2) == 0) && (adapter->dmaq2.bus_addr != 0)) {
-                       adapter->dma_status = adapter->dma_status | 2;
-                       dma2_enable = 1;
-               }
-               // enable dma1 and dma2
-               if ((dma1_enable == 1) && (dma2_enable == 1)) {
-                       write_reg_dw(adapter, 0x000, adapter->dmaq1.bus_addr | 1);
-                       write_reg_dw(adapter, 0x00c, (adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) | 1);
-                       write_reg_dw(adapter, 0x010, adapter->dmaq2.bus_addr | 1);
-
-                       ctrl_enable_receive_data(adapter, 1);
-
-                       return;
-               }
-               // enable dma1
-               if ((dma1_enable == 1) && (dma2_enable == 0)) {
-                       write_reg_dw(adapter, 0x000, adapter->dmaq1.bus_addr | 1);
-                       write_reg_dw(adapter, 0x00c, (adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) | 1);
-
-                       ctrl_enable_receive_data(adapter, 1);
-
-                       return;
-               }
-               // enable dma2
-               if ((dma1_enable == 0) && (dma2_enable == 1)) {
-                       write_reg_dw(adapter, 0x010, adapter->dmaq2.bus_addr | 1);
-
-                       ctrl_enable_receive_data(adapter, 1);
-
-                       return;
-               }
-               // start dma
-               if ((dma1_enable == 0) && (dma2_enable == 0)) {
-                       ctrl_enable_receive_data(adapter, 1);
-
-                       return;
-               }
-
-       } else {
-
-               dprintk("%s: stopping dma\n", __FUNCTION__);
-
-               dma_enable = adapter->dma_status & 0x00000003;
-
-               if (((dma_mask & 1) != 0) && ((adapter->dma_status & 1) != 0)) {
-                       dma_enable = dma_enable & 0xfffffffe;
-               }
-
-               if (((dma_mask & 2) != 0) && ((adapter->dma_status & 2) != 0)) {
-                       dma_enable = dma_enable & 0xfffffffd;
-               }
-               //stop dma
-               if ((dma_enable == 0) && ((adapter->dma_status & 4) != 0)) {
-                       ctrl_enable_receive_data(adapter, 0);
-
-                       udelay(3000);
-               }
-               //disable dma1
-               if (((dma_mask & 1) != 0) && ((adapter->dma_status & 1) != 0) && (adapter->dmaq1.bus_addr != 0)) {
-                       write_reg_dw(adapter, 0x000, adapter->dmaq1.bus_addr);
-                       write_reg_dw(adapter, 0x00c, (adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) | 1);
-
-                       adapter->dma_status = adapter->dma_status & ~0x00000001;
-               }
-               //disable dma2
-               if (((dma_mask & 2) != 0) && ((adapter->dma_status & 2) != 0) && (adapter->dmaq2.bus_addr != 0)) {
-                       write_reg_dw(adapter, 0x010, adapter->dmaq2.bus_addr);
-
-                       adapter->dma_status = adapter->dma_status & ~0x00000002;
-               }
-       }
-}
-
-static void open_stream(struct adapter *adapter, u16 pid)
-{
-       u32 dma_mask;
-
-       ++adapter->capturing;
-
-       filter_enable_mask_filter(adapter, 1);
-
-       add_pid(adapter, pid);
-
-       dprintk("%s: adapter->dma_status=%x\n", __FUNCTION__, adapter->dma_status);
-
-       if ((adapter->dma_status & 7) != 7) {
-               dma_mask = 0;
-
-               if (((adapter->dma_status & 0x10000000) != 0) && ((adapter->dma_status & 1) == 0)) {
-                       dma_mask = dma_mask | 1;
-
-                       adapter->dmaq1.head = 0;
-                       adapter->dmaq1.tail = 0;
-
-                       memset(adapter->dmaq1.buffer, 0, adapter->dmaq1.buffer_size);
-               }
-
-               if (((adapter->dma_status & 0x20000000) != 0) && ((adapter->dma_status & 2) == 0)) {
-                       dma_mask = dma_mask | 2;
-
-                       adapter->dmaq2.head = 0;
-                       adapter->dmaq2.tail = 0;
-               }
-
-               if (dma_mask != 0) {
-                       irq_dma_enable_disable_irq(adapter, 1);
-
-                       dma_start_stop(adapter, dma_mask, 1);
-               }
-       }
-}
-
-static void close_stream(struct adapter *adapter, u16 pid)
-{
-       if (adapter->capturing > 0)
-               --adapter->capturing;
-
-       dprintk("%s: dma_status=%x\n", __FUNCTION__, adapter->dma_status);
-
-       if (adapter->capturing == 0) {
-               u32 dma_mask = 0;
-
-       if ((adapter->dma_status & 1) != 0)
-               dma_mask = dma_mask | 0x00000001;
-       if ((adapter->dma_status & 2) != 0)
-               dma_mask = dma_mask | 0x00000002;
-
-       if (dma_mask != 0) {
-                       dma_start_stop(adapter, dma_mask, 0);
-       }
-       }
-       remove_pid(adapter, pid);
-}
-
-static void interrupt_service_dma1(struct adapter *adapter)
-{
-       struct dvb_demux *dvbdmx = &adapter->demux;
-
-       int n_cur_dma_counter;
-       u32 n_num_bytes_parsed;
-       u32 n_num_new_bytes_transferred;
-       u32 dw_default_packet_size = 188;
-       u8 gb_tmp_buffer[188];
-       u8 *pb_dma_buf_cur_pos;
-
-       n_cur_dma_counter = readl(adapter->io_mem + 0x008) - adapter->dmaq1.bus_addr;
-       n_cur_dma_counter = (n_cur_dma_counter / dw_default_packet_size) * dw_default_packet_size;
-
-       if ((n_cur_dma_counter < 0) || (n_cur_dma_counter > adapter->dmaq1.buffer_size)) {
-               dprintk("%s: dma counter outside dma buffer\n", __FUNCTION__);
-               return;
-       }
-
-       adapter->dmaq1.head = n_cur_dma_counter;
-
-       if (adapter->dmaq1.tail <= n_cur_dma_counter) {
-               n_num_new_bytes_transferred = n_cur_dma_counter - adapter->dmaq1.tail;
-
-       } else {
-
-               n_num_new_bytes_transferred = (adapter->dmaq1.buffer_size - adapter->dmaq1.tail) + n_cur_dma_counter;
-       }
-
-       ddprintk("%s: n_cur_dma_counter = %d\n", __FUNCTION__, n_cur_dma_counter);
-       ddprintk("%s: dmaq1.tail        = %d\n", __FUNCTION__, adapter->dmaq1.tail);
-       ddprintk("%s: bytes_transferred = %d\n", __FUNCTION__, n_num_new_bytes_transferred);
-
-       if (n_num_new_bytes_transferred < dw_default_packet_size)
-               return;
-
-       n_num_bytes_parsed = 0;
-
-       while (n_num_bytes_parsed < n_num_new_bytes_transferred) {
-               pb_dma_buf_cur_pos = adapter->dmaq1.buffer + adapter->dmaq1.tail;
-
-               if (adapter->dmaq1.buffer + adapter->dmaq1.buffer_size < adapter->dmaq1.buffer + adapter->dmaq1.tail + 188) {
-                       memcpy(gb_tmp_buffer, adapter->dmaq1.buffer + adapter->dmaq1.tail,
-                              adapter->dmaq1.buffer_size - adapter->dmaq1.tail);
-                       memcpy(gb_tmp_buffer + (adapter->dmaq1.buffer_size - adapter->dmaq1.tail), adapter->dmaq1.buffer,
-                              (188 - (adapter->dmaq1.buffer_size - adapter->dmaq1.tail)));
-
-                       pb_dma_buf_cur_pos = gb_tmp_buffer;
-               }
-
-               if (adapter->capturing != 0) {
-                       dvb_dmx_swfilter_packets(dvbdmx, pb_dma_buf_cur_pos, dw_default_packet_size / 188);
-               }
-
-               n_num_bytes_parsed = n_num_bytes_parsed + dw_default_packet_size;
-
-               adapter->dmaq1.tail = adapter->dmaq1.tail + dw_default_packet_size;
-
-               if (adapter->dmaq1.tail >= adapter->dmaq1.buffer_size)
-                       adapter->dmaq1.tail = adapter->dmaq1.tail - adapter->dmaq1.buffer_size;
-       };
-}
-
-static void interrupt_service_dma2(struct adapter *adapter)
-{
-       printk("%s:\n", __FUNCTION__);
-}
-
-static irqreturn_t isr(int irq, void *dev_id, struct pt_regs *regs)
-{
-       struct adapter *tmp = dev_id;
-
-       u32 value;
-
-       ddprintk("%s:\n", __FUNCTION__);
-
-       spin_lock_irq(&tmp->lock);
-
-       if (0 == ((value = read_reg_dw(tmp, 0x20c)) & 0x0f)) {
-               spin_unlock_irq(&tmp->lock);
-               return IRQ_NONE;
-       }
-       
-       while (value != 0) {
-               if ((value & 0x03) != 0)
-                       interrupt_service_dma1(tmp);
-               if ((value & 0x0c) != 0)
-                       interrupt_service_dma2(tmp);
-               value = read_reg_dw(tmp, 0x20c) & 0x0f;
-       }
-
-       spin_unlock_irq(&tmp->lock);
-       return IRQ_HANDLED;
-}
-
-static int init_dma_queue_one(struct adapter *adapter, struct dmaq *dmaq,
-                             int size, int dmaq_offset)
-{
-       struct pci_dev *pdev = adapter->pdev;
-       dma_addr_t dma_addr;
-
-       dmaq->head = 0;
-       dmaq->tail = 0;
-
-       dmaq->buffer = pci_alloc_consistent(pdev, size + 0x80, &dma_addr);
-       if (!dmaq->buffer)
-               return -ENOMEM;
-
-       dmaq->bus_addr = dma_addr;
-       dmaq->buffer_size = size;
-
-       dma_init_dma(adapter, dmaq_offset);
-
-       ddprintk("%s: allocated dma buffer at 0x%p, length=%d\n",
-                __FUNCTION__, dmaq->buffer, size);
-
-       return 0;
-       }
-
-static int init_dma_queue(struct adapter *adapter)
-{
-       struct {
-               struct dmaq *dmaq;
-               u32 dma_status;
-               int size;
-       } dmaq_desc[] = {
-               { &adapter->dmaq1, 0x10000000, SIZE_OF_BUF_DMA1 },
-               { &adapter->dmaq2, 0x20000000, SIZE_OF_BUF_DMA2 }
-       }, *p = dmaq_desc;
-       int i;
-
-       for (i = 0; i < 2; i++, p++) {
-               if (init_dma_queue_one(adapter, p->dmaq, p->size, i) < 0)
-                       adapter->dma_status &= ~p->dma_status;
-               else
-                       adapter->dma_status |= p->dma_status;
-       }
-       return (adapter->dma_status & 0x30000000) ? 0 : -ENOMEM;
-}
-
-static void free_dma_queue_one(struct adapter *adapter, struct dmaq *dmaq)
-{
-       if (dmaq->buffer) {
-               pci_free_consistent(adapter->pdev, dmaq->buffer_size + 0x80,
-                                   dmaq->buffer, dmaq->bus_addr);
-               memset(dmaq, 0, sizeof(*dmaq));
-       }
-}
-
-static void free_dma_queue(struct adapter *adapter)
-{
-       struct dmaq *dmaq[] = {
-               &adapter->dmaq1,
-               &adapter->dmaq2,
-               NULL
-       }, **p;
-
-       for (p = dmaq; *p; p++)
-               free_dma_queue_one(adapter, *p);
-       }
-
-static void release_adapter(struct adapter *adapter)
-{
-       struct pci_dev *pdev = adapter->pdev;
-
-       iounmap(adapter->io_mem);
-       pci_disable_device(pdev);
-       pci_release_region(pdev, 0);
-       pci_release_region(pdev, 1);
-}
-
-static void free_adapter_object(struct adapter *adapter)
-{
-       dprintk("%s:\n", __FUNCTION__);
-
-       close_stream(adapter, 0);
-               free_irq(adapter->irq, adapter);
-       free_dma_queue(adapter);
-       release_adapter(adapter);
-       kfree(adapter);
-}
-
-static struct pci_driver skystar2_pci_driver;
-
-static int claim_adapter(struct adapter *adapter)
-{
-       struct pci_dev *pdev = adapter->pdev;
-       u16 var;
-       int ret;
-
-       ret = pci_request_region(pdev, 1, skystar2_pci_driver.name);
-       if (ret < 0)
-               goto out;
-
-       ret = pci_request_region(pdev, 0, skystar2_pci_driver.name);
-       if (ret < 0)
-               goto err_pci_release_1;
-
-       pci_read_config_byte(pdev, PCI_CLASS_REVISION, &adapter->card_revision);
-
-       dprintk("%s: card revision %x \n", __FUNCTION__, adapter->card_revision);
-
-       ret = pci_enable_device(pdev);
-       if (ret < 0)
-               goto err_pci_release_0;
-
-       pci_read_config_word(pdev, 4, &var);
-
-       if ((var & 4) == 0)
-               pci_set_master(pdev);
-
-       adapter->io_port = pdev->resource[1].start;
-
-       adapter->io_mem = ioremap(pdev->resource[0].start, 0x800);
-
-       if (!adapter->io_mem) {
-               dprintk("%s: can not map io memory\n", __FUNCTION__);
-               ret = -EIO;
-               goto err_pci_disable;
-       }
-
-       dprintk("%s: io memory maped at %p\n", __FUNCTION__, adapter->io_mem);
-
-       ret = 1;
-out:
-       return ret;
-
-err_pci_disable:
-       pci_disable_device(pdev);
-err_pci_release_0:
-       pci_release_region(pdev, 0);
-err_pci_release_1:
-       pci_release_region(pdev, 1);
-       goto out;
-}
-
-/*
-static int sll_reset_flexcop(struct adapter *adapter)
-{
-       write_reg_dw(adapter, 0x208, 0);
-       write_reg_dw(adapter, 0x210, 0xb2ff);
-
-       return 0;
-}
-*/
-
-static void decide_how_many_hw_filters(struct adapter *adapter)
-{
-       int hw_filters;
-       int mod_option_hw_filters;
-
-       // FlexCop IIb & III have 6+32 hw filters    
-       // FlexCop II has 6 hw filters, every other should have at least 6
-       switch (adapter->b2c2_revision) {
-       case 0x82:              /* II */
-               hw_filters = 6;
-               break;
-       case 0xc3:              /* IIB */
-               hw_filters = 6 + 32;
-               break;
-       case 0xc0:              /* III */
-               hw_filters = 6 + 32;
-               break;
-       default:
-               hw_filters = 6;
-               break;
-       }
-       printk("%s: the chip has %i hardware filters", __FILE__, hw_filters);
-
-       mod_option_hw_filters = 0;
-       if (enable_hw_filters >= 1)
-               mod_option_hw_filters += 6;
-       if (enable_hw_filters >= 2)
-               mod_option_hw_filters += 32;
-
-       if (mod_option_hw_filters >= hw_filters) {
-               adapter->useable_hw_filters = hw_filters;
-       } else {
-               adapter->useable_hw_filters = mod_option_hw_filters;
-               printk(", but only %d will be used because of module option", mod_option_hw_filters);
-       }
-       printk("\n");
-       dprintk("%s: useable_hardware_filters set to %i\n", __FILE__, adapter->useable_hw_filters);
-}
-
-static int driver_initialize(struct pci_dev *pdev)
-{
-       struct adapter *adapter;
-       u32 tmp;
-       int ret = -ENOMEM;
-
-       adapter = kmalloc(sizeof(struct adapter), GFP_KERNEL);
-       if (!adapter) {
-               dprintk("%s: out of memory!\n", __FUNCTION__);
-               goto out;
-       }
-
-       memset(adapter, 0, sizeof(struct adapter));
-
-       pci_set_drvdata(pdev,adapter);
-
-       adapter->pdev = pdev;
-       adapter->irq = pdev->irq;
-
-       ret = claim_adapter(adapter);
-       if (ret < 0)
-               goto err_kfree;
-
-       irq_dma_enable_disable_irq(adapter, 0);
-
-       ret = request_irq(pdev->irq, isr, 0x4000000, "Skystar2", adapter);
-       if (ret < 0) {
-               dprintk("%s: unable to allocate irq=%d !\n", __FUNCTION__, pdev->irq);
-               goto err_release_adapter;
-       }
-
-       read_reg_dw(adapter, 0x208);
-       write_reg_dw(adapter, 0x208, 0);
-       write_reg_dw(adapter, 0x210, 0xb2ff);
-       write_reg_dw(adapter, 0x208, 0x40);
-
-       ret = init_dma_queue(adapter);
-       if (ret < 0)
-               goto err_free_irq;
-
-       adapter->b2c2_revision = (read_reg_dw(adapter, 0x204) >> 0x18);
-
-       switch (adapter->b2c2_revision) {
-       case 0x82:
-               printk("%s: FlexCopII(rev.130) chip found\n", __FILE__);
-               break;
-       case 0xc3:
-               printk("%s: FlexCopIIB(rev.195) chip found\n", __FILE__);
-               break;
-       case 0xc0:
-               printk("%s: FlexCopIII(rev.192) chip found\n", __FILE__);
-               break;
-       default:
-               printk("%s: The revision of the FlexCop chip on your card is %d\n", __FILE__, adapter->b2c2_revision);
-               printk("%s: This driver works only with FlexCopII(rev.130), FlexCopIIB(rev.195) and FlexCopIII(rev.192).\n", __FILE__);
-               ret = -ENODEV;
-               goto err_free_dma_queue;
-               }
-
-       decide_how_many_hw_filters(adapter);
-
-       init_pids(adapter);
-
-       tmp = read_reg_dw(adapter, 0x204);
-
-       write_reg_dw(adapter, 0x204, 0);
-       mdelay(20);
-
-       write_reg_dw(adapter, 0x204, tmp);
-       mdelay(10);
-
-       tmp = read_reg_dw(adapter, 0x308);
-       write_reg_dw(adapter, 0x308, 0x4000 | tmp);
-
-       adapter->dw_sram_type = 0x10000;
-
-       sll_detect_sram_size(adapter);
-
-       dprintk("%s sram length = %d, sram type= %x\n", __FUNCTION__, sram_length(adapter), adapter->dw_sram_type);
-
-       sram_set_media_dest(adapter, 1);
-       sram_set_net_dest(adapter, 1);
-
-       ctrl_enable_smc(adapter, 0);
-
-       sram_set_cai_dest(adapter, 2);
-       sram_set_cao_dest(adapter, 2);
-
-       dma_enable_disable_irq(adapter, 1, 0, 0);
-
-       if (eeprom_get_mac_addr(adapter, 0, adapter->mac_addr) != 0) {
-               printk("%s MAC address = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x \n", __FUNCTION__, adapter->mac_addr[0],
-                      adapter->mac_addr[1], adapter->mac_addr[2], adapter->mac_addr[3], adapter->mac_addr[4], adapter->mac_addr[5],
-                      adapter->mac_addr[6], adapter->mac_addr[7]
-                   );
-
-               ca_set_mac_dst_addr_filter(adapter, adapter->mac_addr);
-               ctrl_enable_mac(adapter, 1);
-       }
-
-       spin_lock_init(&adapter->lock);
-
-out:
-       return ret;
-
-err_free_dma_queue:
-       free_dma_queue(adapter);
-err_free_irq:
-       free_irq(pdev->irq, adapter);
-err_release_adapter:
-       release_adapter(adapter);
-err_kfree:
-       pci_set_drvdata(pdev, NULL);
-       kfree(adapter);
-       goto out;
-}
-
-static void driver_halt(struct pci_dev *pdev)
-{
-       struct adapter *adapter = pci_get_drvdata(pdev);
-
-       irq_dma_enable_disable_irq(adapter, 0);
-
-       ctrl_enable_receive_data(adapter, 0);
-
-       free_adapter_object(adapter);
-
-       pci_set_drvdata(pdev, NULL);
-}
-
-static int dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-       struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-       struct adapter *adapter = (struct adapter *) dvbdmx->priv;
-
-       dprintk("%s: PID=%d, type=%d\n", __FUNCTION__, dvbdmxfeed->pid, dvbdmxfeed->type);
-
-       open_stream(adapter, dvbdmxfeed->pid);
-
-       return 0;
-}
-
-static int dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-       struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-       struct adapter *adapter = (struct adapter *) dvbdmx->priv;
-
-       dprintk("%s: PID=%d, type=%d\n", __FUNCTION__, dvbdmxfeed->pid, dvbdmxfeed->type);
-
-       close_stream(adapter, dvbdmxfeed->pid);
-
-       return 0;
-}
-
-/* lnb control */
-static void set_tuner_tone(struct adapter *adapter, u8 tone)
-{
-       u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc };
-       u16 ax;
-
-       dprintk("%s: %u\n", __FUNCTION__, tone);
-
-       switch (tone) {
-       case 1:
-               ax = wz_half_period_for_45_mhz[0];
-               break;
-       case 2:
-               ax = wz_half_period_for_45_mhz[1];
-               break;
-       case 3:
-               ax = wz_half_period_for_45_mhz[2];
-               break;
-       case 4:
-               ax = wz_half_period_for_45_mhz[3];
-               break;
-
-       default:
-               ax = 0;
-       }
-
-       if (ax != 0) {
-               write_reg_dw(adapter, 0x200, ((ax << 0x0f) + (ax & 0x7fff)) | 0x40000000);
-
-       } else {
-
-               write_reg_dw(adapter, 0x200, 0x40ff8000);
-       }
-}
-
-static void set_tuner_polarity(struct adapter *adapter, u8 polarity)
-{
-       u32 var;
-
-       dprintk("%s : polarity = %u \n", __FUNCTION__, polarity);
-
-       var = read_reg_dw(adapter, 0x204);
-
-       if (polarity == 0) {
-               dprintk("%s: LNB power off\n", __FUNCTION__);
-               var = var | 1;
-       };
-
-       if (polarity == 1) {
-               var = var & ~1;
-               var = var & ~4;
-       };
-
-       if (polarity == 2) {
-               var = var & ~1;
-               var = var | 4;
-       }
-
-       write_reg_dw(adapter, 0x204, var);
-}
-
-static void diseqc_send_bit(struct adapter *adapter, int data)
-{
-       set_tuner_tone(adapter, 1);
-       udelay(data ? 500 : 1000);
-       set_tuner_tone(adapter, 0);
-       udelay(data ? 1000 : 500);
-}
-
-
-static void diseqc_send_byte(struct adapter *adapter, int data)
-               {
-       int i, par = 1, d;
-
-       for (i = 7; i >= 0; i--) {
-               d = (data >> i) & 1;
-               par ^= d;
-               diseqc_send_bit(adapter, d);
-       }
-
-       diseqc_send_bit(adapter, par);
-               }
-
-
-static int send_diseqc_msg(struct adapter *adapter, int len, u8 *msg, unsigned long burst)
-{
-       int i;
-
-       set_tuner_tone(adapter, 0);
-       mdelay(16);
-
-       for (i = 0; i < len; i++)
-               diseqc_send_byte(adapter, msg[i]);
-
-       mdelay(16);
-
-       if (burst != -1) {
-               if (burst)
-                       diseqc_send_byte(adapter, 0xff);
-               else {
-                       set_tuner_tone(adapter, 1);
-                       udelay(12500);
-                       set_tuner_tone(adapter, 0);
-               }
-               msleep(20);
-       }
-
-       return 0;
-}
-
-static int flexcop_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
-       struct adapter* adapter = (struct adapter*) fe->dvb->priv;
-
-       switch(tone) {
-               case SEC_TONE_ON:
-                       set_tuner_tone(adapter, 1);
-                       break;
-               case SEC_TONE_OFF:
-                       set_tuner_tone(adapter, 0);
-                               break;
-                       default:
-                               return -EINVAL;
-                       };
-
-       return 0;
-}
-
-static int flexcop_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
-               {
-       struct adapter* adapter = (struct adapter*) fe->dvb->priv;
-
-                       send_diseqc_msg(adapter, cmd->msg_len, cmd->msg, 0);
-
-       return 0;
-               }
-
-static int flexcop_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
-{
-       struct adapter* adapter = (struct adapter*) fe->dvb->priv;
-
-       send_diseqc_msg(adapter, 0, NULL, minicmd);
-
-       return 0;
-}
-
-static int flexcop_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-               {
-       struct adapter* adapter = (struct adapter*) fe->dvb->priv;
-
-       dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__);
-
-       switch (voltage) {
-       case SEC_VOLTAGE_13:
-               dprintk("%s: SEC_VOLTAGE_13, %x\n", __FUNCTION__, SEC_VOLTAGE_13);
-               set_tuner_polarity(adapter, 1);
-               return 0;
-
-       case SEC_VOLTAGE_18:
-               dprintk("%s: SEC_VOLTAGE_18, %x\n", __FUNCTION__, SEC_VOLTAGE_18);
-               set_tuner_polarity(adapter, 2);
-                       return 0;
-
-       default:
-               return -EINVAL;
-       }
-       }
-
-static int flexcop_sleep(struct dvb_frontend* fe)
-               {
-       struct adapter* adapter = (struct adapter*) fe->dvb->priv;
-
-       dprintk("%s: FE_SLEEP\n", __FUNCTION__);
-                       set_tuner_polarity(adapter, 0);
-
-       if (adapter->fe_sleep) return adapter->fe_sleep(fe);
-       return 0;
-               }
-
-static u32 flexcop_i2c_func(struct i2c_adapter *adapter)
-               {
-       printk("flexcop_i2c_func\n");
-
-       return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm    flexcop_algo = {
-       .name           = "flexcop i2c algorithm",
-       .id             = I2C_ALGO_BIT,
-       .master_xfer    = master_xfer,
-       .functionality  = flexcop_i2c_func,
-};
-
-
-
-
-static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
-{
-       u8 aclk = 0;
-       u8 bclk = 0;
-
-       if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
-       else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
-       else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
-       else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
-       else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
-       else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
-
-       stv0299_writereg (fe, 0x13, aclk);
-       stv0299_writereg (fe, 0x14, bclk);
-       stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff);
-       stv0299_writereg (fe, 0x20, (ratio >>  8) & 0xff);
-       stv0299_writereg (fe, 0x21, (ratio      ) & 0xf0);
-
-       return 0;
-}
-
-static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
-{
-       u8 buf[4];
-       u32 div;
-       struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
-       struct adapter* adapter = (struct adapter*) fe->dvb->priv;
-
-       div = params->frequency / 125;
-
-       buf[0] = (div >> 8) & 0x7f;
-       buf[1] = div & 0xff;
-       buf[2] = 0x84;  // 0xC4
-       buf[3] = 0x08;
-
-       if (params->frequency < 1500000) buf[3] |= 0x10;
-
-       if (i2c_transfer (&adapter->i2c_adap, &msg, 1) != 1) return -EIO;
-       return 0;
-}
-
-static u8 samsung_tbmu24112_inittab[] = {
-            0x01, 0x15,
-            0x02, 0x30,
-            0x03, 0x00,
-            0x04, 0x7D,
-            0x05, 0x35,
-            0x06, 0x02,
-            0x07, 0x00,
-            0x08, 0xC3,
-            0x0C, 0x00,
-            0x0D, 0x81,
-            0x0E, 0x23,
-            0x0F, 0x12,
-            0x10, 0x7E,
-            0x11, 0x84,
-            0x12, 0xB9,
-            0x13, 0x88,
-            0x14, 0x89,
-            0x15, 0xC9,
-            0x16, 0x00,
-            0x17, 0x5C,
-            0x18, 0x00,
-            0x19, 0x00,
-            0x1A, 0x00,
-            0x1C, 0x00,
-            0x1D, 0x00,
-            0x1E, 0x00,
-            0x1F, 0x3A,
-            0x20, 0x2E,
-            0x21, 0x80,
-            0x22, 0xFF,
-            0x23, 0xC1,
-            0x28, 0x00,
-            0x29, 0x1E,
-            0x2A, 0x14,
-            0x2B, 0x0F,
-            0x2C, 0x09,
-            0x2D, 0x05,
-            0x31, 0x1F,
-            0x32, 0x19,
-            0x33, 0xFE,
-            0x34, 0x93,
-            0xff, 0xff,
-                       };
-
-static struct stv0299_config samsung_tbmu24112_config = {
-       .demod_address = 0x68,
-       .inittab = samsung_tbmu24112_inittab,
-       .mclk = 88000000UL,
-       .invert = 0,
-       .enhanced_tuning = 0,
-       .skip_reinit = 0,
-       .lock_output = STV0229_LOCKOUTPUT_LK,
-       .volt13_op0_op1 = STV0299_VOLT13_OP1,
-       .min_delay_ms = 100,
-       .set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
-       .pll_set = samsung_tbmu24112_pll_set,
-};
-
-
-
-static int nxt2002_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
-{
-       struct adapter* adapter = (struct adapter*) fe->dvb->priv;
-
-       return request_firmware(fw, name, &adapter->pdev->dev);
-}
-
-
-static struct nxt2002_config samsung_tbmv_config = {
-       .demod_address = 0x0A,
-       .request_firmware = nxt2002_request_firmware,
-};
-
-static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
-{
-       static u8 mt352_clock_config [] = { 0x89, 0x18, 0x2d };
-       static u8 mt352_reset [] = { 0x50, 0x80 };
-       static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
-       static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0xa1 };
-       static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
-
-       mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
-       udelay(2000);
-       mt352_write(fe, mt352_reset, sizeof(mt352_reset));
-       mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
-
-       mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
-       mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
-
-       return 0;
-}
-
-static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
-{
-       u32 div;
-       unsigned char bs = 0;
-
-       #define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
-       div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
-
-       if (params->frequency >= 48000000 && params->frequency <= 154000000) bs = 0x09;
-       if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a;
-       if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08;
-
-       pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address
-       pllbuf[1] = div >> 8;
-       pllbuf[2] = div & 0xff;
-       pllbuf[3] = 0xcc;
-       pllbuf[4] = bs;
-
-       return 0;
-}
-
-static struct mt352_config samsung_tdtc9251dh0_config = {
-
-       .demod_address = 0x0f,
-       .demod_init = samsung_tdtc9251dh0_demod_init,
-       .pll_set = samsung_tdtc9251dh0_pll_set,
-};
-
-static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
-{
-       u8 buf[4];
-       u32 div;
-       struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
-       struct adapter* adapter = (struct adapter*) fe->dvb->priv;
-
-       div = (params->frequency + (125/2)) / 125;
-
-       buf[0] = (div >> 8) & 0x7f;
-       buf[1] = (div >> 0) & 0xff;
-       buf[2] = 0x84 | ((div >> 10) & 0x60);
-       buf[3] = 0x80;
-
-       if (params->frequency < 1550000)
-               buf[3] |= 0x02;
-
-       if (i2c_transfer (&adapter->i2c_adap, &msg, 1) != 1) return -EIO;
-       return 0;
-}
-
-static struct mt312_config skystar23_samsung_tbdu18132_config = {
-
-       .demod_address = 0x0e,
-       .pll_set = skystar23_samsung_tbdu18132_pll_set,
-};
-
-
-
-
-static void frontend_init(struct adapter *skystar2)
-{
-       switch(skystar2->pdev->device) {
-       case 0x2103: // Technisat Skystar2 OR Technisat Airstar2 (DVB-T or ATSC)
-
-               // Attempt to load the Nextwave nxt2002 for ATSC support 
-               skystar2->fe = nxt2002_attach(&samsung_tbmv_config, &skystar2->i2c_adap);
-               if (skystar2->fe != NULL) {
-                       skystar2->fe_sleep = skystar2->fe->ops->sleep;
-                       skystar2->fe->ops->sleep = flexcop_sleep;
-                       break;
-               }
-
-               // try the skystar2 v2.6 first (stv0299/Samsung tbmu24112(sl1935))
-               skystar2->fe = stv0299_attach(&samsung_tbmu24112_config, &skystar2->i2c_adap);
-               if (skystar2->fe != NULL) {
-                       skystar2->fe->ops->set_voltage = flexcop_set_voltage;
-                       skystar2->fe_sleep = skystar2->fe->ops->sleep;
-                       skystar2->fe->ops->sleep = flexcop_sleep;
-                       break;
-}
-
-               // try the airstar2 (mt352/Samsung tdtc9251dh0(??))
-               skystar2->fe = mt352_attach(&samsung_tdtc9251dh0_config, &skystar2->i2c_adap);
-               if (skystar2->fe != NULL) {
-                       skystar2->fe->ops->info.frequency_min = 474000000;
-                       skystar2->fe->ops->info.frequency_max = 858000000;
-                       break;
-               }
-
-               // try the skystar2 v2.3 (vp310/Samsung tbdu18132(tsa5059))
-               skystar2->fe = vp310_attach(&skystar23_samsung_tbdu18132_config, &skystar2->i2c_adap);
-               if (skystar2->fe != NULL) {
-                       skystar2->fe->ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
-                       skystar2->fe->ops->diseqc_send_burst = flexcop_diseqc_send_burst;
-                       skystar2->fe->ops->set_tone = flexcop_set_tone;
-                       skystar2->fe->ops->set_voltage = flexcop_set_voltage;
-                       skystar2->fe_sleep = skystar2->fe->ops->sleep;
-                       skystar2->fe->ops->sleep = flexcop_sleep;
-                       break;
-               }
-               break;
-       }
-
-       if (skystar2->fe == NULL) {
-               printk("skystar2: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
-                      skystar2->pdev->vendor,
-                      skystar2->pdev->device,
-                      skystar2->pdev->subsystem_vendor,
-                      skystar2->pdev->subsystem_device);
-       } else {
-               if (dvb_register_frontend(&skystar2->dvb_adapter, skystar2->fe)) {
-                       printk("skystar2: Frontend registration failed!\n");
-                       if (skystar2->fe->ops->release)
-                               skystar2->fe->ops->release(skystar2->fe);
-                       skystar2->fe = NULL;
-               }
-       }
-}
-
-
-static int skystar2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       struct adapter *adapter;
-       struct dvb_adapter *dvb_adapter;
-       struct dvb_demux *dvbdemux;
-       struct dmx_demux *dmx;
-       int ret = -ENODEV;
-
-       if (!pdev)
-               goto out;
-
-       ret = driver_initialize(pdev);
-       if (ret < 0)
-               goto out;
-
-       adapter = pci_get_drvdata(pdev);
-       dvb_adapter = &adapter->dvb_adapter;
-
-       ret = dvb_register_adapter(dvb_adapter, skystar2_pci_driver.name,
-                                  THIS_MODULE);
-       if (ret < 0) {
-               printk("%s: Error registering DVB adapter\n", __FUNCTION__);
-               goto err_halt;
-       }
-
-       dvb_adapter->priv = adapter;
-
-
-       init_MUTEX(&adapter->i2c_sem);
-
-
-       memset(&adapter->i2c_adap, 0, sizeof(struct i2c_adapter));
-       strcpy(adapter->i2c_adap.name, "SkyStar2");
-
-       i2c_set_adapdata(&adapter->i2c_adap, adapter);
-
-#ifdef I2C_ADAP_CLASS_TV_DIGITAL
-       adapter->i2c_adap.class             = I2C_ADAP_CLASS_TV_DIGITAL;
-#else
-       adapter->i2c_adap.class             = I2C_CLASS_TV_DIGITAL;
-#endif
-       adapter->i2c_adap.algo              = &flexcop_algo;
-       adapter->i2c_adap.algo_data         = NULL;
-       adapter->i2c_adap.id                = I2C_ALGO_BIT;
-
-       ret = i2c_add_adapter(&adapter->i2c_adap);
-       if (ret < 0)
-               goto err_dvb_unregister;
-
-       dvbdemux = &adapter->demux;
-
-       dvbdemux->priv = adapter;
-       dvbdemux->filternum = N_PID_SLOTS;
-       dvbdemux->feednum = N_PID_SLOTS;
-       dvbdemux->start_feed = dvb_start_feed;
-       dvbdemux->stop_feed = dvb_stop_feed;
-       dvbdemux->write_to_decoder = NULL;
-       dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
-
-       ret = dvb_dmx_init(&adapter->demux);
-       if (ret < 0)
-               goto err_i2c_del;
-
-       dmx = &dvbdemux->dmx;
-
-       adapter->hw_frontend.source = DMX_FRONTEND_0;
-       adapter->dmxdev.filternum = N_PID_SLOTS;
-       adapter->dmxdev.demux = dmx;
-       adapter->dmxdev.capabilities = 0;
-
-       ret = dvb_dmxdev_init(&adapter->dmxdev, &adapter->dvb_adapter);
-       if (ret < 0)
-               goto err_dmx_release;
-
-       ret = dmx->add_frontend(dmx, &adapter->hw_frontend);
-       if (ret < 0)
-               goto err_dmxdev_release;
-
-       adapter->mem_frontend.source = DMX_MEMORY_FE;
-
-       ret = dmx->add_frontend(dmx, &adapter->mem_frontend);
-       if (ret < 0)
-               goto err_remove_hw_frontend;
-
-       ret = dmx->connect_frontend(dmx, &adapter->hw_frontend);
-       if (ret < 0)
-               goto err_remove_mem_frontend;
-
-       dvb_net_init(&adapter->dvb_adapter, &adapter->dvbnet, &dvbdemux->dmx);
-
-       frontend_init(adapter);
-out:
-       return ret;
-
-err_remove_mem_frontend:
-       dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &adapter->mem_frontend);
-err_remove_hw_frontend:
-       dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &adapter->hw_frontend);
-err_dmxdev_release:
-       dvb_dmxdev_release(&adapter->dmxdev);
-err_dmx_release:
-       dvb_dmx_release(&adapter->demux);
-err_i2c_del:
-       i2c_del_adapter(&adapter->i2c_adap);
-err_dvb_unregister:
-       dvb_unregister_adapter(&adapter->dvb_adapter);
-err_halt:
-       driver_halt(pdev);
-       goto out;
-}
-
-static void skystar2_remove(struct pci_dev *pdev)
-{
-       struct adapter *adapter = pci_get_drvdata(pdev);
-       struct dvb_demux *dvbdemux;
-       struct dmx_demux *dmx;
-
-       if (!adapter)
-               return;
-
-               dvb_net_release(&adapter->dvbnet);
-               dvbdemux = &adapter->demux;
-       dmx = &dvbdemux->dmx;
-
-       dmx->close(dmx);
-       dmx->remove_frontend(dmx, &adapter->hw_frontend);
-       dmx->remove_frontend(dmx, &adapter->mem_frontend);
-
-               dvb_dmxdev_release(&adapter->dmxdev);
-       dvb_dmx_release(dvbdemux);
-
-       if (adapter->fe != NULL)
-               dvb_unregister_frontend(adapter->fe);
-
-       dvb_unregister_adapter(&adapter->dvb_adapter);
-
-                       i2c_del_adapter(&adapter->i2c_adap);
-
-               driver_halt(pdev);
-       }
-
-static struct pci_device_id skystar2_pci_tbl[] = {
-       {0x000013d0, 0x00002103, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000},
-/*     {0x000013d0, 0x00002200, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000}, UNDEFINED HARDWARE - mail linuxtv.org list */     //FCIII
-       {0,},
-};
-
-MODULE_DEVICE_TABLE(pci, skystar2_pci_tbl);
-
-static struct pci_driver skystar2_pci_driver = {
-       .name = "SkyStar2",
-       .id_table = skystar2_pci_tbl,
-       .probe = skystar2_probe,
-       .remove = skystar2_remove,
-};
-
-static int skystar2_init(void)
-{
-       return pci_register_driver(&skystar2_pci_driver);
-}
-
-static void skystar2_cleanup(void)
-{
-       pci_unregister_driver(&skystar2_pci_driver);
-}
-
-module_init(skystar2_init);
-module_exit(skystar2_cleanup);
-
-MODULE_DESCRIPTION("Technisat SkyStar2 DVB PCI Driver");
-MODULE_LICENSE("GPL");
index 1339912c308b4a502e418ab0949b658d0583c26f..9bd12832e3d9a18fd7b2a480edd63eb25dce9c50 100644 (file)
@@ -258,10 +258,10 @@ int write_dst(struct dst_state *state, u8 *data, u8 len)
        if (debug && (verbose > 4)) {
                u8 i;
                if (verbose > 4) {
-                       dprintk("%s writing", __FUNCTION__);
+                       dprintk("%s writing [ ", __FUNCTION__);
                        for (i = 0; i < len; i++)
-                               dprintk(" %02x", data[i]);
-                       dprintk("\n");
+                               dprintk("%02x ", data[i]);
+                       dprintk("]\n");
                }
        }
        for (cnt = 0; cnt < 2; cnt++) {
@@ -320,10 +320,29 @@ int read_dst(struct dst_state *state, u8 * ret, u8 len)
 }
 EXPORT_SYMBOL(read_dst);
 
-static int dst_set_freq(struct dst_state *state, u32 freq)
+static int dst_set_polarization(struct dst_state *state)
 {
-       u8 *val;
+       switch (state->voltage) {
+               case SEC_VOLTAGE_13:    // vertical
+                       printk("%s: Polarization=[Vertical]\n", __FUNCTION__);
+                       state->tx_tuna[8] &= ~0x40;  //1
+                       break;
+
+               case SEC_VOLTAGE_18:    // horizontal
+                       printk("%s: Polarization=[Horizontal]\n", __FUNCTION__);
+                       state->tx_tuna[8] |= 0x40;  // 0
+                       break;
+
+               case SEC_VOLTAGE_OFF:
+
+                       break;
+       }
+
+       return 0;
+}
 
+static int dst_set_freq(struct dst_state *state, u32 freq)
+{
        state->frequency = freq;
        if (debug > 4)
                dprintk("%s: set Frequency %u\n", __FUNCTION__, freq);
@@ -332,46 +351,30 @@ static int dst_set_freq(struct dst_state *state, u32 freq)
                freq = freq / 1000;
                if (freq < 950 || freq > 2150)
                        return -EINVAL;
-               val = &state->tx_tuna[0];
-               val[2] = (freq >> 8) & 0x7f;
-               val[3] = (u8) freq;
-               val[4] = 1;
-               val[8] &= ~4;
-               if (freq < 1531)
-                       val[8] |= 4;
+
+               state->tx_tuna[2] = (freq >> 8);
+               state->tx_tuna[3] = (u8) freq;
+               state->tx_tuna[4] = 0x01;
+               state->tx_tuna[8] &= ~0x04;
+               if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
+                       if (freq < 1531)
+                               state->tx_tuna[8] |= 0x04;
+               }
+
        } else if (state->dst_type == DST_TYPE_IS_TERR) {
                freq = freq / 1000;
                if (freq < 137000 || freq > 858000)
                        return -EINVAL;
-               val = &state->tx_tuna[0];
-               val[2] = (freq >> 16) & 0xff;
-               val[3] = (freq >> 8) & 0xff;
-               val[4] = (u8) freq;
-               val[5] = 0;
-               switch (state->bandwidth) {
-               case BANDWIDTH_6_MHZ:
-                       val[6] = 6;
-                       break;
 
-               case BANDWIDTH_7_MHZ:
-               case BANDWIDTH_AUTO:
-                       val[6] = 7;
-                       break;
+               state->tx_tuna[2] = (freq >> 16) & 0xff;
+               state->tx_tuna[3] = (freq >> 8) & 0xff;
+               state->tx_tuna[4] = (u8) freq;
 
-               case BANDWIDTH_8_MHZ:
-                       val[6] = 8;
-                       break;
-               }
-
-               val[7] = 0;
-               val[8] = 0;
        } else if (state->dst_type == DST_TYPE_IS_CABLE) {
-               /* guess till will get one */
-               freq = freq / 1000;
-               val = &state->tx_tuna[0];
-               val[2] = (freq >> 16) & 0xff;
-               val[3] = (freq >> 8) & 0xff;
-               val[4] = (u8) freq;
+               state->tx_tuna[2] = (freq >> 16) & 0xff;
+               state->tx_tuna[3] = (freq >> 8) & 0xff;
+               state->tx_tuna[4] = (u8) freq;
+
        } else
                return -EINVAL;
        return 0;
@@ -379,51 +382,58 @@ static int dst_set_freq(struct dst_state *state, u32 freq)
 
 static int dst_set_bandwidth(struct dst_state* state, fe_bandwidth_t bandwidth)
 {
-       u8 *val;
-
        state->bandwidth = bandwidth;
 
        if (state->dst_type != DST_TYPE_IS_TERR)
                return 0;
 
-       val = &state->tx_tuna[0];
        switch (bandwidth) {
-       case BANDWIDTH_6_MHZ:
-               val[6] = 6;
-               break;
+               case BANDWIDTH_6_MHZ:
+                       if (state->dst_hw_cap & DST_TYPE_HAS_CA)
+                               state->tx_tuna[7] = 0x06;
+                       else {
+                               state->tx_tuna[6] = 0x06;
+                               state->tx_tuna[7] = 0x00;
+                       }
+                       break;
 
-       case BANDWIDTH_7_MHZ:
-               val[6] = 7;
-               break;
+               case BANDWIDTH_7_MHZ:
+                       if (state->dst_hw_cap & DST_TYPE_HAS_CA)
+                               state->tx_tuna[7] = 0x07;
+                       else {
+                               state->tx_tuna[6] = 0x07;
+                               state->tx_tuna[7] = 0x00;
+                       }
+                       break;
 
-       case BANDWIDTH_8_MHZ:
-               val[6] = 8;
-               break;
+               case BANDWIDTH_8_MHZ:
+                       if (state->dst_hw_cap & DST_TYPE_HAS_CA)
+                               state->tx_tuna[7] = 0x08;
+                       else {
+                               state->tx_tuna[6] = 0x08;
+                               state->tx_tuna[7] = 0x00;
+                       }
+                       break;
 
-       default:
-               return -EINVAL;
+               default:
+                       return -EINVAL;
        }
        return 0;
 }
 
 static int dst_set_inversion(struct dst_state* state, fe_spectral_inversion_t inversion)
 {
-       u8 *val;
-
        state->inversion = inversion;
-
-       val = &state->tx_tuna[0];
-
-       val[8] &= ~0x80;
-
        switch (inversion) {
-       case INVERSION_OFF:
-               break;
-       case INVERSION_ON:
-               val[8] |= 0x80;
-               break;
-       default:
-               return -EINVAL;
+               case INVERSION_OFF:     // Inversion = Normal
+                       state->tx_tuna[8] &= ~0x80;
+                       break;
+
+               case INVERSION_ON:
+                       state->tx_tuna[8] |= 0x80;
+                       break;
+               default:
+                       return -EINVAL;
        }
        return 0;
 }
@@ -478,6 +488,52 @@ static int dst_set_symbolrate(struct dst_state* state, u32 srate)
        return 0;
 }
 
+
+static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation)
+{
+       if (state->dst_type != DST_TYPE_IS_CABLE)
+               return 0;
+
+       state->modulation = modulation;
+       switch (modulation) {
+               case QAM_16:
+                       state->tx_tuna[8] = 0x10;
+                       break;
+
+               case QAM_32:
+                       state->tx_tuna[8] = 0x20;
+                       break;
+
+               case QAM_64:
+                       state->tx_tuna[8] = 0x40;
+                       break;
+
+               case QAM_128:
+                       state->tx_tuna[8] = 0x80;
+                       break;
+
+               case QAM_256:
+                       state->tx_tuna[8] = 0x00;
+                       break;
+
+               case QPSK:
+               case QAM_AUTO:
+               case VSB_8:
+               case VSB_16:
+               default:
+                       return -EINVAL;
+
+       }
+
+       return 0;
+}
+
+static fe_modulation_t dst_get_modulation(struct dst_state *state)
+{
+       return state->modulation;
+}
+
+
 u8 dst_check_sum(u8 * buf, u32 len)
 {
        u32 i;
@@ -577,7 +633,7 @@ struct dst_types dst_tlist[] = {
                .device_id = "200103A",
                .offset = 0,
                .dst_type =  DST_TYPE_IS_SAT,
-               .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
+               .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_OBS_REGS,
                .dst_feature = 0
        },      /*      obsolete        */
 
@@ -626,7 +682,7 @@ struct dst_types dst_tlist[] = {
                .device_id = "DSTMCI",
                .offset = 1,
                .dst_type = DST_TYPE_IS_SAT,
-               .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
+               .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT,
                .dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4
                                                        | DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC
        },
@@ -872,7 +928,7 @@ static int dst_get_signal(struct dst_state* state)
 {
        int retval;
        u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb };
-
+       printk("%s: Getting Signal strength and other parameters !!!!!!!!\n", __FUNCTION__);
        if ((state->diseq_flags & ATTEMPT_TUNE) == 0) {
                state->decode_lock = state->decode_strength = state->decode_snr = 0;
                return 0;
@@ -954,15 +1010,8 @@ static int dst_get_tuna(struct dst_state* state)
        state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3];
 
        state->decode_lock = 1;
-       /*
-          dst->decode_n1 = (dst->rx_tuna[4] << 8) +
-          (dst->rx_tuna[5]);
-
-          dst->decode_n2 = (dst->rx_tuna[8] << 8) +
-          (dst->rx_tuna[7]);
-        */
        state->diseq_flags |= HAS_LOCK;
-       /* dst->cur_jiff = jiffies; */
+
        return 1;
 }
 
@@ -1098,7 +1147,11 @@ static int dst_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 
        switch (tone) {
                case SEC_TONE_OFF:
-                       state->tx_tuna[2] = 0xff;
+                       if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
+                           state->tx_tuna[2] = 0x00;
+                       else
+                           state->tx_tuna[2] = 0xff;
+
                        break;
 
                case SEC_TONE_ON:
@@ -1145,7 +1198,8 @@ static int dst_init(struct dvb_frontend* fe)
        static u8 ini_tvci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
        static u8 ini_cabfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
        static u8 ini_cabci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
-       state->inversion = INVERSION_ON;
+//     state->inversion = INVERSION_ON;
+       state->inversion = INVERSION_OFF;
        state->voltage = SEC_VOLTAGE_13;
        state->tone = SEC_TONE_OFF;
        state->symbol_rate = 29473000;
@@ -1174,7 +1228,7 @@ static int dst_read_status(struct dvb_frontend* fe, fe_status_t* status)
 
        *status = 0;
        if (state->diseq_flags & HAS_LOCK) {
-               dst_get_signal(state);
+//             dst_get_signal(state);  // don't require(?) to ask MCU
                if (state->decode_lock)
                        *status |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | FE_HAS_VITERBI;
        }
@@ -1208,20 +1262,25 @@ static int dst_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_paramet
 
        dst_set_freq(state, p->frequency);
        if (verbose > 4)
-               dprintk("Set Frequency = [%d]\n", p->frequency);
+               dprintk("Set Frequency=[%d]\n", p->frequency);
 
-       dst_set_inversion(state, p->inversion);
+//     dst_set_inversion(state, p->inversion);
        if (state->dst_type == DST_TYPE_IS_SAT) {
+               if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
+                       dst_set_inversion(state, p->inversion);
+
                dst_set_fec(state, p->u.qpsk.fec_inner);
                dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
+               dst_set_polarization(state);
                if (verbose > 4)
-                       dprintk("Set Symbolrate = [%d]\n", p->u.qpsk.symbol_rate);
+                       dprintk("Set Symbolrate=[%d]\n", p->u.qpsk.symbol_rate);
 
        } else if (state->dst_type == DST_TYPE_IS_TERR) {
                dst_set_bandwidth(state, p->u.ofdm.bandwidth);
        } else if (state->dst_type == DST_TYPE_IS_CABLE) {
                dst_set_fec(state, p->u.qam.fec_inner);
                dst_set_symbolrate(state, p->u.qam.symbol_rate);
+               dst_set_modulation(state, p->u.qam.modulation);
        }
        dst_write_tuna(fe);
 
@@ -1233,8 +1292,11 @@ static int dst_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_paramet
        struct dst_state* state = fe->demodulator_priv;
 
        p->frequency = state->decode_freq;
-       p->inversion = state->inversion;
+//     p->inversion = state->inversion;
        if (state->dst_type == DST_TYPE_IS_SAT) {
+               if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
+                       p->inversion = state->inversion;
+
                p->u.qpsk.symbol_rate = state->symbol_rate;
                p->u.qpsk.fec_inner = dst_get_fec(state);
        } else if (state->dst_type == DST_TYPE_IS_TERR) {
@@ -1242,7 +1304,8 @@ static int dst_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_paramet
        } else if (state->dst_type == DST_TYPE_IS_CABLE) {
                p->u.qam.symbol_rate = state->symbol_rate;
                p->u.qam.fec_inner = dst_get_fec(state);
-               p->u.qam.modulation = QAM_AUTO;
+//             p->u.qam.modulation = QAM_AUTO;
+               p->u.qam.modulation = dst_get_modulation(state);
        }
 
        return 0;
index d781504cc2fa8e4c6aa7289e0304a295c995c8ef..bfaacd5fc20f01b1663132c30e281e794f049c86 100644 (file)
@@ -32,7 +32,7 @@
 #include "dst_ca.h"
 #include "dst_common.h"
 
-static unsigned int verbose = 1;
+static unsigned int verbose = 5;
 module_param(verbose, int, 0644);
 MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
 
@@ -295,34 +295,28 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message,
        return 0;
 }
 
-static int handle_en50221_tag(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer)
+static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u32 length)
 {
        if (state->dst_hw_cap & DST_TYPE_HAS_SESSION) {
                hw_buffer->msg[2] = p_ca_message->msg[1];               /*              MSB                     */
                hw_buffer->msg[3] = p_ca_message->msg[2];               /*              LSB                     */
        }
        else {
+               hw_buffer->msg[0] = (length & 0xff) + 7;
+               hw_buffer->msg[1] = 0x40;
                hw_buffer->msg[2] = 0x03;
                hw_buffer->msg[3] = 0x00;
+               hw_buffer->msg[4] = 0x03;
+               hw_buffer->msg[5] = length & 0xff;
+               hw_buffer->msg[6] = 0x00;
        }
        return 0;
 }
 
-static int debug_8820_buffer(struct ca_msg *hw_buffer)
-{
-       unsigned int i;
-
-       dprintk("%s:Debug=[", __FUNCTION__);
-       for (i = 0; i < (hw_buffer->msg[0] + 1); i++)
-               dprintk(" %02x", hw_buffer->msg[i]);
-       dprintk("]\n");
-
-       return 0;
-}
 
-static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 reply)
+static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 length, u8 reply)
 {
-       if ((dst_put_ci(state, hw_buffer->msg, (hw_buffer->length + 1), hw_buffer->msg, reply)) < 0) {
+       if ((dst_put_ci(state, hw_buffer->msg, length, hw_buffer->msg, reply)) < 0) {
                dprintk("%s: DST-CI Command failed.\n", __FUNCTION__);
                dprintk("%s: Resetting DST.\n", __FUNCTION__);
                rdc_reset_state(state);
@@ -334,234 +328,141 @@ static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 r
        return 0;
 }
 
-
-static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query)
+u32 asn_1_decode(u8 *asn_1_array)
 {
-       u32 hw_offset, buf_offset, i, k;
-       u32 program_info_length = 0, es_info_length = 0, length = 0, words = 0;
-       u8 found_prog_ca_desc = 0, found_stream_ca_desc = 0, error_condition = 0, hw_buffer_length = 0;
-
-       if (verbose > 3)
-               dprintk("%s, p_ca_message length %d (0x%x)\n", __FUNCTION__,p_ca_message->length,p_ca_message->length );
-
-       handle_en50221_tag(state, p_ca_message, hw_buffer);                     /*      EN50221 tag             */
-
-       /*      Handle the length field (variable)      */
-       if (!(p_ca_message->msg[3] & 0x80)) {                           /*      Length = 1              */
-               length = p_ca_message->msg[3] & 0x7f;
-               words = 0;                                              /*      domi's suggestion       */
-       }
-       else {                                                          /*      Length = words          */
-               words = p_ca_message->msg[3] & 0x7f;
-               for (i = 0; i < words; i++) {
-                       length = length << 8;
-                       length = length | p_ca_message->msg[4 + i];
+       u8 length_field = 0, word_count = 0, count = 0;
+       u32 length = 0;
+
+       length_field = asn_1_array[0];
+       dprintk("%s: Length field=[%02x]\n", __FUNCTION__, length_field);
+       if (length_field < 0x80) {
+               length = length_field & 0x7f;
+               dprintk("%s: Length=[%02x]\n", __FUNCTION__, length);
+       } else {
+               word_count = length_field & 0x7f;
+               for (count = 0; count < word_count; count++) {
+                       length = (length | asn_1_array[count + 1]) << 8;
+                       dprintk("%s: Length=[%04x]\n", __FUNCTION__, length);
                }
        }
-       if (verbose > 4) {
-               dprintk("%s:Length=[%d (0x%x)], Words=[%d]\n", __FUNCTION__, length,length, words);
-
-               /*      Debug Input string              */
-               for (i = 0; i < length; i++)
-                       dprintk(" %02x", p_ca_message->msg[i]);
-               dprintk("]\n");
-       }
-
-       hw_offset = 7;
-       buf_offset = words + 4;
-
-       /*              Program Header                  */
-       if (verbose > 4)
-               dprintk("\n%s:Program Header=[", __FUNCTION__);
-       for (i = 0; i < 6; i++) {
-               hw_buffer->msg[hw_offset] = p_ca_message->msg[buf_offset];
-               if (verbose > 4)
-                       dprintk(" %02x", p_ca_message->msg[buf_offset]);
-               hw_offset++, buf_offset++, hw_buffer_length++;
-       }
-       if (verbose > 4)
-               dprintk("]\n");
+       return length;
+}
 
-       program_info_length = 0;
-       program_info_length = (((program_info_length | p_ca_message->msg[words + 8]) & 0x0f) << 8) | p_ca_message->msg[words + 9];
-       if (verbose > 4)
-               dprintk("%s:Program info Length=[%d][%02x], hw_offset=[%d], buf_offset=[%d] \n",
-                       __FUNCTION__, program_info_length, program_info_length, hw_offset, buf_offset);
+static int init_buffer(u8 *buffer, u32 length)
+{
+       u32 i;
+       for (i = 0; i < length; i++)
+               buffer[i] = 0;
 
-       if (program_info_length && (program_info_length < 256)) {       /*      If program_info_length          */
-               hw_buffer->msg[11] = hw_buffer->msg[11] & 0x0f;         /*      req only 4 bits                 */
-               hw_buffer->msg[12] = hw_buffer->msg[12] + 1;            /*      increment! ASIC bug!            */
+       return 0;
+}
 
-               if (p_ca_message->msg[buf_offset + 1] == 0x09) {        /*      Check CA descriptor             */
-                       found_prog_ca_desc = 1;
-                       if (verbose > 4)
-                               dprintk("%s: Found CA descriptor @ Program level\n", __FUNCTION__);
-               }
+static int debug_string(u8 *msg, u32 length, u32 offset)
+{
+       u32 i;
 
-               if (found_prog_ca_desc) {                               /*      Command only if CA descriptor   */
-                       hw_buffer->msg[13] = p_ca_message->msg[buf_offset];     /*      CA PMT command ID       */
-                       hw_offset++, buf_offset++, hw_buffer_length++;
-               }
+       dprintk(" String=[ ");
+       for (i = offset; i < length; i++)
+               dprintk("%02x ", msg[i]);
+       dprintk("]\n");
 
-               /*                      Program descriptors                             */
-               if (verbose > 4) {
-                       dprintk("%s:**********>buf_offset=[%d], hw_offset=[%d]\n", __FUNCTION__, buf_offset, hw_offset);
-                       dprintk("%s:Program descriptors=[", __FUNCTION__);
-               }
-               while (program_info_length && !error_condition) {               /*      Copy prog descriptors   */
-                       if (program_info_length > p_ca_message->length) {       /*      Error situation         */
-                               dprintk ("%s:\"WARNING\" Length error, line=[%d], prog_info_length=[%d]\n",
-                                                               __FUNCTION__, __LINE__, program_info_length);
-                               dprintk("%s:\"WARNING\" Bailing out of possible loop\n", __FUNCTION__);
-                               error_condition = 1;
-                               break;
-                       }
+       return 0;
+}
 
-                       hw_buffer->msg[hw_offset] = p_ca_message->msg[buf_offset];
-                       dprintk(" %02x", p_ca_message->msg[buf_offset]);
-                       hw_offset++, buf_offset++, hw_buffer_length++, program_info_length--;
-               }
-               if (verbose > 4) {
-                       dprintk("]\n");
-                       dprintk("%s:**********>buf_offset=[%d], hw_offset=[%d]\n", __FUNCTION__, buf_offset, hw_offset);
-               }
-               if (found_prog_ca_desc) {
-                       if (!reply) {
-                               hw_buffer->msg[13] = 0x01;              /*      OK descrambling                 */
-                               if (verbose > 1)
-                                       dprintk("CA PMT Command = OK Descrambling\n");
-                       }
-                       else {
-                               hw_buffer->msg[13] = 0x02;              /*      Ok MMI                          */
-                               if (verbose > 1)
-                                       dprintk("CA PMT Command = Ok MMI\n");
-                       }
-                       if (query) {
-                               hw_buffer->msg[13] = 0x03;              /*      Query                           */
-                               if (verbose > 1)
-                                       dprintk("CA PMT Command = CA PMT query\n");
-                       }
-               }
-       }
-       else {
-               hw_buffer->msg[11] = hw_buffer->msg[11] & 0xf0;         /*      Don't write to ASIC             */
-               hw_buffer->msg[12] = hw_buffer->msg[12] = 0x00;
+static int copy_string(u8 *destination, u8 *source, u32 dest_offset, u32 source_offset, u32 length)
+{
+       u32 i;
+       dprintk("%s: Copying [", __FUNCTION__);
+       for (i = 0; i < length; i++) {
+               destination[i + dest_offset] = source[i + source_offset];
+               dprintk(" %02x", source[i + source_offset]);
        }
-       if (verbose > 4)
-               dprintk("%s:**********>p_ca_message->length=[%d], buf_offset=[%d], hw_offset=[%d]\n",
-                                       __FUNCTION__, p_ca_message->length, buf_offset, hw_offset);
-
-       while ((buf_offset  < p_ca_message->length)  && !error_condition) {
-               /*      Bail out in case of an indefinite loop          */
-               if ((es_info_length > p_ca_message->length) || (buf_offset > p_ca_message->length)) {
-                       dprintk("%s:\"WARNING\" Length error, line=[%d], prog_info_length=[%d], buf_offset=[%d]\n",
-                                                       __FUNCTION__, __LINE__, program_info_length, buf_offset);
-
-                       dprintk("%s:\"WARNING\" Bailing out of possible loop\n", __FUNCTION__);
-                       error_condition = 1;
-                       break;
-               }
-
-               /*              Stream Header                           */
-
-               for (k = 0; k < 5; k++) {
-                       hw_buffer->msg[hw_offset + k] = p_ca_message->msg[buf_offset + k];
-               }
+       dprintk("]\n");
 
-               es_info_length = 0;
-               es_info_length = (es_info_length | (p_ca_message->msg[buf_offset + 3] & 0x0f)) << 8 | p_ca_message->msg[buf_offset + 4];
+       return i;
+}
 
-               if (verbose > 4) {
-                       dprintk("\n%s:----->Stream header=[%02x %02x %02x %02x %02x]\n", __FUNCTION__,
-                               p_ca_message->msg[buf_offset + 0], p_ca_message->msg[buf_offset + 1],
-                               p_ca_message->msg[buf_offset + 2], p_ca_message->msg[buf_offset + 3],
-                               p_ca_message->msg[buf_offset + 4]);
+static int modify_4_bits(u8 *message, u32 pos)
+{
+       message[pos] &= 0x0f;
 
-                       dprintk("%s:----->Stream type=[%02x], es length=[%d (0x%x)], Chars=[%02x] [%02x], buf_offset=[%d]\n", __FUNCTION__,
-                               p_ca_message->msg[buf_offset + 0], es_info_length, es_info_length,
-                               p_ca_message->msg[buf_offset + 3], p_ca_message->msg[buf_offset + 4], buf_offset);
-               }
+       return 0;
+}
 
-               hw_buffer->msg[hw_offset + 3] &= 0x0f;                  /*      req only 4 bits                 */
 
-               if (found_prog_ca_desc) {
-                       hw_buffer->msg[hw_offset + 3] = 0x00;
-                       hw_buffer->msg[hw_offset + 4] = 0x00;
-               }
 
-               hw_offset += 5, buf_offset += 5, hw_buffer_length += 5;
+static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query)
+{
+       u32 length = 0, count = 0;
+       u8 asn_1_words, program_header_length;
+       u16 program_info_length = 0, es_info_length = 0;
+       u32 hw_offset = 0, buf_offset = 0, i;
+       u8 dst_tag_length;
 
-               /*              Check for CA descriptor                 */
-               if (p_ca_message->msg[buf_offset + 1] == 0x09) {
-                       if (verbose > 4)
-                               dprintk("%s:Found CA descriptor @ Stream level\n", __FUNCTION__);
-                       found_stream_ca_desc = 1;
-               }
+       length = asn_1_decode(&p_ca_message->msg[3]);
+       dprintk("%s: CA Message length=[%d]\n", __FUNCTION__, length);
+       dprintk("%s: ASN.1 ", __FUNCTION__);
+       debug_string(&p_ca_message->msg[4], length, 0); // length does not include tag and length
 
-               /*              ES descriptors                          */
-
-               if (es_info_length && !error_condition && !found_prog_ca_desc && found_stream_ca_desc) {
-//                     if (!ca_pmt_done) {
-                               hw_buffer->msg[hw_offset] = p_ca_message->msg[buf_offset];      /*      CA PMT cmd(es)  */
-                               if (verbose > 4)
-                                       printk("%s:----->CA PMT Command ID=[%02x]\n", __FUNCTION__, p_ca_message->msg[buf_offset]);
-//                             hw_offset++, buf_offset++, hw_buffer_length++, es_info_length--, ca_pmt_done = 1;
-                               hw_offset++, buf_offset++, hw_buffer_length++, es_info_length--;
-//                     }
-                       if (verbose > 4)
-                               dprintk("%s:----->ES descriptors=[", __FUNCTION__);
-
-                       while (es_info_length && !error_condition) {    /*      ES descriptors                  */
-                               if ((es_info_length > p_ca_message->length) || (buf_offset > p_ca_message->length)) {
-                                       if (verbose > 4) {
-                                               dprintk("%s:\"WARNING\" ES Length error, line=[%d], es_info_length=[%d], buf_offset=[%d]\n",
-                                                                               __FUNCTION__, __LINE__, es_info_length, buf_offset);
-
-                                               dprintk("%s:\"WARNING\" Bailing out of possible loop\n", __FUNCTION__);
-                                       }
-                                       error_condition = 1;
-                                       break;
-                               }
+       init_buffer(hw_buffer->msg, length);
+       handle_dst_tag(state, p_ca_message, hw_buffer, length);
 
-                               hw_buffer->msg[hw_offset] = p_ca_message->msg[buf_offset];
-                               if (verbose > 3)
-                                       dprintk("%02x ", hw_buffer->msg[hw_offset]);
-                               hw_offset++, buf_offset++, hw_buffer_length++, es_info_length--;
-                       }
-                       found_stream_ca_desc = 0;                       /*      unset for new streams           */
-                       dprintk("]\n");
+       hw_offset = 7;
+       asn_1_words = 1; // just a hack to test, should compute this one
+       buf_offset = 3;
+       program_header_length = 6;
+       dst_tag_length = 7;
+
+//     debug_twinhan_ca_params(state, p_ca_message, hw_buffer, reply, query, length, hw_offset, buf_offset);
+//     dprintk("%s: Program Header(BUF)", __FUNCTION__);
+//     debug_string(&p_ca_message->msg[4], program_header_length, 0);
+//     dprintk("%s: Copying Program header\n", __FUNCTION__);
+       copy_string(hw_buffer->msg, p_ca_message->msg, hw_offset, (buf_offset + asn_1_words), program_header_length);
+       buf_offset += program_header_length, hw_offset += program_header_length;
+       modify_4_bits(hw_buffer->msg, (hw_offset - 2));
+       if (state->type_flags & DST_TYPE_HAS_INC_COUNT) {       // workaround
+               dprintk("%s: Probably an ASIC bug !!!\n", __FUNCTION__);
+               debug_string(hw_buffer->msg, (hw_offset + program_header_length), 0);
+               hw_buffer->msg[hw_offset - 1] += 1;
+       }
+
+//     dprintk("%s: Program Header(HW), Count=[%d]", __FUNCTION__, count);
+//     debug_string(hw_buffer->msg, hw_offset, 0);
+
+       program_info_length =  ((program_info_length | (p_ca_message->msg[buf_offset - 1] & 0x0f)) << 8) | p_ca_message->msg[buf_offset];
+       dprintk("%s: Program info length=[%02x]\n", __FUNCTION__, program_info_length);
+       if (program_info_length) {
+               count = copy_string(hw_buffer->msg, p_ca_message->msg, hw_offset, (buf_offset + 1), (program_info_length + 1) ); // copy next elem, not current
+               buf_offset += count, hw_offset += count;
+//             dprintk("%s: Program level ", __FUNCTION__);
+//             debug_string(hw_buffer->msg, hw_offset, 0);
+       }
+
+       buf_offset += 1;// hw_offset += 1;
+       for (i = buf_offset; i < length; i++) {
+//             dprintk("%s: Stream Header ", __FUNCTION__);
+               count = copy_string(hw_buffer->msg, p_ca_message->msg, hw_offset, buf_offset, 5);
+               modify_4_bits(hw_buffer->msg, (hw_offset + 3));
+
+               hw_offset += 5, buf_offset += 5, i += 4;
+//             debug_string(hw_buffer->msg, hw_offset, (hw_offset - 5));
+               es_info_length = ((es_info_length | (p_ca_message->msg[buf_offset - 1] & 0x0f)) << 8) | p_ca_message->msg[buf_offset];
+               dprintk("%s: ES info length=[%02x]\n", __FUNCTION__, es_info_length);
+               if (es_info_length) {
+                       // copy descriptors @ STREAM level
+                       dprintk("%s: Descriptors @ STREAM level...!!! \n", __FUNCTION__);
                }
-       }
-
-       /*              MCU Magic words                                 */
-
-       hw_buffer_length += 7;
-       hw_buffer->msg[0] = hw_buffer_length;
-       hw_buffer->msg[1] = 64;
-       hw_buffer->msg[4] = 3;
-       hw_buffer->msg[5] = hw_buffer->msg[0] - 7;
-       hw_buffer->msg[6] = 0;
-
 
-       /*      Fix length      */
-       hw_buffer->length = hw_buffer->msg[0];
-
-       put_checksum(&hw_buffer->msg[0], hw_buffer->msg[0]);
-       /*      Do the actual write     */
-       if (verbose > 4) {
-               dprintk("%s:======================DEBUGGING================================\n", __FUNCTION__);
-               dprintk("%s: Actual Length=[%d]\n", __FUNCTION__, hw_buffer_length);
        }
-       /*      Only for debugging!     */
-       if (verbose > 2)
-               debug_8820_buffer(hw_buffer);
-       if (verbose > 3)
-               dprintk("%s: Reply = [%d]\n", __FUNCTION__, reply);
-       write_to_8820(state, hw_buffer, reply);
+       hw_buffer->msg[length + dst_tag_length] = dst_check_sum(hw_buffer->msg, (length + dst_tag_length));
+//     dprintk("%s: Total length=[%d], Checksum=[%02x]\n", __FUNCTION__, (length + dst_tag_length), hw_buffer->msg[length + dst_tag_length]);
+       debug_string(hw_buffer->msg, (length + dst_tag_length + 1), 0); // dst tags also
+       write_to_8820(state, hw_buffer, (length + dst_tag_length + 1), reply);  // checksum
 
        return 0;
 }
 
+
 /*     Board supports CA PMT reply ?           */
 static int dst_check_ca_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer)
 {
@@ -605,7 +506,7 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
        struct ca_msg *hw_buffer;
 
        if ((hw_buffer = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
-               printk("%s: Memory allocation failure\n", __FUNCTION__);
+               dprintk("%s: Memory allocation failure\n", __FUNCTION__);
                return -ENOMEM;
        }
        if (verbose > 3)
@@ -630,8 +531,10 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
                switch (command) {
                        case CA_PMT:
                                if (verbose > 3)
+//                                     dprintk("Command = SEND_CA_PMT\n");
                                        dprintk("Command = SEND_CA_PMT\n");
-                               if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) {
+//                             if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) {
+                               if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) {   // code simplification started
                                        dprintk("%s: -->CA_PMT Failed !\n", __FUNCTION__);
                                        return -1;
                                }
@@ -664,7 +567,7 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
                                        return -1;
                                }
                                if (verbose > 3)
-                                       printk("%s: -->CA_APP_INFO_ENQUIRY Success !\n", __FUNCTION__);
+                                       dprintk("%s: -->CA_APP_INFO_ENQUIRY Success !\n", __FUNCTION__);
 
                                break;
                }
@@ -681,17 +584,17 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        struct ca_msg *p_ca_message;
 
        if ((p_ca_message = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
-               printk("%s: Memory allocation failure\n", __FUNCTION__);
+               dprintk("%s: Memory allocation failure\n", __FUNCTION__);
                return -ENOMEM;
        }
 
        if ((p_ca_slot_info = (struct ca_slot_info *) kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL)) == NULL) {
-               printk("%s: Memory allocation failure\n", __FUNCTION__);
+               dprintk("%s: Memory allocation failure\n", __FUNCTION__);
                return -ENOMEM;
        }
 
        if ((p_ca_caps = (struct ca_caps *) kmalloc(sizeof (struct ca_caps), GFP_KERNEL)) == NULL) {
-               printk("%s: Memory allocation failure\n", __FUNCTION__);
+               dprintk("%s: Memory allocation failure\n", __FUNCTION__);
                return -ENOMEM;
        }
 
index 0b3da29245fb2deb7709032e21dbc5738cd87303..ef532a6aceaa3fb4057166cea9956e6a9cb657c4 100644 (file)
@@ -47,6 +47,8 @@
 #define DST_TYPE_HAS_FW_2      16
 #define DST_TYPE_HAS_FW_3      32
 #define DST_TYPE_HAS_FW_BUILD  64
+#define DST_TYPE_HAS_OBS_REGS  128
+#define DST_TYPE_HAS_INC_COUNT 256
 
 /*     Card capability list    */
 
@@ -110,6 +112,7 @@ struct dst_state {
        u32 dst_hw_cap;
        u8 dst_fw_version;
        fe_sec_mini_cmd_t minicmd;
+       fe_modulation_t modulation;
        u8 messages[256];
 };
 
index 96c57fde95a0da96efd4e16f47c8417837ee7a2c..7d8b3cad350bea238b84d4029cf209d894c116f5 100644 (file)
@@ -699,6 +699,8 @@ static void cinergyt2_query_rc (void *data)
        for (n=0; len>0 && n<(len/sizeof(rc_events[0])); n++) {
                int i;
 
+/*             dprintk(1,"rc_events[%d].value = %x, type=%x\n",n,le32_to_cpu(rc_events[n].value),rc_events[n].type);*/
+
                if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC &&
                    rc_events[n].value == ~0)
                {
@@ -714,7 +716,7 @@ static void cinergyt2_query_rc (void *data)
                        cinergyt2->rc_input_event = KEY_MAX;
                        for (i=0; i<sizeof(rc_keys)/sizeof(rc_keys[0]); i+=3) {
                                if (rc_keys[i+0] == rc_events[n].type &&
-                                   rc_keys[i+1] == rc_events[n].value)
+                                   rc_keys[i+1] == le32_to_cpu(rc_events[n].value))
                                {
                                        cinergyt2->rc_input_event = rc_keys[i+2];
                                        break;
index c225de7ffd82429f61103839a4657df49a440a3c..68050cd527cb4db568a0868b10d2234bbe003ace 100644 (file)
@@ -42,12 +42,6 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
 
 #define dprintk        if (debug) printk
 
-static inline struct dmxdev_filter *
-dvb_dmxdev_file_to_filter(struct file *file)
-{
-       return (struct dmxdev_filter *) file->private_data;
-}
-
 static inline void dvb_dmxdev_buffer_init(struct dmxdev_buffer *buffer)
 {
        buffer->data=NULL;
@@ -669,8 +663,10 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
 
                ret = filter->feed.ts->start_filtering(filter->feed.ts);
 
-               if (ret < 0)
+               if (ret < 0) {
+                       dmxdev->demux->release_ts_feed(dmxdev->demux, *tsfeed);
                        return ret;
+               }
 
                break;
        }
@@ -842,7 +838,7 @@ static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil,
 static ssize_t
 dvb_demux_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
-       struct dmxdev_filter *dmxdevfilter=dvb_dmxdev_file_to_filter(file);
+       struct dmxdev_filter *dmxdevfilter= file->private_data;
        int ret=0;
 
        if (down_interruptible(&dmxdevfilter->mutex))
@@ -863,7 +859,7 @@ dvb_demux_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 static int dvb_demux_do_ioctl(struct inode *inode, struct file *file,
                              unsigned int cmd, void *parg)
 {
-       struct dmxdev_filter *dmxdevfilter=dvb_dmxdev_file_to_filter(file);
+       struct dmxdev_filter *dmxdevfilter = file->private_data;
        struct dmxdev *dmxdev=dmxdevfilter->dev;
        unsigned long arg=(unsigned long) parg;
        int ret=0;
@@ -960,7 +956,7 @@ static int dvb_demux_ioctl(struct inode *inode, struct file *file,
 
 static unsigned int dvb_demux_poll (struct file *file, poll_table *wait)
 {
-       struct dmxdev_filter *dmxdevfilter = dvb_dmxdev_file_to_filter(file);
+       struct dmxdev_filter *dmxdevfilter = file->private_data;
        unsigned int mask = 0;
 
        if (!dmxdevfilter)
@@ -985,7 +981,7 @@ static unsigned int dvb_demux_poll (struct file *file, poll_table *wait)
 
 static int dvb_demux_release(struct inode *inode, struct file *file)
 {
-       struct dmxdev_filter *dmxdevfilter = dvb_dmxdev_file_to_filter(file);
+       struct dmxdev_filter *dmxdevfilter = file->private_data;
        struct dmxdev *dmxdev = dmxdevfilter->dev;
 
        return dvb_dmxdev_filter_free(dmxdev, dmxdevfilter);
@@ -1109,7 +1105,6 @@ dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
                dvb_dmxdev_filter_state_set(&dmxdev->filter[i], DMXDEV_STATE_FREE);
                dmxdev->dvr[i].dev=dmxdev;
                dmxdev->dvr[i].buffer.data=NULL;
-               dvb_dmxdev_filter_state_set(&dmxdev->filter[i], DMXDEV_STATE_FREE);
                dvb_dmxdev_dvr_state_set(&dmxdev->dvr[i], DMXDEV_STATE_FREE);
        }
 
index f11daae91cd4e07ce54bdb375f5f10aed22aa104..a8bc84240b50a8ea5b78338bd56df515d4cc77bd 100644 (file)
@@ -42,6 +42,8 @@
 #include "dvb_frontend.h"
 #include "dvbdev.h"
 
+// #define DEBUG_LOCKLOSS 1
+
 static int dvb_frontend_debug;
 static int dvb_shutdown_timeout = 5;
 static int dvb_force_auto_inversion;
@@ -113,6 +115,7 @@ struct dvb_frontend_private {
        int exit;
        int wakeup;
        fe_status_t status;
+       fe_sec_tone_mode_t tone;
 };
 
 
@@ -434,9 +437,26 @@ static int dvb_frontend_thread(void *data)
                        /* we're tuned, and the lock is still good... */
                        if (s & FE_HAS_LOCK)
                                continue;
-                       else {
-                               /* if we _WERE_ tuned, but now don't have a lock,
-                                * need to zigzag */
+                       else { /* if we _WERE_ tuned, but now don't have a lock */
+#ifdef DEBUG_LOCKLOSS
+                               /* first of all try setting the tone again if it was on - this
+                                * sometimes works around problems with noisy power supplies */
+                               if (fe->ops->set_tone && (fepriv->tone == SEC_TONE_ON)) {
+                                       fe->ops->set_tone(fe, fepriv->tone);
+                                       mdelay(100);
+                                       s = 0;
+                                       fe->ops->read_status(fe, &s);
+                                       if (s & FE_HAS_LOCK) {
+                                               printk("DVB%i: Lock was lost, but regained by setting "
+                                                      "the tone. This may indicate your power supply "
+                                                      "is noisy/slightly incompatable with this DVB-S "
+                                                      "adapter\n", fe->dvb->num);
+                                               fepriv->state = FESTATE_TUNED;
+                                               continue;
+                                       }
+                               }
+#endif
+                               /* some other reason for losing the lock - start zigzagging */
                                fepriv->state = FESTATE_ZIGZAG_FAST;
                                fepriv->started_auto_step = fepriv->auto_step;
                                check_wrapped = 0;
@@ -626,11 +646,21 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                break;
        }
 
-       case FE_READ_STATUS:
+       case FE_READ_STATUS: {
+               fe_status_t* status = parg;
+
+               /* if retune was requested but hasn't occured yet, prevent
+                * that user get signal state from previous tuning */
+               if(fepriv->state == FESTATE_RETUNE) {
+                       err=0;
+                       *status = 0;
+                       break;
+               }
+
                if (fe->ops->read_status)
-                       err = fe->ops->read_status(fe, (fe_status_t*) parg);
+                       err = fe->ops->read_status(fe, status);
                break;
-
+       }
        case FE_READ_BER:
                if (fe->ops->read_ber)
                        err = fe->ops->read_ber(fe, (__u32*) parg);
@@ -681,6 +711,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                        err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg);
                        fepriv->state = FESTATE_DISEQC;
                        fepriv->status = 0;
+                       fepriv->tone = (fe_sec_tone_mode_t) parg;
                }
                break;
 
@@ -883,6 +914,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
        init_MUTEX (&fepriv->events.sem);
        fe->dvb = dvb;
        fepriv->inversion = INVERSION_OFF;
+       fepriv->tone = SEC_TONE_OFF;
 
        printk ("DVB: registering frontend %i (%s)...\n",
                fe->dvb->num,
index d2b021792791e1760bda63f00071bafcc64694c8..9c2c1d1136bd158ead80b9e7d902fbd84573127e 100644 (file)
 
 #include "dvbdev.h"
 
-/* FIXME: Move to i2c-id.h */
-#define I2C_DRIVERID_DVBFE_SP8870      I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_CX22700     I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_AT76C651    I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_CX24110     I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_CX22702     I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_DIB3000MB   I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_DST         I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_DUMMY       I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_L64781      I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_MT312       I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_MT352       I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_NXT6000     I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_SP887X      I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_STV0299     I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_TDA1004X    I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_TDA8083     I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_VES1820     I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_VES1X93     I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_TDA80XX     I2C_DRIVERID_EXP2
-
-
 struct dvb_frontend_tune_settings {
         int min_delay_ms;
         int step_size;
index 8aa32f6e447b67f3a197fc53e84f7d2f3a564aba..612e5b087b1c1208b5a517a12b7ad1fa8728d348 100644 (file)
@@ -3,30 +3,35 @@ config DVB_USB
        depends on DVB_CORE && USB
        select FW_LOADER
        help
-         By enabling this you will be able to choose the various USB 1.1 and
-         USB2.0 DVB devices.
+         By enabling this you will be able to choose the various supported
+         USB1.1 and USB2.0 DVB devices.
 
          Almost every USB device needs a firmware, please look into
-         <file:Documentation/dvb/README.dvb-usb>
+         <file:Documentation/dvb/README.dvb-usb>.
 
-         Say Y if you own an USB DVB device.
+         For a complete list of supported USB devices see the LinuxTV DVB Wiki:
+         <http://www.linuxtv.org/wiki/index.php/DVB_USB>
+
+         Say Y if you own a USB DVB device.
 
 config DVB_USB_DEBUG
        bool "Enable extended debug support for all DVB-USB devices"
        depends on DVB_USB
        help
-         Say Y if you want to enable debuging. See modinfo dvb-usb (and the
+         Say Y if you want to enable debugging. See modinfo dvb-usb (and the
          appropriate drivers) for debug levels.
 
 config DVB_USB_A800
        tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)"
        depends on DVB_USB
+       select DVB_DIB3000MC
        help
          Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver.
 
 config DVB_USB_DIBUSB_MB
        tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)"
        depends on DVB_USB
+       select DVB_DIB3000MB
        help
          Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by
          DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
@@ -52,6 +57,7 @@ config DVB_USB_DIBUSB_MB
 config DVB_USB_DIBUSB_MC
        tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
        depends on DVB_USB
+       select DVB_DIB3000MC
        help
          Support for 2.0 DVB-T receivers based on reference designs made by
          DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
@@ -66,12 +72,23 @@ config DVB_USB_DIBUSB_MC
 config DVB_USB_UMT_010
        tristate "HanfTek UMT-010 DVB-T USB2.0 support"
        depends on DVB_USB
+       select DVB_DIB3000MC
        help
          Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
 
+config DVB_USB_CXUSB
+       tristate "Medion MD95700 hybrid USB2.0 (Conexant) support"
+       depends on DVB_USB
+       select DVB_CX22702
+       help
+         Say Y here to support the Medion MD95700 hybrid USB2.0 device. Currently
+         only the DVB-T part is supported.
+
 config DVB_USB_DIGITV
        tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
        depends on DVB_USB
+       select DVB_NXT6000
+       select DVB_MT352
        help
          Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver.
 
@@ -87,13 +104,16 @@ config DVB_USB_VP7045
 config DVB_USB_NOVA_T_USB2
        tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
        depends on DVB_USB
+       select DVB_DIB3000MC
        help
          Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
 
 config DVB_USB_DTT200U
-       tristate "Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 support"
+       tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)"
        depends on DVB_USB
        help
-         Say Y here to support the Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 receiver.
+         Say Y here to support the WideView/Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 receiver.
 
          The receivers are also known as DTT200U (Yakumo) and UB300 (Yuan).
+
+         The WT-220U and its clones are pen-sized.
index d65b50f9abb0d5775009add1f9ac02c0188d80e3..746d87ed6f3280248d96179a3a0b41c8dd280e68 100644 (file)
@@ -27,4 +27,7 @@ obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o
 dvb-usb-digitv-objs = digitv.o
 obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o
 
+dvb-usb-cxusb-objs = cxusb.o
+obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o
+
 EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
index a3542935604fb14a9a5065fbd599253133e92b05..f2fcc2f1f846114391ae66ddffebd89dec5027d8 100644 (file)
@@ -61,6 +61,12 @@ static struct dvb_usb_rc_key a800_rc_keys[] = {
        { 0x02, 0x00, KEY_LAST },        /* >>| / BLUE */
        { 0x02, 0x04, KEY_EPG },         /* EPG */
        { 0x02, 0x15, KEY_MENU },        /* MENU */
+
+       { 0x03, 0x03, KEY_CHANNELUP },   /* CH UP */
+       { 0x03, 0x02, KEY_CHANNELDOWN }, /* CH DOWN */
+       { 0x03, 0x01, KEY_FIRST },       /* |<< / GREEN */
+       { 0x03, 0x00, KEY_LAST },        /* >>| / BLUE */
+
 };
 
 int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
@@ -68,7 +74,7 @@ int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
        u8 key[5];
        if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0),
                                0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5,
-                               2*HZ) != 5)
+                               2000) != 5)
                return -ENODEV;
 
        /* call the universal NEC remote processor, to find out the key's state and event */
@@ -143,7 +149,7 @@ static struct dvb_usb_properties a800_properties = {
 
 static struct usb_driver a800_driver = {
        .owner          = THIS_MODULE,
-       .name           = "AVerMedia AverTV DVB-T USB 2.0 (A800)",
+       .name           = "dvb_usb_a800",
        .probe          = a800_probe,
        .disconnect = dvb_usb_device_exit,
        .id_table       = a800_table,
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
new file mode 100644 (file)
index 0000000..c3e1b66
--- /dev/null
@@ -0,0 +1,295 @@
+/* DVB USB compliant linux driver for Conexant USB reference design.
+ *
+ * The Conexant reference design I saw on their website was only for analogue
+ * capturing (using the cx25842). The box I took to write this driver (reverse
+ * engineered) is the one labeled Medion MD95700. In addition to the cx25842
+ * for analogue capturing it also has a cx22702 DVB-T demodulator on the main
+ * board. Besides it has a atiremote (X10) and a USB2.0 hub onboard.
+ *
+ * Maybe it is a little bit premature to call this driver cxusb, but I assume
+ * the USB protocol is identical or at least inherited from the reference
+ * design, so it can be reused for the "analogue-only" device (if it will
+ * appear at all).
+ *
+ * TODO: check if the cx25840-driver (from ivtv) can be used for the analogue
+ * part
+ *
+ * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ *     This program is free software; you can redistribute it and/or modify it
+ *     under the terms of the GNU General Public License as published by the Free
+ *     Software Foundation, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "cxusb.h"
+
+#include "cx22702.h"
+
+/* debug */
+int dvb_usb_cxusb_debug;
+module_param_named(debug,dvb_usb_cxusb_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
+static int cxusb_ctrl_msg(struct dvb_usb_device *d,
+               u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+{
+       int wo = (rbuf == NULL || rlen == 0); /* write-only */
+       u8 sndbuf[1+wlen];
+       memset(sndbuf,0,1+wlen);
+
+       sndbuf[0] = cmd;
+       memcpy(&sndbuf[1],wbuf,wlen);
+       if (wo)
+               dvb_usb_generic_write(d,sndbuf,1+wlen);
+       else
+               dvb_usb_generic_rw(d,sndbuf,1+wlen,rbuf,rlen,0);
+
+       return 0;
+}
+
+/* I2C */
+static void cxusb_set_i2c_path(struct dvb_usb_device *d, enum cxusb_i2c_pathes path)
+{
+       struct cxusb_state *st = d->priv;
+       u8 o[2],i;
+
+       if (path == st->cur_i2c_path)
+               return;
+
+       o[0] = IOCTL_SET_I2C_PATH;
+       switch (path) {
+               case PATH_CX22702:
+                       o[1] = 0;
+                       break;
+               case PATH_TUNER_OTHER:
+                       o[1] = 1;
+                       break;
+               default:
+                       err("unkown i2c path");
+                       return;
+       }
+       cxusb_ctrl_msg(d,CMD_IOCTL,o,2,&i,1);
+
+       if (i != 0x01)
+               deb_info("i2c_path setting failed.\n");
+
+       st->cur_i2c_path = path;
+}
+
+static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
+{
+       struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       int i;
+
+       if (down_interruptible(&d->i2c_sem) < 0)
+               return -EAGAIN;
+
+       if (num > 2)
+               warn("more than 2 i2c messages at a time is not handled yet. TODO.");
+
+       for (i = 0; i < num; i++) {
+
+               switch (msg[i].addr) {
+                       case 0x63:
+                               cxusb_set_i2c_path(d,PATH_CX22702);
+                               break;
+                       default:
+                               cxusb_set_i2c_path(d,PATH_TUNER_OTHER);
+                               break;
+               }
+
+               /* read request */
+               if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+                       u8 obuf[3+msg[i].len], ibuf[1+msg[i+1].len];
+                       obuf[0] = msg[i].len;
+                       obuf[1] = msg[i+1].len;
+                       obuf[2] = msg[i].addr;
+                       memcpy(&obuf[3],msg[i].buf,msg[i].len);
+
+                       if (cxusb_ctrl_msg(d, CMD_I2C_READ,
+                                               obuf, 3+msg[i].len,
+                                               ibuf, 1+msg[i+1].len) < 0)
+                               break;
+
+                       if (ibuf[0] != 0x08)
+                               deb_info("i2c read could have been failed\n");
+
+                       memcpy(msg[i+1].buf,&ibuf[1],msg[i+1].len);
+
+                       i++;
+               } else { /* write */
+                       u8 obuf[2+msg[i].len], ibuf;
+                       obuf[0] = msg[i].addr;
+                       obuf[1] = msg[i].len;
+                       memcpy(&obuf[2],msg[i].buf,msg[i].len);
+
+                       if (cxusb_ctrl_msg(d,CMD_I2C_WRITE, obuf, 2+msg[i].len, &ibuf,1) < 0)
+                               break;
+                       if (ibuf != 0x08)
+                               deb_info("i2c write could have been failed\n");
+               }
+       }
+
+       up(&d->i2c_sem);
+       return i;
+}
+
+static u32 cxusb_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm cxusb_i2c_algo = {
+       .name          = "Conexant USB I2C algorithm",
+       .id            = I2C_ALGO_BIT,
+       .master_xfer   = cxusb_i2c_xfer,
+       .functionality = cxusb_i2c_func,
+};
+
+static int cxusb_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+       return 0;
+}
+
+static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+{
+       u8 buf[2] = { 0x03, 0x00 };
+       if (onoff)
+               cxusb_ctrl_msg(d,0x36, buf, 2, NULL, 0);
+       else
+               cxusb_ctrl_msg(d,0x37, NULL, 0, NULL, 0);
+
+       return 0;
+}
+
+struct cx22702_config cxusb_cx22702_config = {
+       .demod_address = 0x63,
+
+       .output_mode = CX22702_PARALLEL_OUTPUT,
+
+       .pll_init = dvb_usb_pll_init_i2c,
+       .pll_set  = dvb_usb_pll_set_i2c,
+};
+
+/* Callbacks for DVB USB */
+static int cxusb_tuner_attach(struct dvb_usb_device *d)
+{
+       u8 bpll[4] = { 0x0b, 0xdc, 0x9c, 0xa0 };
+       d->pll_addr = 0x61;
+       memcpy(d->pll_init,bpll,4);
+       d->pll_desc = &dvb_pll_fmd1216me;
+       return 0;
+}
+
+static int cxusb_frontend_attach(struct dvb_usb_device *d)
+{
+       u8 buf[2] = { 0x03, 0x00 };
+       u8 b = 0;
+
+       if (usb_set_interface(d->udev,0,0) < 0)
+               err("set interface to alts=0 failed");
+
+       cxusb_ctrl_msg(d,0xde,&b,0,NULL,0);
+       cxusb_set_i2c_path(d,PATH_TUNER_OTHER);
+       cxusb_ctrl_msg(d,CMD_POWER_OFF, NULL, 0, &b, 1);
+
+       if (usb_set_interface(d->udev,0,6) < 0)
+               err("set interface failed");
+
+       cxusb_ctrl_msg(d,0x36, buf, 2, NULL, 0);
+       cxusb_set_i2c_path(d,PATH_CX22702);
+       cxusb_ctrl_msg(d,CMD_POWER_ON, NULL, 0, &b, 1);
+
+       if ((d->fe = cx22702_attach(&cxusb_cx22702_config, &d->i2c_adap)) != NULL)
+               return 0;
+
+       return -EIO;
+}
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_properties cxusb_properties;
+
+static int cxusb_probe(struct usb_interface *intf,
+               const struct usb_device_id *id)
+{
+       return dvb_usb_device_init(intf,&cxusb_properties,THIS_MODULE);
+}
+
+static struct usb_device_id cxusb_table [] = {
+               { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
+               {}              /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, cxusb_table);
+
+static struct dvb_usb_properties cxusb_properties = {
+       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+       .usb_ctrl = CYPRESS_FX2,
+
+       .size_of_priv     = sizeof(struct cxusb_state),
+
+       .streaming_ctrl   = cxusb_streaming_ctrl,
+       .power_ctrl       = cxusb_power_ctrl,
+       .frontend_attach  = cxusb_frontend_attach,
+       .tuner_attach     = cxusb_tuner_attach,
+
+       .i2c_algo         = &cxusb_i2c_algo,
+
+       .generic_bulk_ctrl_endpoint = 0x01,
+       /* parameter for the MPEG2-data transfer */
+       .urb = {
+               .type = DVB_USB_ISOC,
+               .count = 5,
+               .endpoint = 0x02,
+               .u = {
+                       .isoc = {
+                               .framesperurb = 32,
+                               .framesize = 940,
+                               .interval = 5,
+                       }
+               }
+       },
+
+       .num_device_descs = 1,
+       .devices = {
+               {   "Medion MD95700 (MDUSBTV-HYBRID)",
+                       { NULL },
+                       { &cxusb_table[0], NULL },
+               },
+       }
+};
+
+static struct usb_driver cxusb_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "dvb_usb_cxusb",
+       .probe          = cxusb_probe,
+       .disconnect = dvb_usb_device_exit,
+       .id_table       = cxusb_table,
+};
+
+/* module stuff */
+static int __init cxusb_module_init(void)
+{
+       int result;
+       if ((result = usb_register(&cxusb_driver))) {
+               err("usb_register failed. Error number %d",result);
+               return result;
+       }
+
+       return 0;
+}
+
+static void __exit cxusb_module_exit(void)
+{
+       /* deregister this driver from the USB subsystem */
+       usb_deregister(&cxusb_driver);
+}
+
+module_init (cxusb_module_init);
+module_exit (cxusb_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design");
+MODULE_VERSION("1.0-alpha");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h
new file mode 100644 (file)
index 0000000..1d79016
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef _DVB_USB_CXUSB_H_
+#define _DVB_USB_CXUSB_H_
+
+#define DVB_USB_LOG_PREFIX "digitv"
+#include "dvb-usb.h"
+
+extern int dvb_usb_cxusb_debug;
+#define deb_info(args...)   dprintk(dvb_usb_cxusb_debug,0x01,args)
+
+/* usb commands - some of it are guesses, don't have a reference yet */
+#define CMD_I2C_WRITE    0x08
+#define CMD_I2C_READ     0x09
+
+#define CMD_IOCTL        0x0e
+#define    IOCTL_SET_I2C_PATH 0x02
+
+#define CMD_POWER_OFF    0x50
+#define CMD_POWER_ON     0x51
+
+enum cxusb_i2c_pathes {
+       PATH_UNDEF       = 0x00,
+       PATH_CX22702     = 0x01,
+       PATH_TUNER_OTHER = 0x02,
+};
+
+struct cxusb_state {
+       enum cxusb_i2c_pathes cur_i2c_path;
+};
+
+#endif
index a0ffbb59fa144925823d13afc8718553fe970626..828b5182e16c31b62bbbd7f1b906225a511d2258 100644 (file)
@@ -31,10 +31,17 @@ static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d)
        return 0;
 }
 
-/* some of the dibusb 1.1 device aren't equipped with the default tuner
+static int dibusb_thomson_tuner_attach(struct dvb_usb_device *d)
+{
+       d->pll_addr = 0x61;
+       d->pll_desc = &dvb_pll_tua6010xs;
+       return 0;
+}
+
+/* Some of the Artec 1.1 device aren't equipped with the default tuner
  * (Thomson Cable), but with a Panasonic ENV77H11D5.  This function figures
  * this out. */
-static int dibusb_dib3000mb_tuner_attach (struct dvb_usb_device *d)
+static int dibusb_tuner_probe_and_attach(struct dvb_usb_device *d)
 {
        u8 b[2] = { 0,0 }, b2[1];
        int ret = 0;
@@ -59,8 +66,7 @@ static int dibusb_dib3000mb_tuner_attach (struct dvb_usb_device *d)
 
        if (b2[0] == 0xfe) {
                info("this device has the Thomson Cable onboard. Which is default.");
-               d->pll_addr = 0x61;
-               d->pll_desc = &dvb_pll_tua6010xs;
+               dibusb_thomson_tuner_attach(d);
        } else {
                u8 bpll[4] = { 0x0b, 0xf5, 0x85, 0xab };
                info("this device has the Panasonic ENV77H11D5 onboard.");
@@ -90,8 +96,8 @@ static int dibusb_probe(struct usb_interface *intf,
 
 /* do not change the order of the ID table */
 static struct usb_device_id dibusb_dib3000mb_table [] = {
-/* 00 */       { USB_DEVICE(USB_VID_AVERMEDIA_UNK,     USB_PID_AVERMEDIA_DVBT_USB_COLD)},
-/* 01 */       { USB_DEVICE(USB_VID_AVERMEDIA_UNK,     USB_PID_AVERMEDIA_DVBT_USB_WARM)},
+/* 00 */       { USB_DEVICE(USB_VID_WIDEVIEW,          USB_PID_AVERMEDIA_DVBT_USB_COLD)},
+/* 01 */       { USB_DEVICE(USB_VID_WIDEVIEW,          USB_PID_AVERMEDIA_DVBT_USB_WARM)},
 /* 02 */       { USB_DEVICE(USB_VID_COMPRO,            USB_PID_COMPRO_DVBU2000_COLD) },
 /* 03 */       { USB_DEVICE(USB_VID_COMPRO,            USB_PID_COMPRO_DVBU2000_WARM) },
 /* 04 */       { USB_DEVICE(USB_VID_COMPRO_UNK,        USB_PID_COMPRO_DVBU2000_UNK_COLD) },
@@ -114,7 +120,17 @@ static struct usb_device_id dibusb_dib3000mb_table [] = {
 /* 21 */       { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
 /* 22 */       { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
 /* 23 */       { USB_DEVICE(USB_VID_ADSTECH,           USB_PID_ADSTECH_USB2_COLD) },
+
+/* device ID with default DIBUSB2_0-firmware and with the hacked firmware */
 /* 24 */       { USB_DEVICE(USB_VID_ADSTECH,           USB_PID_ADSTECH_USB2_WARM) },
+/* 25 */       { USB_DEVICE(USB_VID_KYE,                       USB_PID_KYE_DVB_T_COLD) },
+/* 26 */       { USB_DEVICE(USB_VID_KYE,                       USB_PID_KYE_DVB_T_WARM) },
+
+// #define DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
+
+#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
+/* 27 */       { USB_DEVICE(USB_VID_ANCHOR,            USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
+#endif
                        { }             /* Terminating entry */
 };
 MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table);
@@ -134,7 +150,7 @@ static struct dvb_usb_properties dibusb1_1_properties = {
        .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
        .power_ctrl       = dibusb_power_ctrl,
        .frontend_attach  = dibusb_dib3000mb_frontend_attach,
-       .tuner_attach     = dibusb_dib3000mb_tuner_attach,
+       .tuner_attach     = dibusb_tuner_probe_and_attach,
 
        .rc_interval      = DEFAULT_RC_INTERVAL,
        .rc_key_map       = dibusb_rc_keys,
@@ -156,7 +172,7 @@ static struct dvb_usb_properties dibusb1_1_properties = {
                }
        },
 
-       .num_device_descs = 8,
+       .num_device_descs = 9,
        .devices = {
                {       "AVerMedia AverTV DVBT USB1.1",
                        { &dibusb_dib3000mb_table[0],  NULL },
@@ -190,11 +206,17 @@ static struct dvb_usb_properties dibusb1_1_properties = {
                        { &dibusb_dib3000mb_table[19], NULL },
                        { &dibusb_dib3000mb_table[20], NULL },
                },
+               {       "VideoWalker DVB-T USB",
+                       { &dibusb_dib3000mb_table[25], NULL },
+                       { &dibusb_dib3000mb_table[26], NULL },
+               },
        }
 };
 
 static struct dvb_usb_properties dibusb1_1_an2235_properties = {
        .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+       .pid_filter_count = 16,
+
        .usb_ctrl = CYPRESS_AN2235,
 
        .firmware = "dvb-usb-dibusb-an2235-01.fw",
@@ -206,7 +228,7 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
        .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
        .power_ctrl       = dibusb_power_ctrl,
        .frontend_attach  = dibusb_dib3000mb_frontend_attach,
-       .tuner_attach     = dibusb_dib3000mb_tuner_attach,
+       .tuner_attach     = dibusb_tuner_probe_and_attach,
 
        .rc_interval      = DEFAULT_RC_INTERVAL,
        .rc_key_map       = dibusb_rc_keys,
@@ -228,20 +250,32 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
                }
        },
 
+#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
+       .num_device_descs = 2,
+#else
        .num_device_descs = 1,
+#endif
        .devices = {
                {       "Artec T1 USB1.1 TVBOX with AN2235",
                        { &dibusb_dib3000mb_table[20], NULL },
                        { &dibusb_dib3000mb_table[21], NULL },
                },
+#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
+               {       "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)",
+                       { &dibusb_dib3000mb_table[27], NULL },
+                       { NULL },
+               },
+#endif
        }
 };
 
 static struct dvb_usb_properties dibusb2_0b_properties = {
        .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+       .pid_filter_count = 32,
+
        .usb_ctrl = CYPRESS_FX2,
 
-       .firmware = "dvb-usb-adstech-usb2-01.fw",
+       .firmware = "dvb-usb-adstech-usb2-02.fw",
 
        .size_of_priv     = sizeof(struct dibusb_state),
 
@@ -250,7 +284,7 @@ static struct dvb_usb_properties dibusb2_0b_properties = {
        .pid_filter_ctrl  = dibusb_pid_filter_ctrl,
        .power_ctrl       = dibusb2_0_power_ctrl,
        .frontend_attach  = dibusb_dib3000mb_frontend_attach,
-       .tuner_attach     = dibusb_dib3000mb_tuner_attach,
+       .tuner_attach     = dibusb_thomson_tuner_attach,
 
        .rc_interval      = DEFAULT_RC_INTERVAL,
        .rc_key_map       = dibusb_rc_keys,
@@ -272,18 +306,18 @@ static struct dvb_usb_properties dibusb2_0b_properties = {
                }
        },
 
-       .num_device_descs = 2,
+       .num_device_descs = 1,
        .devices = {
                {       "KWorld/ADSTech Instant DVB-T USB 2.0",
                        { &dibusb_dib3000mb_table[23], NULL },
-                       { &dibusb_dib3000mb_table[24], NULL }, /* device ID with default DIBUSB2_0-firmware */
+                       { &dibusb_dib3000mb_table[24], NULL },
                },
        }
 };
 
 static struct usb_driver dibusb_driver = {
        .owner          = THIS_MODULE,
-       .name           = "DiBcom based USB DVB-T devices (DiB3000M-B based)",
+       .name           = "dvb_usb_dibusb_mb",
        .probe          = dibusb_probe,
        .disconnect = dvb_usb_device_exit,
        .id_table       = dibusb_dib3000mb_table,
index aad8ed3fe005f821c8c03b2cc9cd3f4fac99a053..e9dac430f37da036079d2ea50a77ae8113ad63eb 100644 (file)
@@ -83,7 +83,7 @@ static struct dvb_usb_properties dibusb_mc_properties = {
 
 static struct usb_driver dibusb_mc_driver = {
        .owner          = THIS_MODULE,
-       .name           = "DiBcom based USB2.0 DVB-T (DiB3000M-C/P based) devices",
+       .name           = "dvb_usb_dibusb_mc",
        .probe          = dibusb_mc_probe,
        .disconnect = dvb_usb_device_exit,
        .id_table       = dibusb_dib3000mc_table,
index 5acf3fde95226f68a0c25fc7c3d6551c8932794f..9a676afc1d6e89c4943db39b1e3a93202adbf033 100644 (file)
@@ -1,10 +1,9 @@
 /* DVB USB compliant linux driver for Nebula Electronics uDigiTV DVB-T USB2.0
  * receiver
  *
- * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) and
- *                    Allan Third (allan.third@cs.man.ac.uk)
+ * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
  *
- * partly based on the SDK published by Nebula Electronics (TODO do we want this line ?)
+ * partly based on the SDK published by Nebula Electronics
  *
  *     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
@@ -38,7 +37,7 @@ static int digitv_ctrl_msg(struct dvb_usb_device *d,
                dvb_usb_generic_write(d,sndbuf,7);
        } else {
                dvb_usb_generic_rw(d,sndbuf,7,rcvbuf,7,10);
-               memcpy(&rbuf,&rcvbuf[3],rlen);
+               memcpy(rbuf,&rcvbuf[3],rlen);
        }
        return 0;
 }
@@ -95,41 +94,20 @@ static int digitv_identify_state (struct usb_device *udev, struct
 
 static int digitv_mt352_demod_init(struct dvb_frontend *fe)
 {
-       static u8 mt352_clock_config[] = { 0x89, 0x38, 0x2d };
-       static u8 mt352_reset[] = { 0x50, 0x80 };
-       static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 };
-
-       static u8 mt352_agc_cfg[] = { 0x68, 0xa0 };
-       static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0xa0 };
-       static u8 mt352_acq_ctl[] = { 0x53, 0x50 };
-       static u8 mt352_agc_target[] = { 0x67, 0x20 };
-
-       static u8 mt352_rs_err_per[] = { 0x7c, 0x00, 0x01 };
-       static u8 mt352_snr_select[] = { 0x79, 0x00, 0x20 };
-
-       static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x05 };
+       static u8 reset_buf[] = { 0x89, 0x38,  0x8a, 0x2d, 0x50, 0x80 };
+       static u8 init_buf[] = { 0x68, 0xa0,  0x8e, 0x40,  0x53, 0x50,
+                       0x67, 0x20,  0x7d, 0x01,  0x7c, 0x00,  0x7a, 0x00,
+                       0x79, 0x20,  0x57, 0x05,  0x56, 0x31,  0x88, 0x0f,
+                       0x75, 0x32 };
+       int i;
 
-       static u8 mt352_scan_ctl[] = { 0x88, 0x0f };
-       static u8 mt352_capt_range[] = { 0x75, 0x32 };
+       for (i = 0; i < ARRAY_SIZE(reset_buf); i += 2)
+               mt352_write(fe, &reset_buf[i], 2);
 
-       mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
-       mt352_write(fe, mt352_reset, sizeof(mt352_reset));
        msleep(1);
-       mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio));
-
-       mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
-       mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
-       mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl));
-       mt352_write(fe, mt352_agc_target, sizeof(mt352_agc_target));
-
-
-       mt352_write(fe, mt352_rs_err_per, sizeof(mt352_rs_err_per));
-       mt352_write(fe, mt352_snr_select, sizeof(mt352_snr_select));
 
-       mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1));
-
-       mt352_write(fe, mt352_scan_ctl, sizeof(mt352_scan_ctl));
-       mt352_write(fe, mt352_capt_range, sizeof(mt352_capt_range));
+       for (i = 0; i < ARRAY_SIZE(init_buf); i += 2)
+               mt352_write(fe, &init_buf[i], 2);
 
        return 0;
 }
@@ -137,7 +115,7 @@ static int digitv_mt352_demod_init(struct dvb_frontend *fe)
 static struct mt352_config digitv_mt352_config = {
        .demod_address = 0x0, /* ignored by the digitv anyway */
        .demod_init = digitv_mt352_demod_init,
-       .pll_set = NULL, /* TODO */
+       .pll_set = dvb_usb_pll_set,
 };
 
 static struct nxt6000_config digitv_nxt6000_config = {
@@ -150,9 +128,9 @@ static struct nxt6000_config digitv_nxt6000_config = {
 
 static int digitv_frontend_attach(struct dvb_usb_device *d)
 {
-       if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) == NULL)
+       if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL)
                return 0;
-       if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) == NULL) {
+       if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL) {
 
                warn("nxt6000 support is not done yet, in fact you are one of the first "
                                "person who wants to use this device in Linux. Please report to "
@@ -163,6 +141,13 @@ static int digitv_frontend_attach(struct dvb_usb_device *d)
        return -EIO;
 }
 
+static int digitv_tuner_attach(struct dvb_usb_device *d)
+{
+       d->pll_addr = 0x60;
+       d->pll_desc = &dvb_pll_tded4;
+       return 0;
+}
+
 static struct dvb_usb_rc_key digitv_rc_keys[] = {
        { 0x00, 0x16, KEY_POWER }, /* dummy key */
 };
@@ -184,7 +169,6 @@ int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
        return 0;
 }
 
-
 /* DVB USB Driver stuff */
 static struct dvb_usb_properties digitv_properties;
 
@@ -208,13 +192,8 @@ static struct dvb_usb_properties digitv_properties = {
 
        .size_of_priv     = 0,
 
-       .streaming_ctrl   = NULL,
-       .pid_filter       = NULL,
-       .pid_filter_ctrl  = NULL,
-       .power_ctrl       = NULL,
        .frontend_attach  = digitv_frontend_attach,
-       .tuner_attach     = NULL, // digitv_tuner_attach,
-       .read_mac_address = NULL,
+       .tuner_attach     = digitv_tuner_attach,
 
        .rc_interval      = 1000,
        .rc_key_map       = digitv_rc_keys,
@@ -238,7 +217,7 @@ static struct dvb_usb_properties digitv_properties = {
                }
        },
 
-       .num_device_descs = 2,
+       .num_device_descs = 1,
        .devices = {
                {   "Nebula Electronics uDigiTV DVB-T USB2.0)",
                        { &digitv_table[0], NULL },
@@ -249,7 +228,7 @@ static struct dvb_usb_properties digitv_properties = {
 
 static struct usb_driver digitv_driver = {
        .owner          = THIS_MODULE,
-       .name           = "Nebula Electronics uDigiTV DVB-T USB2.0 device",
+       .name           = "dvb_usb_digitv",
        .probe          = digitv_probe,
        .disconnect = dvb_usb_device_exit,
        .id_table       = digitv_table,
index d17d768038c62a60c8c639efb6e47e7e0a563df0..b032523b07bc42aaeac7116926e6a7824e7702ed 100644 (file)
@@ -1,5 +1,5 @@
-/* Frontend part of the Linux driver for the Yakumo/Hama/Typhoon DVB-T
- * USB2.0 receiver.
+/* Frontend part of the Linux driver for the WideView/ Yakumo/ Hama/
+ * Typhoon/ Yuan DVB-T USB2.0 receiver.
  *
  * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
  *
 struct dtt200u_fe_state {
        struct dvb_usb_device *d;
 
+       fe_status_t stat;
+
        struct dvb_frontend_parameters fep;
        struct dvb_frontend frontend;
 };
 
-#define moan(which,what) info("unexpected value in '%s' for cmd '%02x' - please report to linux-dvb@linuxtv.org",which,what)
-
 static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
 {
        struct dtt200u_fe_state *state = fe->demodulator_priv;
-       u8 bw = GET_TUNE_STAT;
-       u8 br[3] = { 0 };
-//     u8 bdeb[5] = { 0 };
+       u8 st = GET_TUNE_STATUS, b[3];
+
+       dvb_usb_generic_rw(state->d,&st,1,b,3,0);
 
-       dvb_usb_generic_rw(state->d,&bw,1,br,3,0);
-       switch (br[0]) {
+       switch (b[0]) {
                case 0x01:
-                       *stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+                       *stat = FE_HAS_SIGNAL | FE_HAS_CARRIER |
+                               FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
                        break;
-               case 0x00:
-                       *stat = 0;
+               case 0x00: /* pending */
+                       *stat = FE_TIMEDOUT; /* during set_frontend */
                        break;
                default:
-                       moan("br[0]",GET_TUNE_STAT);
+               case 0x02: /* failed */
+                       *stat = 0;
                        break;
        }
-
-//     bw[0] = 0x88;
-//     dvb_usb_generic_rw(state->d,bw,1,bdeb,5,0);
-
-//     deb_info("%02x: %02x %02x %02x %02x %02x\n",bw[0],bdeb[0],bdeb[1],bdeb[2],bdeb[3],bdeb[4]);
-
        return 0;
 }
+
 static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
 {
        struct dtt200u_fe_state *state = fe->demodulator_priv;
-       u8 bw = GET_BER;
-       *ber = 0;
-       dvb_usb_generic_rw(state->d,&bw,1,(u8*) ber,3,0);
+       u8 bw = GET_VIT_ERR_CNT,b[3];
+       dvb_usb_generic_rw(state->d,&bw,1,b,3,0);
+       *ber = (b[0] << 16) | (b[1] << 8) | b[2];
        return 0;
 }
 
 static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
 {
        struct dtt200u_fe_state *state = fe->demodulator_priv;
-       u8 bw = GET_UNK;
-       *unc = 0;
-       dvb_usb_generic_rw(state->d,&bw,1,(u8*) unc,3,0);
+       u8 bw = GET_RS_UNCOR_BLK_CNT,b[2];
+
+       dvb_usb_generic_rw(state->d,&bw,1,b,2,0);
+       *unc = (b[0] << 8) | b[1];
        return 0;
 }
 
 static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
 {
        struct dtt200u_fe_state *state = fe->demodulator_priv;
-       u8 bw = GET_SIG_STRENGTH, b;
+       u8 bw = GET_AGC, b;
        dvb_usb_generic_rw(state->d,&bw,1,&b,1,0);
        *strength = (b << 8) | b;
        return 0;
@@ -86,7 +83,7 @@ static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
 static int dtt200u_fe_init(struct dvb_frontend* fe)
 {
        struct dtt200u_fe_state *state = fe->demodulator_priv;
-       u8 b = RESET_DEMOD;
+       u8 b = SET_INIT;
        return dvb_usb_generic_write(state->d,&b,1);
 }
 
@@ -98,8 +95,8 @@ static int dtt200u_fe_sleep(struct dvb_frontend* fe)
 static int dtt200u_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
 {
        tune->min_delay_ms = 1500;
-       tune->step_size = 166667;
-       tune->max_drift = 166667 * 2;
+       tune->step_size = 0;
+       tune->max_drift = 0;
        return 0;
 }
 
@@ -107,27 +104,32 @@ static int dtt200u_fe_set_frontend(struct dvb_frontend* fe,
                                  struct dvb_frontend_parameters *fep)
 {
        struct dtt200u_fe_state *state = fe->demodulator_priv;
+       int i;
+       fe_status_t st;
        u16 freq = fep->frequency / 250000;
-       u8 bw,bwbuf[2] = { SET_BANDWIDTH, 0 }, freqbuf[3] = { SET_FREQUENCY, 0, 0 };
+       u8 bwbuf[2] = { SET_BANDWIDTH, 0 },freqbuf[3] = { SET_RF_FREQ, 0, 0 };
 
        switch (fep->u.ofdm.bandwidth) {
-               case BANDWIDTH_8_MHZ: bw = 8; break;
-               case BANDWIDTH_7_MHZ: bw = 7; break;
-               case BANDWIDTH_6_MHZ: bw = 6; break;
+               case BANDWIDTH_8_MHZ: bwbuf[1] = 8; break;
+               case BANDWIDTH_7_MHZ: bwbuf[1] = 7; break;
+               case BANDWIDTH_6_MHZ: bwbuf[1] = 6; break;
                case BANDWIDTH_AUTO: return -EOPNOTSUPP;
                default:
                        return -EINVAL;
        }
-       deb_info("set_frontend\n");
 
-       bwbuf[1] = bw;
        dvb_usb_generic_write(state->d,bwbuf,2);
 
        freqbuf[1] = freq & 0xff;
        freqbuf[2] = (freq >> 8) & 0xff;
        dvb_usb_generic_write(state->d,freqbuf,3);
 
-       memcpy(&state->fep,fep,sizeof(struct dvb_frontend_parameters));
+       for (i = 0; i < 30; i++) {
+               msleep(20);
+               dtt200u_fe_read_status(fe, &st);
+               if (st & FE_TIMEDOUT)
+                       continue;
+       }
 
        return 0;
 }
@@ -174,7 +176,7 @@ success:
 
 static struct dvb_frontend_ops dtt200u_fe_ops = {
        .info = {
-               .name                   = "DTT200U (Yakumo/Typhoon/Hama) DVB-T",
+               .name                   = "WideView USB DVB-T",
                .type                   = FE_OFDM,
                .frequency_min          = 44250000,
                .frequency_max          = 867250000,
index fb2b5a2da13755222ce0bdfa7714de2464f6feae..47dba6e45968b9095c02f1ec709a230e69f5270e 100644 (file)
@@ -1,8 +1,10 @@
-/* DVB USB library compliant Linux driver for the Yakumo/Hama/Typhoon DVB-T
- * USB2.0 receiver.
+/* DVB USB library compliant Linux driver for the WideView/ Yakumo/ Hama/
+ * Typhoon/ Yuan DVB-T USB2.0 receiver.
  *
  * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
  *
+ * Thanks to Steve Chang from WideView for providing support for the WT-220U.
+ *
  *     This program is free software; you can redistribute it and/or modify it
  *     under the terms of the GNU General Public License as published by the Free
  *     Software Foundation, version 2.
@@ -16,14 +18,24 @@ int dvb_usb_dtt200u_debug;
 module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS);
 
+static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+       u8 b = SET_INIT;
+
+       if (onoff)
+               dvb_usb_generic_write(d,&b,2);
+
+       return 0;
+}
+
 static int dtt200u_streaming_ctrl(struct dvb_usb_device *d, int onoff)
 {
-       u8 b_streaming[2] = { SET_TS_CTRL, onoff };
+       u8 b_streaming[2] = { SET_STREAMING, onoff };
        u8 b_rst_pid = RESET_PID_FILTER;
 
        dvb_usb_generic_write(d,b_streaming,2);
 
-       if (!onoff)
+       if (onoff == 0)
                dvb_usb_generic_write(d,&b_rst_pid,1);
        return 0;
 }
@@ -36,7 +48,7 @@ static int dtt200u_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int
        b_pid[0] = SET_PID_FILTER;
        b_pid[1] = index;
        b_pid[2] = pid & 0xff;
-       b_pid[3] = (pid >> 8) & 0xff;
+       b_pid[3] = (pid >> 8) & 0x1f;
 
        return dvb_usb_generic_write(d,b_pid,4);
 }
@@ -54,9 +66,9 @@ static struct dvb_usb_rc_key dtt200u_rc_keys[] = {
        { 0x80, 0x08, KEY_5 },
        { 0x80, 0x09, KEY_6 },
        { 0x80, 0x0a, KEY_7 },
-       { 0x00, 0x0c, KEY_ZOOM },
+       { 0x80, 0x0c, KEY_ZOOM },
        { 0x80, 0x0d, KEY_0 },
-       { 0x00, 0x0e, KEY_SELECT },
+       { 0x80, 0x0e, KEY_SELECT },
        { 0x80, 0x12, KEY_POWER },
        { 0x80, 0x1a, KEY_CHANNELUP },
        { 0x80, 0x1b, KEY_8 },
@@ -66,7 +78,7 @@ static struct dvb_usb_rc_key dtt200u_rc_keys[] = {
 
 static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
-       u8 key[5],cmd = GET_RC_KEY;
+       u8 key[5],cmd = GET_RC_CODE;
        dvb_usb_generic_rw(d,&cmd,1,key,5,0);
        dvb_usb_nec_rc_key_to_event(d,key,event,state);
        if (key[0] != 0)
@@ -81,32 +93,41 @@ static int dtt200u_frontend_attach(struct dvb_usb_device *d)
 }
 
 static struct dvb_usb_properties dtt200u_properties;
+static struct dvb_usb_properties wt220u_properties;
 
 static int dtt200u_usb_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE);
+       if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE) == 0 ||
+               dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE) == 0)
+               return 0;
+
+       return -ENODEV;
 }
 
 static struct usb_device_id dtt200u_usb_table [] = {
-           { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_DTT200U_COLD) },
-           { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_DTT200U_WARM) },
+//             { USB_DEVICE(0x04b4,0x8613) },
+           { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_COLD) },
+           { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_WARM) },
+               { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_COLD)  },
+               { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_WARM)  },
            { 0 },
 };
 MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
 
 static struct dvb_usb_properties dtt200u_properties = {
        .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
-       .pid_filter_count = 255, /* It is a guess, but there are at least 10 */
+       .pid_filter_count = 15,
 
        .usb_ctrl = CYPRESS_FX2,
        .firmware = "dvb-usb-dtt200u-01.fw",
 
+       .power_ctrl      = dtt200u_power_ctrl,
        .streaming_ctrl  = dtt200u_streaming_ctrl,
        .pid_filter      = dtt200u_pid_filter,
        .frontend_attach = dtt200u_frontend_attach,
 
-       .rc_interval     = 200,
+       .rc_interval     = 300,
        .rc_key_map      = dtt200u_rc_keys,
        .rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
        .rc_query        = dtt200u_rc_query,
@@ -127,18 +148,59 @@ static struct dvb_usb_properties dtt200u_properties = {
 
        .num_device_descs = 1,
        .devices = {
-               { .name = "Yakumo/Hama/Typhoon DVB-T USB2.0)",
-                 .cold_ids = { &dtt200u_usb_table[0], &dtt200u_usb_table[2] },
+               { .name = "WideView/Yuan/Yakumo/Hama/Typhoon DVB-T USB2.0 (WT-200U)",
+                 .cold_ids = { &dtt200u_usb_table[0], NULL },
                  .warm_ids = { &dtt200u_usb_table[1], NULL },
                },
                { 0 },
        }
 };
 
+static struct dvb_usb_properties wt220u_properties = {
+       .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
+       .pid_filter_count = 15,
+
+       .usb_ctrl = CYPRESS_FX2,
+       .firmware = "dvb-usb-wt220u-01.fw",
+
+       .power_ctrl      = dtt200u_power_ctrl,
+       .streaming_ctrl  = dtt200u_streaming_ctrl,
+       .pid_filter      = dtt200u_pid_filter,
+       .frontend_attach = dtt200u_frontend_attach,
+
+       .rc_interval     = 300,
+       .rc_key_map      = dtt200u_rc_keys,
+       .rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
+       .rc_query        = dtt200u_rc_query,
+
+       .generic_bulk_ctrl_endpoint = 0x01,
+
+       /* parameter for the MPEG2-data transfer */
+       .urb = {
+               .type = DVB_USB_BULK,
+               .count = 7,
+               .endpoint = 0x02,
+               .u = {
+                       .bulk = {
+                               .buffersize = 4096,
+                       }
+               }
+       },
+
+       .num_device_descs = 1,
+       .devices = {
+               { .name = "WideView WT-220U PenType Receiver (and clones)",
+                 .cold_ids = { &dtt200u_usb_table[2], NULL },
+                 .warm_ids = { &dtt200u_usb_table[3], NULL },
+               },
+               { 0 },
+       }
+};
+
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver dtt200u_usb_driver = {
        .owner          = THIS_MODULE,
-       .name           = "Yakumo/Hama/Typhoon DVB-T USB2.0",
+       .name           = "dvb_usb_dtt200u",
        .probe          = dtt200u_usb_probe,
        .disconnect = dvb_usb_device_exit,
        .id_table       = dtt200u_usb_table,
@@ -166,6 +228,6 @@ module_init(dtt200u_usb_module_init);
 module_exit(dtt200u_usb_module_exit);
 
 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_DESCRIPTION("Driver for the Yakumo/Hama/Typhoon DVB-T USB2.0 device");
+MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon DVB-T USB2.0 devices");
 MODULE_VERSION("1.0");
 MODULE_LICENSE("GPL");
index ed41420715180332e81e816086224891aa862be3..6f1f3042e21a54a5ce3f70be303601d66d5670dc 100644 (file)
@@ -1,5 +1,5 @@
-/* Common header file of Linux driver for the Yakumo/Hama/Typhoon DVB-T
- * USB2.0 receiver.
+/* Common header file of Linux driver for the WideView/ Yakumo/ Hama/
+ * Typhoon/ Yuan DVB-T USB2.0 receiver.
  *
  * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
  *
@@ -22,44 +22,34 @@ extern int dvb_usb_dtt200u_debug;
 /* guessed protocol description (reverse engineered):
  * read
  *  00 - USB type 0x02 for usb2.0, 0x01 for usb1.1
- *  81 - <TS_LOCK> <current frequency divided by 250000>
- *  82 - crash - do not touch
- *  83 - crash - do not touch
- *  84 - remote control
- *  85 - crash - do not touch (OK, stop testing here)
  *  88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal)
- *  89 - noise-to-signal
- *     8a - unkown 1 byte - signal_strength
- *  8c - ber ???
- *  8d - ber
- *  8e - unc
  */
 
-#define GET_SPEED        0x00
-#define GET_TUNE_STAT    0x81
-#define GET_RC_KEY       0x84
-#define GET_STATUS       0x88
-#define GET_SNR          0x89
-#define GET_SIG_STRENGTH 0x8a
-#define GET_UNK          0x8c
-#define GET_BER          0x8d
-#define GET_UNC          0x8e
+#define GET_SPEED            0x00
+#define GET_TUNE_STATUS      0x81
+#define GET_RC_CODE          0x84
+#define GET_CONFIGURATION    0x88
+#define GET_AGC              0x89
+#define GET_SNR              0x8a
+#define GET_VIT_ERR_CNT      0x8c
+#define GET_RS_ERR_CNT       0x8d
+#define GET_RS_UNCOR_BLK_CNT 0x8e
 
 /* write
- *  01 - reset the demod
+ *  01 - init
  *  02 - frequency (divided by 250000)
  *  03 - bandwidth
  *  04 - pid table (index pid(7:0) pid(12:8))
  *  05 - reset the pid table
- *  08 - demod transfer enabled or not (FX2 transfer is enabled by default)
+ *  08 - transfer switch
  */
 
-#define RESET_DEMOD      0x01
-#define SET_FREQUENCY    0x02
+#define SET_INIT         0x01
+#define SET_RF_FREQ      0x02
 #define SET_BANDWIDTH    0x03
 #define SET_PID_FILTER   0x04
 #define RESET_PID_FILTER 0x05
-#define SET_TS_CTRL      0x08
+#define SET_STREAMING    0x08
 
 extern struct dvb_frontend * dtt200u_fe_attach(struct dvb_usb_device *d);
 
index 67e0d73fbceb6626d14ea6a1f24d2527e0369c40..7300489d3e2420b66bcdf21450394faab5106e22 100644 (file)
 #include "dvb-usb.h"
 
 extern int dvb_usb_debug;
+extern int dvb_usb_disable_rc_polling;
 
 #define deb_info(args...) dprintk(dvb_usb_debug,0x01,args)
 #define deb_xfer(args...) dprintk(dvb_usb_debug,0x02,args)
-#define deb_pll(args...) dprintk(dvb_usb_debug,0x04,args)
+#define deb_pll(args...)  dprintk(dvb_usb_debug,0x04,args)
 #define deb_ts(args...)   dprintk(dvb_usb_debug,0x08,args)
 #define deb_err(args...)  dprintk(dvb_usb_debug,0x10,args)
 #define deb_rc(args...)   dprintk(dvb_usb_debug,0x20,args)
 #define deb_fw(args...)   dprintk(dvb_usb_debug,0x40,args)
+#define deb_mem(args...)  dprintk(dvb_usb_debug,0x80,args)
 
 /* commonly used  methods */
 extern int usb_cypress_load_firmware(struct usb_device *, const char *, int);
index bcb34191868b18677675031a08811500981771fe..794d513a8480f8b758262bf807f60dc99083a971 100644 (file)
@@ -12,7 +12,7 @@
 /* Vendor IDs */
 #define USB_VID_ADSTECH                                                0x06e1
 #define USB_VID_ANCHOR                                         0x0547
-#define USB_VID_AVERMEDIA_UNK                          0x14aa
+#define USB_VID_WIDEVIEW                                       0x14aa
 #define USB_VID_AVERMEDIA                                      0x07ca
 #define USB_VID_COMPRO                                         0x185b
 #define USB_VID_COMPRO_UNK                                     0x145f
@@ -24,6 +24,8 @@
 #define USB_VID_HANFTEK                                                0x15f4
 #define USB_VID_HAUPPAUGE                                      0x2040
 #define USB_VID_HYPER_PALTEK                           0x1025
+#define USB_VID_KYE                                                    0x0458
+#define USB_VID_MEDION                                         0x1660
 #define USB_VID_VISIONPLUS                                     0x13d3
 #define USB_VID_TWINHAN                                                0x1822
 #define USB_VID_ULTIMA_ELECTRONIC                      0x05d8
@@ -70,6 +72,8 @@
 #define USB_PID_HANFTEK_UMT_010_WARM           0x0015
 #define USB_PID_DTT200U_COLD                           0x0201
 #define USB_PID_DTT200U_WARM                           0x0301
+#define USB_PID_WT220U_COLD                                    0x0222
+#define USB_PID_WT220U_WARM                                    0x0221
 #define USB_PID_WINTV_NOVA_T_USB2_COLD         0x9300
 #define USB_PID_WINTV_NOVA_T_USB2_WARM         0x9301
 #define USB_PID_NEBULA_DIGITV                          0x0201
@@ -78,6 +82,8 @@
 #define USB_PID_DVICO_BLUEBIRD_LGDT                    0xd820
 #define USB_PID_DVICO_BLUEBIRD_LGZ201_1                0xdb01
 #define USB_PID_DVICO_BLUEBIRD_TH7579_2                0xdb11
-
+#define USB_PID_MEDION_MD95700                         0x0932
+#define USB_PID_KYE_DVB_T_COLD                         0x701e
+#define USB_PID_KYE_DVB_T_WARM                         0x701f
 
 #endif
index 3aadec974cf17b57d0a4c2b420532cd002c77545..c3b3ae4f3ec7a2475fe1f8c97b5638c9724e5bde 100644 (file)
@@ -18,6 +18,10 @@ int dvb_usb_debug;
 module_param_named(debug,dvb_usb_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))." DVB_USB_DEBUG_STATUS);
 
+int dvb_usb_disable_rc_polling;
+module_param_named(disable_rc_polling, dvb_usb_disable_rc_polling, int, 0644);
+MODULE_PARM_DESC(disable_rc_polling, "disable remote control polling (default: 0).");
+
 /* general initialization functions */
 int dvb_usb_exit(struct dvb_usb_device *d)
 {
index 9f1e23f82bae844eb8c09f279571cceeffccc036..fc7800f1743ee5c8747a6ea5d0dd17540ed738c8 100644 (file)
@@ -21,6 +21,10 @@ static void dvb_usb_read_remote_control(void *data)
        /* TODO: need a lock here.  We can simply skip checking for the remote control
           if we're busy. */
 
+       /* when the parameter has been set to 1 via sysfs while the driver was running */
+       if (dvb_usb_disable_rc_polling)
+               return;
+
        if (d->props.rc_query(d,&event,&state)) {
                err("error while querying for an remote control event.");
                goto schedule;
@@ -35,7 +39,7 @@ static void dvb_usb_read_remote_control(void *data)
                        d->last_event = event;
                case REMOTE_KEY_REPEAT:
                        deb_rc("key repeated\n");
-                       input_event(&d->rc_input_dev, EV_KEY, event, 1);
+                       input_event(&d->rc_input_dev, EV_KEY, d->last_event, 1);
                        input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0);
                        input_sync(&d->rc_input_dev);
                        break;
@@ -85,7 +89,9 @@ schedule:
 int dvb_usb_remote_init(struct dvb_usb_device *d)
 {
        int i;
-       if (d->props.rc_key_map == NULL)
+       if (d->props.rc_key_map == NULL ||
+               d->props.rc_query == NULL ||
+               dvb_usb_disable_rc_polling)
                return 0;
 
        /* Initialise the remote-control structures.*/
@@ -154,12 +160,12 @@ int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
                                break;
                        }
                        /* See if we can match the raw key code. */
-                       for (i = 0; i < sizeof(keymap)/sizeof(struct dvb_usb_rc_key); i++)
+                       for (i = 0; i < d->props.rc_key_map_size; i++)
                                if (keymap[i].custom == keybuf[1] &&
                                        keymap[i].data == keybuf[3]) {
                                        *event = keymap[i].event;
                                        *state = REMOTE_KEY_PRESSED;
-                                       break;
+                                       return 0;
                                }
                        deb_err("key mapping failed - no appropriate key found in keymapping\n");
                        break;
index 83d476fb410a2623fe7b9e15e25ae1a25e0bba93..f5799a4c228e9610aa11151e97505f5430820e96 100644 (file)
@@ -24,11 +24,12 @@ int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
        if ((ret = down_interruptible(&d->usb_sem)))
                return ret;
 
+       deb_xfer(">>> ");
        debug_dump(wbuf,wlen,deb_xfer);
 
        ret = usb_bulk_msg(d->udev,usb_sndbulkpipe(d->udev,
                        d->props.generic_bulk_ctrl_endpoint), wbuf,wlen,&actlen,
-                       2*HZ);
+                       2000);
 
        if (ret)
                err("bulk message failed: %d (%d/%d)",ret,wlen,actlen);
@@ -42,12 +43,14 @@ int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
 
                ret = usb_bulk_msg(d->udev,usb_rcvbulkpipe(d->udev,
                                d->props.generic_bulk_ctrl_endpoint),rbuf,rlen,&actlen,
-                               2*HZ);
+                               2000);
 
                if (ret)
                        err("recv bulk message failed: %d",ret);
-               else
+               else {
+                       deb_xfer("<<< ");
                        debug_dump(rbuf,actlen,deb_xfer);
+               }
        }
 
        up(&d->usb_sem);
@@ -61,12 +64,19 @@ int dvb_usb_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len)
 }
 EXPORT_SYMBOL(dvb_usb_generic_write);
 
-static void dvb_usb_bulk_urb_complete(struct urb *urb, struct pt_regs *ptregs)
+
+/* URB stuff for streaming */
+static void dvb_usb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
 {
        struct dvb_usb_device *d = urb->context;
+       int ptype = usb_pipetype(urb->pipe);
+       int i;
+       u8 *b;
 
-       deb_ts("bulk urb completed. feedcount: %d, status: %d, length: %d\n",d->feedcount,urb->status,
-                       urb->actual_length);
+       deb_ts("'%s' urb completed. feedcount: %d, status: %d, length: %d/%d, pack_num: %d, errors: %d\n",
+                       ptype == PIPE_ISOCHRONOUS ? "isoc" : "bulk", d->feedcount,
+                       urb->status,urb->actual_length,urb->transfer_buffer_length,
+                       urb->number_of_packets,urb->error_count);
 
        switch (urb->status) {
                case 0:         /* success */
@@ -81,11 +91,33 @@ static void dvb_usb_bulk_urb_complete(struct urb *urb, struct pt_regs *ptregs)
                        break;
        }
 
-       if (d->feedcount > 0 && urb->actual_length > 0) {
-               if (d->state & DVB_USB_STATE_DVB)
-                       dvb_dmx_swfilter(&d->demux, (u8*) urb->transfer_buffer,urb->actual_length);
-       } else
-               deb_ts("URB dropped because of feedcount.\n");
+       if (d->feedcount > 0) {
+               if (d->state & DVB_USB_STATE_DVB) {
+                       switch (ptype) {
+                               case PIPE_ISOCHRONOUS:
+                                       b = (u8 *) urb->transfer_buffer;
+                                       for (i = 0; i < urb->number_of_packets; i++) {
+                                               if (urb->iso_frame_desc[i].status != 0)
+                                                       deb_ts("iso frame descriptor has an error: %d\n",urb->iso_frame_desc[i].status);
+                                               else if (urb->iso_frame_desc[i].actual_length > 0) {
+                                                               dvb_dmx_swfilter(&d->demux,b + urb->iso_frame_desc[i].offset,
+                                                                               urb->iso_frame_desc[i].actual_length);
+                                                       }
+                                               urb->iso_frame_desc[i].status = 0;
+                                               urb->iso_frame_desc[i].actual_length = 0;
+                                       }
+                                       debug_dump(b,20,deb_ts);
+                                       break;
+                               case PIPE_BULK:
+                                       if (urb->actual_length > 0)
+                                               dvb_dmx_swfilter(&d->demux, (u8 *) urb->transfer_buffer,urb->actual_length);
+                                       break;
+                               default:
+                                       err("unkown endpoint type in completition handler.");
+                                       return;
+                       }
+               }
+       }
 
        usb_submit_urb(urb,GFP_ATOMIC);
 }
@@ -94,7 +126,7 @@ int dvb_usb_urb_kill(struct dvb_usb_device *d)
 {
        int i;
        for (i = 0; i < d->urbs_submitted; i++) {
-               deb_info("killing URB no. %d.\n",i);
+               deb_ts("killing URB no. %d.\n",i);
 
                /* stop the URB */
                usb_kill_urb(d->urb_list[i]);
@@ -107,9 +139,9 @@ int dvb_usb_urb_submit(struct dvb_usb_device *d)
 {
        int i,ret;
        for (i = 0; i < d->urbs_initialized; i++) {
-               deb_info("submitting URB no. %d\n",i);
+               deb_ts("submitting URB no. %d\n",i);
                if ((ret = usb_submit_urb(d->urb_list[i],GFP_ATOMIC))) {
-                       err("could not submit URB no. %d - get them all back\n",i);
+                       err("could not submit URB no. %d - get them all back",i);
                        dvb_usb_urb_kill(d);
                        return ret;
                }
@@ -118,32 +150,78 @@ int dvb_usb_urb_submit(struct dvb_usb_device *d)
        return 0;
 }
 
-static int dvb_usb_bulk_urb_init(struct dvb_usb_device *d)
+static int dvb_usb_free_stream_buffers(struct dvb_usb_device *d)
 {
-       int i,bufsize = d->props.urb.count * d->props.urb.u.bulk.buffersize;
+       if (d->state & DVB_USB_STATE_URB_BUF) {
+               while (d->buf_num) {
+                       d->buf_num--;
+                       deb_mem("freeing buffer %d\n",d->buf_num);
+                       usb_buffer_free(d->udev, d->buf_size,
+                                       d->buf_list[d->buf_num], d->dma_addr[d->buf_num]);
+               }
+               kfree(d->buf_list);
+               kfree(d->dma_addr);
+       }
+
+       d->state &= ~DVB_USB_STATE_URB_BUF;
 
-       deb_info("allocate %d bytes as buffersize for all URBs\n",bufsize);
-       /* allocate the actual buffer for the URBs */
-       if ((d->buffer =  usb_buffer_alloc(d->udev, bufsize, SLAB_ATOMIC, &d->dma_handle)) == NULL) {
-               deb_info("not enough memory for urb-buffer allocation.\n");
+       return 0;
+}
+
+static int dvb_usb_allocate_stream_buffers(struct dvb_usb_device *d, int num, unsigned long size)
+{
+       d->buf_num = 0;
+       d->buf_size = size;
+
+       deb_mem("all in all I will use %lu bytes for streaming\n",num*size);
+
+       if ((d->buf_list = kmalloc(num*sizeof(u8 *), GFP_ATOMIC)) == NULL)
+               return -ENOMEM;
+
+       if ((d->dma_addr = kmalloc(num*sizeof(dma_addr_t), GFP_ATOMIC)) == NULL) {
+               kfree(d->buf_list);
                return -ENOMEM;
        }
-       deb_info("allocation successful\n");
-       memset(d->buffer,0,bufsize);
+       memset(d->buf_list,0,num*sizeof(u8 *));
+       memset(d->dma_addr,0,num*sizeof(dma_addr_t));
 
        d->state |= DVB_USB_STATE_URB_BUF;
 
+       for (d->buf_num = 0; d->buf_num < num; d->buf_num++) {
+               deb_mem("allocating buffer %d\n",d->buf_num);
+               if (( d->buf_list[d->buf_num] =
+                                       usb_buffer_alloc(d->udev, size, SLAB_ATOMIC,
+                                       &d->dma_addr[d->buf_num]) ) == NULL) {
+                       deb_mem("not enough memory for urb-buffer allocation.\n");
+                       dvb_usb_free_stream_buffers(d);
+                       return -ENOMEM;
+               }
+               deb_mem("buffer %d: %p (dma: %d)\n",d->buf_num,d->buf_list[d->buf_num],d->dma_addr[d->buf_num]);
+               memset(d->buf_list[d->buf_num],0,size);
+       }
+       deb_mem("allocation successful\n");
+
+       return 0;
+}
+
+static int dvb_usb_bulk_urb_init(struct dvb_usb_device *d)
+{
+       int i;
+
+       if ((i = dvb_usb_allocate_stream_buffers(d,d->props.urb.count,
+                                       d->props.urb.u.bulk.buffersize)) < 0)
+               return i;
+
        /* allocate the URBs */
        for (i = 0; i < d->props.urb.count; i++) {
-               if (!(d->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC))) {
+               if ((d->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC)) == NULL)
                        return -ENOMEM;
-               }
 
                usb_fill_bulk_urb( d->urb_list[i], d->udev,
                                usb_rcvbulkpipe(d->udev,d->props.urb.endpoint),
-                               &d->buffer[i*d->props.urb.u.bulk.buffersize],
+                               d->buf_list[i],
                                d->props.urb.u.bulk.buffersize,
-                               dvb_usb_bulk_urb_complete, d);
+                               dvb_usb_urb_complete, d);
 
                d->urb_list[i]->transfer_flags = 0;
                d->urbs_initialized++;
@@ -151,6 +229,47 @@ static int dvb_usb_bulk_urb_init(struct dvb_usb_device *d)
        return 0;
 }
 
+static int dvb_usb_isoc_urb_init(struct dvb_usb_device *d)
+{
+       int i,j;
+
+       if ((i = dvb_usb_allocate_stream_buffers(d,d->props.urb.count,
+                                       d->props.urb.u.isoc.framesize*d->props.urb.u.isoc.framesperurb)) < 0)
+               return i;
+
+       /* allocate the URBs */
+       for (i = 0; i < d->props.urb.count; i++) {
+               struct urb *urb;
+               int frame_offset = 0;
+               if ((d->urb_list[i] =
+                                       usb_alloc_urb(d->props.urb.u.isoc.framesperurb,GFP_ATOMIC)) == NULL)
+                       return -ENOMEM;
+
+               urb = d->urb_list[i];
+
+               urb->dev = d->udev;
+               urb->context = d;
+               urb->complete = dvb_usb_urb_complete;
+               urb->pipe = usb_rcvisocpipe(d->udev,d->props.urb.endpoint);
+               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+               urb->interval = d->props.urb.u.isoc.interval;
+               urb->number_of_packets = d->props.urb.u.isoc.framesperurb;
+               urb->transfer_buffer_length = d->buf_size;
+               urb->transfer_buffer = d->buf_list[i];
+               urb->transfer_dma = d->dma_addr[i];
+
+               for (j = 0; j < d->props.urb.u.isoc.framesperurb; j++) {
+                       urb->iso_frame_desc[j].offset = frame_offset;
+                       urb->iso_frame_desc[j].length = d->props.urb.u.isoc.framesize;
+                       frame_offset += d->props.urb.u.isoc.framesize;
+               }
+
+               d->urbs_initialized++;
+       }
+       return 0;
+
+}
+
 int dvb_usb_urb_init(struct dvb_usb_device *d)
 {
        /*
@@ -174,8 +293,7 @@ int dvb_usb_urb_init(struct dvb_usb_device *d)
                case DVB_USB_BULK:
                        return dvb_usb_bulk_urb_init(d);
                case DVB_USB_ISOC:
-                       err("isochronous transfer not yet implemented in dvb-usb.");
-                       return -EINVAL;
+                       return dvb_usb_isoc_urb_init(d);
                default:
                        err("unkown URB-type for data transfer.");
                        return -EINVAL;
@@ -191,7 +309,7 @@ int dvb_usb_urb_exit(struct dvb_usb_device *d)
        if (d->state & DVB_USB_STATE_URB_LIST) {
                for (i = 0; i < d->urbs_initialized; i++) {
                        if (d->urb_list[i] != NULL) {
-                               deb_info("freeing URB no. %d.\n",i);
+                               deb_mem("freeing URB no. %d.\n",i);
                                /* free the URBs */
                                usb_free_urb(d->urb_list[i]);
                        }
@@ -202,10 +320,6 @@ int dvb_usb_urb_exit(struct dvb_usb_device *d)
                d->state &= ~DVB_USB_STATE_URB_LIST;
        }
 
-       if (d->state & DVB_USB_STATE_URB_BUF)
-               usb_buffer_free(d->udev, d->props.urb.u.bulk.buffersize * d->props.urb.count,
-                               d->buffer, d->dma_handle);
-
-       d->state &= ~DVB_USB_STATE_URB_BUF;
+       dvb_usb_free_stream_buffers(d);
        return 0;
 }
index abcee1943f64e2ca83696d7f8d8e3b2c2a26ecce..a80567caf508aab80da113d31cfb495dc9d72997 100644 (file)
@@ -189,12 +189,13 @@ struct dvb_usb_properties {
                        struct {
                                int framesperurb;
                                int framesize;
+                               int interval;
                        } isoc;
                } u;
        } urb;
 
        int num_device_descs;
-       struct dvb_usb_device_description devices[8];
+       struct dvb_usb_device_description devices[9];
 };
 
 
@@ -207,19 +208,28 @@ struct dvb_usb_properties {
  * @udev: pointer to the device's struct usb_device.
  * @urb_list: array of dynamically allocated struct urb for the MPEG2-TS-
  *  streaming.
- * @buffer: buffer used to streaming.
- * @dma_handle: dma_addr_t for buffer.
+ *
+ * @buf_num: number of buffer allocated.
+ * @buf_size: size of each buffer in buf_list.
+ * @buf_list: array containing all allocate buffers for streaming.
+ * @dma_addr: list of dma_addr_t for each buffer in buf_list.
+ *
  * @urbs_initialized: number of URBs initialized.
  * @urbs_submitted: number of URBs submitted.
+ *
  * @feedcount: number of reqested feeds (used for streaming-activation)
  * @pid_filtering: is hardware pid_filtering used or not.
+ *
  * @usb_sem: semaphore of USB control messages (reading needs two messages)
  * @i2c_sem: semaphore for i2c-transfers
+ *
  * @i2c_adap: device's i2c_adapter if it uses I2CoverUSB
  * @pll_addr: I2C address of the tuner for programming
  * @pll_init: array containing the initialization buffer
  * @pll_desc: pointer to the appropriate struct dvb_pll_desc
- * @tuner_pass_ctrl: called to (de)activate tuner passthru of the demod
+ *
+ * @tuner_pass_ctrl: called to (de)activate tuner passthru of the demod or the board
+ *
  * @dvb_adap: device's dvb_adapter.
  * @dmxdev: device's dmxdev.
  * @demux: device's software demuxer.
@@ -253,8 +263,12 @@ struct dvb_usb_device {
        /* usb */
        struct usb_device *udev;
        struct urb **urb_list;
-       u8 *buffer;
-       dma_addr_t dma_handle;
+
+       int buf_num;
+       unsigned long buf_size;
+       u8 **buf_list;
+       dma_addr_t *dma_addr;
+
        int urbs_initialized;
        int urbs_submitted;
 
index 9d83781aef95a525c34d1861e617b67a90118cf3..258a92bfbcc79d354a6ffaaeb8e09be826890c2f 100644 (file)
@@ -203,7 +203,7 @@ static struct dvb_usb_properties nova_t_properties = {
 
 static struct usb_driver nova_t_driver = {
        .owner          = THIS_MODULE,
-       .name           = "Hauppauge WinTV-NOVA-T usb2",
+       .name           = "dvb_usb_nova_t_usb2",
        .probe          = nova_t_probe,
        .disconnect = dvb_usb_device_exit,
        .id_table       = nova_t_table,
index aa560422ce7c583d9f8dc620383e8f6e35ea90b1..2112ac3cf5e2c35a7059d4fa00594ff397795aba 100644 (file)
@@ -129,7 +129,7 @@ static struct dvb_usb_properties umt_properties = {
 
 static struct usb_driver umt_driver = {
        .owner          = THIS_MODULE,
-       .name           = "HanfTek UMT-010 USB2.0 DVB-T devices",
+       .name           = "dvb_usb_umt_010",
        .probe          = umt_probe,
        .disconnect = dvb_usb_device_exit,
        .id_table       = umt_table,
index 02ecc9a8e3b61ee5f2119cbd049a208b6ded9c4f..5adc5d69ec845e8bc5abf2c37fcb2584d036da02 100644 (file)
@@ -44,7 +44,7 @@ int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in,
        if (usb_control_msg(d->udev,
                        usb_sndctrlpipe(d->udev,0),
                        TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0,
-                       outbuf, 20, 2*HZ) != 20) {
+                       outbuf, 20, 2000) != 20) {
                err("USB control message 'out' went wrong.");
                ret = -EIO;
                goto unlock;
@@ -55,7 +55,7 @@ int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in,
        if (usb_control_msg(d->udev,
                        usb_rcvctrlpipe(d->udev,0),
                        TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
-                       inbuf, 12, 2*HZ) != 12) {
+                       inbuf, 12, 2000) != 12) {
                err("USB control message 'in' went wrong.");
                ret = -EIO;
                goto unlock;
@@ -94,13 +94,38 @@ static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff)
 /* The keymapping struct. Somehow this should be loaded to the driver, but
  * currently it is hardcoded. */
 static struct dvb_usb_rc_key vp7045_rc_keys[] = {
-       /* insert the keys like this. to make the raw keys visible, enable
-        * debug=0x04 when loading dvb-usb-vp7045. */
-
-       /* these keys are probably wrong. I don't have a working IR-receiver on my
-        * vp7045, so I can't test it.  Patches are welcome. */
-       { 0x00, 0x01, KEY_1 },
-       { 0x00, 0x02, KEY_2 },
+       { 0x00, 0x16, KEY_POWER },
+       { 0x00, 0x10, KEY_MUTE },
+       { 0x00, 0x03, KEY_1 },
+       { 0x00, 0x01, KEY_2 },
+       { 0x00, 0x06, KEY_3 },
+       { 0x00, 0x09, KEY_4 },
+       { 0x00, 0x1d, KEY_5 },
+       { 0x00, 0x1f, KEY_6 },
+       { 0x00, 0x0d, KEY_7 },
+       { 0x00, 0x19, KEY_8 },
+       { 0x00, 0x1b, KEY_9 },
+       { 0x00, 0x15, KEY_0 },
+       { 0x00, 0x05, KEY_CHANNELUP },
+       { 0x00, 0x02, KEY_CHANNELDOWN },
+       { 0x00, 0x1e, KEY_VOLUMEUP },
+       { 0x00, 0x0a, KEY_VOLUMEDOWN },
+       { 0x00, 0x11, KEY_RECORD },
+       { 0x00, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */
+       { 0x00, 0x14, KEY_PLAY },
+       { 0x00, 0x1a, KEY_STOP },
+       { 0x00, 0x40, KEY_REWIND },
+       { 0x00, 0x12, KEY_FASTFORWARD },
+       { 0x00, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */
+       { 0x00, 0x4c, KEY_PAUSE },
+       { 0x00, 0x4d, KEY_SCREEN }, /* Full screen mode. */
+       { 0x00, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */
+       { 0x00, 0x0c, KEY_CANCEL }, /* Cancel */
+       { 0x00, 0x1c, KEY_EPG }, /* EPG */
+       { 0x00, 0x00, KEY_TAB }, /* Tab */
+       { 0x00, 0x48, KEY_INFO }, /* Preview */
+       { 0x00, 0x04, KEY_LIST }, /* RecordList */
+       { 0x00, 0x0f, KEY_TEXT } /* Teletext */
 };
 
 static int vp7045_rc_query(struct dvb_usb_device *d, u32 *key_buf, int *state)
@@ -230,7 +255,7 @@ static struct dvb_usb_properties vp7045_properties = {
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver vp7045_usb_driver = {
        .owner          = THIS_MODULE,
-       .name           = "dvb-usb-vp7045",
+       .name           = "dvb_usb_vp7045",
        .probe          = vp7045_usb_probe,
        .disconnect = dvb_usb_device_exit,
        .id_table       = vp7045_usb_table,
index b4fddf513ebeaa27f10b0d8be421071866a7547f..d847c62bd83771bed26e439c1d54bf69344a2bf5 100644 (file)
@@ -40,6 +40,12 @@ config DVB_VES1X93
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
+config DVB_S5H1420
+       tristate "Samsung S5H1420 based"
+       depends on DVB_CORE
+       help
+         A DVB-S tuner module. Say Y when you want to support this frontend.
+
 comment "DVB-T (terrestrial) frontends"
        depends on DVB_CORE
 
@@ -181,4 +187,11 @@ config DVB_BCM3510
          An ATSC 8VSB/16VSB and QAM64/256 tuner module. Say Y when you want to
          support this frontend.
 
+config DVB_LGDT3302
+       tristate "LGDT3302 based (DViCO FusionHDTV3 Gold)"
+       depends on DVB_CORE
+       help
+         An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+         to support this frontend.
+
 endmenu
index 91d6d3576d3d366e1460a344fda1fd5dd89472c2..de5e240cba7f5a512314f126bdb33022432b78bf 100644 (file)
@@ -29,3 +29,5 @@ obj-$(CONFIG_DVB_NXT2002) += nxt2002.o
 obj-$(CONFIG_DVB_OR51211) += or51211.o
 obj-$(CONFIG_DVB_OR51132) += or51132.o
 obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
+obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
+obj-$(CONFIG_DVB_LGDT3302) += lgdt3302.o
index f4aa44136c7ced10a677e46dbde06cf39a1f9fe2..9f639297a9f2d7f4ccb50f2af145dfb93b148495 100644 (file)
@@ -76,7 +76,6 @@ static u8 init_tab [] = {
        0x49, 0x56,
        0x6b, 0x1e,
        0xc8, 0x02,
-       0xf8, 0x02,
        0xf9, 0x00,
        0xfa, 0x00,
        0xfb, 0x00,
@@ -203,7 +202,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
        struct cx22702_state* state = fe->demodulator_priv;
 
        /* set PLL */
-        cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe);
+       cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe);
        if (state->config->pll_set) {
                state->config->pll_set(fe, p);
        } else if (state->config->pll_desc) {
@@ -217,7 +216,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
        } else {
                BUG();
        }
-        cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1);
+       cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1);
 
        /* set inversion */
        cx22702_set_inversion (state, p->inversion);
@@ -256,7 +255,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
                cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B) & 0xfc );
                cx22702_writereg(state, 0x0C, (cx22702_readreg(state, 0x0C) & 0xBF) | 0x40 );
                cx22702_writereg(state, 0x00, 0x01); /* Begin aquisition */
-               printk("%s: Autodetecting\n",__FUNCTION__);
+               dprintk("%s: Autodetecting\n",__FUNCTION__);
                return 0;
        }
 
@@ -347,10 +346,11 @@ static int cx22702_init (struct dvb_frontend* fe)
        for (i=0; i<sizeof(init_tab); i+=2)
                cx22702_writereg (state, init_tab[i], init_tab[i+1]);
 
+       cx22702_writereg (state, 0xf8, (state->config->output_mode << 1) & 0x02);
 
        /* init PLL */
        if (state->config->pll_init) {
-               cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe);
+               cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) & 0xfe);
                state->config->pll_init(fe);
                cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1);
        }
@@ -440,8 +440,10 @@ static int cx22702_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 
        /* RS Uncorrectable Packet Count then reset */
        _ucblocks = cx22702_readreg (state, 0xE3);
-       if (state->prevUCBlocks < _ucblocks) *ucblocks = (_ucblocks - state->prevUCBlocks);
-       else *ucblocks = state->prevUCBlocks - _ucblocks;
+       if (state->prevUCBlocks < _ucblocks)
+               *ucblocks = (_ucblocks - state->prevUCBlocks);
+       else
+               *ucblocks = state->prevUCBlocks - _ucblocks;
        state->prevUCBlocks = _ucblocks;
 
        return 0;
@@ -457,6 +459,12 @@ static int cx22702_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        return cx22702_get_tps (state, &p->u.ofdm);
 }
 
+static int cx22702_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+       tune->min_delay_ms = 1000;
+       return 0;
+}
+
 static void cx22702_release(struct dvb_frontend* fe)
 {
        struct cx22702_state* state = fe->demodulator_priv;
@@ -472,7 +480,8 @@ struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
 
        /* allocate memory for the internal state */
        state = kmalloc(sizeof(struct cx22702_state), GFP_KERNEL);
-       if (state == NULL) goto error;
+       if (state == NULL)
+               goto error;
 
        /* setup the state */
        state->config = config;
@@ -481,7 +490,8 @@ struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
        state->prevUCBlocks = 0;
 
        /* check if the demod is there */
-       if (cx22702_readreg(state, 0x1f) != 0x3) goto error;
+       if (cx22702_readreg(state, 0x1f) != 0x3)
+               goto error;
 
        /* create dvb_frontend */
        state->frontend.ops = &state->ops;
@@ -514,6 +524,7 @@ static struct dvb_frontend_ops cx22702_ops = {
 
        .set_frontend = cx22702_set_tps,
        .get_frontend = cx22702_get_frontend,
+       .get_tune_settings = cx22702_get_tune_settings,
 
        .read_status = cx22702_read_status,
        .read_ber = cx22702_read_ber,
index 559fdb90666930f7d5219532c3e31ceb085567b3..11f86806756ef76fe48b33890cca8d6b23e589ed 100644 (file)
@@ -35,6 +35,11 @@ struct cx22702_config
        /* the demodulator's i2c address */
        u8 demod_address;
 
+       /* serial/parallel output */
+#define CX22702_PARALLEL_OUTPUT 0
+#define CX22702_SERIAL_OUTPUT   1
+       u8 output_mode;
+
        /* PLL maintenance */
        u8 pll_address;
        struct dvb_pll_desc *pll_desc;
index f73b5f48e23591b83aa39102040d52c48325c4f9..5afeaa9b43b4d6fcfb6b0772a683f097cdb36f29 100644 (file)
@@ -55,7 +55,7 @@ struct dvb_pll_desc dvb_pll_thomson_dtt7610 = {
 };
 EXPORT_SYMBOL(dvb_pll_thomson_dtt7610);
 
-static void thomson_dtt759x_bw(u8 *buf, int bandwidth)
+static void thomson_dtt759x_bw(u8 *buf, u32 freq, int bandwidth)
 {
        if (BANDWIDTH_7_MHZ == bandwidth)
                buf[3] |= 0x10;
@@ -93,6 +93,32 @@ struct dvb_pll_desc dvb_pll_lg_z201 = {
 };
 EXPORT_SYMBOL(dvb_pll_lg_z201);
 
+struct dvb_pll_desc dvb_pll_microtune_4042 = {
+       .name  = "Microtune 4042 FI5",
+       .min   =  57000000,
+       .max   = 858000000,
+       .count = 3,
+       .entries = {
+               { 162000000, 44000000, 62500, 0x8e, 0xa1 },
+               { 457000000, 44000000, 62500, 0x8e, 0x91 },
+               { 999999999, 44000000, 62500, 0x8e, 0x31 },
+       },
+};
+EXPORT_SYMBOL(dvb_pll_microtune_4042);
+
+struct dvb_pll_desc dvb_pll_thomson_dtt7611 = {
+       .name  = "Thomson dtt7611",
+       .min   =  44000000,
+       .max   = 958000000,
+       .count = 3,
+       .entries = {
+               { 157250000, 44000000, 62500, 0x8e, 0x39 },
+               { 454000000, 44000000, 62500, 0x8e, 0x3a },
+               { 999999999, 44000000, 62500, 0x8e, 0x3c },
+       },
+};
+EXPORT_SYMBOL(dvb_pll_thomson_dtt7611);
+
 struct dvb_pll_desc dvb_pll_unknown_1 = {
        .name  = "unknown 1", /* used by dntv live dvb-t */
        .min   = 174000000,
@@ -146,7 +172,7 @@ EXPORT_SYMBOL(dvb_pll_env57h1xd5);
 /* Philips TDA6650/TDA6651
  * used in Panasonic ENV77H11D5
  */
-static void tda665x_bw(u8 *buf, int bandwidth)
+static void tda665x_bw(u8 *buf, u32 freq, int bandwidth)
 {
        if (bandwidth == BANDWIDTH_8_MHZ)
                buf[3] |= 0x08;
@@ -178,7 +204,7 @@ EXPORT_SYMBOL(dvb_pll_tda665x);
 /* Infineon TUA6034
  * used in LG TDTP E102P
  */
-static void tua6034_bw(u8 *buf, int bandwidth)
+static void tua6034_bw(u8 *buf, u32 freq, int bandwidth)
 {
        if (BANDWIDTH_7_MHZ != bandwidth)
                buf[3] |= 0x08;
@@ -198,6 +224,57 @@ struct dvb_pll_desc dvb_pll_tua6034 = {
 };
 EXPORT_SYMBOL(dvb_pll_tua6034);
 
+/* Philips FMD1216ME
+ * used in Medion Hybrid PCMCIA card and USB Box
+ */
+static void fmd1216me_bw(u8 *buf, u32 freq, int bandwidth)
+{
+       if (bandwidth == BANDWIDTH_8_MHZ && freq >= 158870000)
+               buf[3] |= 0x08;
+}
+
+struct dvb_pll_desc dvb_pll_fmd1216me = {
+       .name = "Philips FMD1216ME",
+       .min = 50870000,
+       .max = 858000000,
+       .setbw = fmd1216me_bw,
+       .count = 7,
+       .entries = {
+               { 143870000, 36213333, 166667, 0xbc, 0x41 },
+               { 158870000, 36213333, 166667, 0xf4, 0x41 },
+               { 329870000, 36213333, 166667, 0xbc, 0x42 },
+               { 441870000, 36213333, 166667, 0xf4, 0x42 },
+               { 625870000, 36213333, 166667, 0xbc, 0x44 },
+               { 803870000, 36213333, 166667, 0xf4, 0x44 },
+               { 999999999, 36213333, 166667, 0xfc, 0x44 },
+       }
+};
+EXPORT_SYMBOL(dvb_pll_fmd1216me);
+
+/* ALPS TDED4
+ * used in Nebula-Cards and USB boxes
+ */
+static void tded4_bw(u8 *buf, u32 freq, int bandwidth)
+{
+       if (bandwidth == BANDWIDTH_8_MHZ)
+               buf[3] |= 0x04;
+}
+
+struct dvb_pll_desc dvb_pll_tded4 = {
+       .name = "ALPS TDED4",
+       .min = 47000000,
+       .max = 863000000,
+       .setbw = tded4_bw,
+       .count = 4,
+       .entries = {
+               { 153000000, 36166667, 166667, 0x85, 0x01 },
+               { 470000000, 36166667, 166667, 0x85, 0x02 },
+               { 823000000, 36166667, 166667, 0x85, 0x08 },
+               { 999999999, 36166667, 166667, 0x85, 0x88 },
+       }
+};
+EXPORT_SYMBOL(dvb_pll_tded4);
+
 /* ----------------------------------------------------------- */
 /* code                                                        */
 
@@ -231,7 +308,7 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
        buf[3] = desc->entries[i].cb2;
 
        if (desc->setbw)
-               desc->setbw(buf, bandwidth);
+               desc->setbw(buf, freq, bandwidth);
 
        if (debug)
                printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
index b796778624b61059ce427c59bbec8b3b32c6a2f8..cb794759d89ede20b028816bd5c40c6140391a5a 100644 (file)
@@ -9,7 +9,7 @@ struct dvb_pll_desc {
        char *name;
        u32  min;
        u32  max;
-       void (*setbw)(u8 *buf, int bandwidth);
+       void (*setbw)(u8 *buf, u32 freq, int bandwidth);
        int  count;
        struct {
                u32 limit;
@@ -24,12 +24,16 @@ extern struct dvb_pll_desc dvb_pll_thomson_dtt7579;
 extern struct dvb_pll_desc dvb_pll_thomson_dtt759x;
 extern struct dvb_pll_desc dvb_pll_thomson_dtt7610;
 extern struct dvb_pll_desc dvb_pll_lg_z201;
+extern struct dvb_pll_desc dvb_pll_microtune_4042;
+extern struct dvb_pll_desc dvb_pll_thomson_dtt7611;
 extern struct dvb_pll_desc dvb_pll_unknown_1;
 
 extern struct dvb_pll_desc dvb_pll_tua6010xs;
 extern struct dvb_pll_desc dvb_pll_env57h1xd5;
 extern struct dvb_pll_desc dvb_pll_tua6034;
 extern struct dvb_pll_desc dvb_pll_tda665x;
+extern struct dvb_pll_desc dvb_pll_fmd1216me;
+extern struct dvb_pll_desc dvb_pll_tded4;
 
 int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
                      u32 freq, int bandwidth);
index 031a1ddc7d11f16662e3446dd6fe561650959ad0..faaad1ae85594bbfa4a205c3638baa0c6399e12d 100644 (file)
@@ -474,11 +474,12 @@ static int l64781_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int l64781_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
+static int l64781_get_tune_settings(struct dvb_frontend* fe,
+                                   struct dvb_frontend_tune_settings* fesettings)
 {
-        fesettings->min_delay_ms = 200;
-        fesettings->step_size = 166667;
-        fesettings->max_drift = 166667*2;
+        fesettings->min_delay_ms = 4000;
+        fesettings->step_size = 0;
+        fesettings->max_drift = 0;
         return 0;
 }
 
diff --git a/drivers/media/dvb/frontends/lgdt3302.c b/drivers/media/dvb/frontends/lgdt3302.c
new file mode 100644 (file)
index 0000000..09c9142
--- /dev/null
@@ -0,0 +1,611 @@
+/*
+ * $Id: lgdt3302.c,v 1.5 2005/07/07 03:47:15 mkrufky Exp $
+ *
+ *    Support for LGDT3302 (DViCO FustionHDTV 3 Gold) - VSB/QAM
+ *
+ *    Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net>
+ *
+ *    Based on code from  Kirk Lapray <kirk_lapray@bigfoot.com>
+ *                           Copyright (C) 2005
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ *                      NOTES ABOUT THIS DRIVER
+ *
+ * This driver supports DViCO FusionHDTV 3 Gold under Linux.
+ *
+ * TODO:
+ * BER and signal strength always return 0.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <asm/byteorder.h>
+
+#include "dvb_frontend.h"
+#include "dvb-pll.h"
+#include "lgdt3302_priv.h"
+#include "lgdt3302.h"
+
+static int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,"Turn on/off lgdt3302 frontend debugging (default:off).");
+#define dprintk(args...) \
+do { \
+if (debug) printk(KERN_DEBUG "lgdt3302: " args); \
+} while (0)
+
+struct lgdt3302_state
+{
+       struct i2c_adapter* i2c;
+       struct dvb_frontend_ops ops;
+
+       /* Configuration settings */
+       const struct lgdt3302_config* config;
+
+       struct dvb_frontend frontend;
+
+       /* Demodulator private data */
+       fe_modulation_t current_modulation;
+
+       /* Tuner private data */
+       u32 current_frequency;
+};
+
+static int i2c_writebytes (struct lgdt3302_state* state,
+                          u8 addr, /* demod_address or pll_address */
+                          u8 *buf, /* data bytes to send */
+                          int len  /* number of bytes to send */ )
+{
+       if (addr == state->config->pll_address) {
+               struct i2c_msg msg =
+                       { .addr = addr, .flags = 0, .buf = buf,  .len = len };
+               int err;
+
+               if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+                       printk(KERN_WARNING "lgdt3302: %s error (addr %02x <- %02x, err == %i)\n", __FUNCTION__, addr, buf[0], err);
+                       return -EREMOTEIO;
+               }
+       } else {
+               u8 tmp[] = { buf[0], buf[1] };
+               struct i2c_msg msg =
+                       { .addr = addr, .flags = 0, .buf = tmp,  .len = 2 };
+               int err;
+               int i;
+
+               for (i=1; i<len; i++) {
+                       tmp[1] = buf[i];
+                       if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+                               printk(KERN_WARNING "lgdt3302: %s error (addr %02x <- %02x, err == %i)\n", __FUNCTION__, addr, buf[0], err);
+                               return -EREMOTEIO;
+                       }
+                       tmp[0]++;
+               }
+       }
+       return 0;
+}
+static int i2c_readbytes (struct lgdt3302_state* state,
+                         u8 addr, /* demod_address or pll_address */
+                         u8 *buf, /* holds data bytes read */
+                         int len  /* number of bytes to read */ )
+{
+       struct i2c_msg msg =
+               { .addr = addr, .flags = I2C_M_RD, .buf = buf,  .len = len };
+       int err;
+
+       if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+               printk(KERN_WARNING "lgdt3302: %s error (addr %02x, err == %i)\n", __FUNCTION__, addr, err);
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+/*
+ * This routine writes the register (reg) to the demod bus
+ * then reads the data returned for (len) bytes.
+ */
+
+static u8 i2c_selectreadbytes (struct lgdt3302_state* state,
+                              enum I2C_REG reg, u8* buf, int len)
+{
+       u8 wr [] = { reg };
+       struct i2c_msg msg [] = {
+               { .addr = state->config->demod_address,
+                 .flags = 0, .buf = wr,  .len = 1 },
+               { .addr = state->config->demod_address,
+                 .flags = I2C_M_RD, .buf = buf, .len = len },
+       };
+       int ret;
+       ret = i2c_transfer(state->i2c, msg, 2);
+       if (ret != 2) {
+               printk(KERN_WARNING "lgdt3302: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __FUNCTION__, state->config->demod_address, reg, ret);
+       } else {
+               ret = 0;
+       }
+       return ret;
+}
+
+/* Software reset */
+int lgdt3302_SwReset(struct lgdt3302_state* state)
+{
+       u8 ret;
+       u8 reset[] = {
+               IRQ_MASK,
+               0x00 /* bit 6 is active low software reset
+                     * bits 5-0 are 1 to mask interrupts */
+       };
+
+       ret = i2c_writebytes(state,
+                            state->config->demod_address,
+                            reset, sizeof(reset));
+       if (ret == 0) {
+               /* spec says reset takes 100 ns why wait */
+               /* mdelay(100);    */ /* keep low for 100mS */
+               reset[1] = 0x7f;      /* force reset high (inactive)
+                                      * and unmask interrupts */
+               ret = i2c_writebytes(state,
+                                    state->config->demod_address,
+                                    reset, sizeof(reset));
+       }
+       /* Spec does not indicate a need for this either */
+       /*mdelay(5); */               /* wait 5 msec before doing more */
+       return ret;
+}
+
+static int lgdt3302_init(struct dvb_frontend* fe)
+{
+       /* Hardware reset is done using gpio[0] of cx23880x chip.
+        * I'd like to do it here, but don't know how to find chip address.
+        * cx88-cards.c arranges for the reset bit to be inactive (high).
+        * Maybe there needs to be a callable function in cx88-core or
+        * the caller of this function needs to do it. */
+
+       dprintk("%s entered\n", __FUNCTION__);
+       return lgdt3302_SwReset((struct lgdt3302_state*) fe->demodulator_priv);
+}
+
+static int lgdt3302_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+       *ber = 0; /* Dummy out for now */
+       return 0;
+}
+
+static int lgdt3302_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+       struct lgdt3302_state* state = (struct lgdt3302_state*) fe->demodulator_priv;
+       u8 buf[2];
+
+       i2c_selectreadbytes(state, PACKET_ERR_COUNTER1, buf, sizeof(buf));
+
+       *ucblocks = (buf[0] << 8) | buf[1];
+       return 0;
+}
+
+static int lgdt3302_set_parameters(struct dvb_frontend* fe,
+                                  struct dvb_frontend_parameters *param)
+{
+       u8 buf[4];
+       struct lgdt3302_state* state =
+               (struct lgdt3302_state*) fe->demodulator_priv;
+
+       /* Use 50MHz parameter values from spec sheet since xtal is 50 */
+       static u8 top_ctrl_cfg[]   = { TOP_CONTROL, 0x03 };
+       static u8 vsb_freq_cfg[]   = { VSB_CARRIER_FREQ0, 0x00, 0x87, 0x8e, 0x01 };
+       static u8 demux_ctrl_cfg[] = { DEMUX_CONTROL, 0xfb };
+       static u8 agc_rf_cfg[]     = { AGC_RF_BANDWIDTH0, 0x40, 0x93, 0x00 };
+       static u8 agc_ctrl_cfg[]   = { AGC_FUNC_CTRL2, 0xc6, 0x40 };
+       static u8 agc_delay_cfg[]  = { AGC_DELAY0, 0x00, 0x00, 0x00 };
+       static u8 agc_loop_cfg[]   = { AGC_LOOP_BANDWIDTH0, 0x08, 0x9a };
+
+       /* Change only if we are actually changing the modulation */
+       if (state->current_modulation != param->u.vsb.modulation) {
+               switch(param->u.vsb.modulation) {
+               case VSB_8:
+                       dprintk("%s: VSB_8 MODE\n", __FUNCTION__);
+
+                       /* Select VSB mode and serial MPEG interface */
+                       top_ctrl_cfg[1] = 0x07;
+                       break;
+
+               case QAM_64:
+                       dprintk("%s: QAM_64 MODE\n", __FUNCTION__);
+
+                       /* Select QAM_64 mode and serial MPEG interface */
+                       top_ctrl_cfg[1] = 0x04;
+                       break;
+
+               case QAM_256:
+                       dprintk("%s: QAM_256 MODE\n", __FUNCTION__);
+
+                       /* Select QAM_256 mode and serial MPEG interface */
+                       top_ctrl_cfg[1] = 0x05;
+                       break;
+               default:
+                       printk(KERN_WARNING "lgdt3302: %s: Modulation type(%d) UNSUPPORTED\n", __FUNCTION__, param->u.vsb.modulation);
+                       return -1;
+               }
+               /* Initializations common to all modes */
+
+               /* Select the requested mode */
+               i2c_writebytes(state, state->config->demod_address,
+                              top_ctrl_cfg, sizeof(top_ctrl_cfg));
+
+               /* Change the value of IFBW[11:0]
+                  of AGC IF/RF loop filter bandwidth register */
+               i2c_writebytes(state, state->config->demod_address,
+                              agc_rf_cfg, sizeof(agc_rf_cfg));
+
+               /* Change the value of bit 6, 'nINAGCBY' and
+                  'NSSEL[1:0] of ACG function control register 2 */
+               /* Change the value of bit 6 'RFFIX'
+                  of AGC function control register 3 */
+               i2c_writebytes(state, state->config->demod_address,
+                              agc_ctrl_cfg, sizeof(agc_ctrl_cfg));
+
+               /* Change the TPCLK pin polarity
+                  data is valid on falling clock */
+               i2c_writebytes(state, state->config->demod_address,
+                              demux_ctrl_cfg, sizeof(demux_ctrl_cfg));
+
+               if (param->u.vsb.modulation == VSB_8) {
+                       /* Initialization for VSB modes only */
+                       /* Change the value of NCOCTFV[25:0]of carrier
+                          recovery center frequency register for VSB */
+                       i2c_writebytes(state, state->config->demod_address,
+                                      vsb_freq_cfg, sizeof(vsb_freq_cfg));
+               } else {
+                       /* Initialization for QAM modes only */
+                       /* Set the value of 'INLVTHD' register 0x2a/0x2c
+                          to value from 'IFACC' register 0x39/0x3b -1 */
+                       int value;
+                       i2c_selectreadbytes(state, AGC_RFIF_ACC0,
+                                           &agc_delay_cfg[1], 3);
+                       value = ((agc_delay_cfg[1] & 0x0f) << 8) | agc_delay_cfg[3];
+                       value = value -1;
+                       dprintk("%s IFACC -1 = 0x%03x\n", __FUNCTION__, value);
+                       agc_delay_cfg[1] = (value >> 8) & 0x0f;
+                       agc_delay_cfg[2] = 0x00;
+                       agc_delay_cfg[3] = value & 0xff;
+                       i2c_writebytes(state, state->config->demod_address,
+                                      agc_delay_cfg, sizeof(agc_delay_cfg));
+
+                       /* Change the value of IAGCBW[15:8]
+                          of inner AGC loop filter bandwith */
+                       i2c_writebytes(state, state->config->demod_address,
+                                      agc_loop_cfg, sizeof(agc_loop_cfg));
+               }
+
+               state->config->set_ts_params(fe, 0);
+               lgdt3302_SwReset(state);
+               state->current_modulation = param->u.vsb.modulation;
+       }
+
+       /* Change only if we are actually changing the channel */
+       if (state->current_frequency != param->frequency) {
+               dvb_pll_configure(state->config->pll_desc, buf,
+                                 param->frequency, 0);
+               dprintk("%s: tuner bytes: 0x%02x 0x%02x "
+                       "0x%02x 0x%02x\n", __FUNCTION__, buf[0],buf[1],buf[2],buf[3]);
+               i2c_writebytes(state, state->config->pll_address ,buf, 4);
+
+               /* Check the status of the tuner pll */
+               i2c_readbytes(state, state->config->pll_address, buf, 1);
+               dprintk("%s: tuner status byte = 0x%02x\n", __FUNCTION__, buf[0]);
+
+               lgdt3302_SwReset(state);
+
+               /* Update current frequency */
+               state->current_frequency = param->frequency;
+       }
+       return 0;
+}
+
+static int lgdt3302_get_frontend(struct dvb_frontend* fe,
+                                struct dvb_frontend_parameters* param)
+{
+       struct lgdt3302_state *state = fe->demodulator_priv;
+       param->frequency = state->current_frequency;
+       return 0;
+}
+
+static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+       struct lgdt3302_state* state = (struct lgdt3302_state*) fe->demodulator_priv;
+       u8 buf[3];
+
+       *status = 0; /* Reset status result */
+
+       /* Check the status of the tuner pll */
+       i2c_readbytes(state, state->config->pll_address, buf, 1);
+       dprintk("%s: tuner status byte = 0x%02x\n", __FUNCTION__, buf[0]);
+       if ((buf[0] & 0xc0) != 0x40)
+               return 0; /* Tuner PLL not locked or not powered on */
+
+       /*
+        * You must set the Mask bits to 1 in the IRQ_MASK in order
+        * to see that status bit in the IRQ_STATUS register.
+        * This is done in SwReset();
+        */
+
+       /* AGC status register */
+       i2c_selectreadbytes(state, AGC_STATUS, buf, 1);
+       dprintk("%s: AGC_STATUS = 0x%02x\n", __FUNCTION__, buf[0]);
+       if ((buf[0] & 0x0c) == 0x8){
+               /* Test signal does not exist flag */
+               /* as well as the AGC lock flag.   */
+               *status |= FE_HAS_SIGNAL;
+       } else {
+               /* Without a signal all other status bits are meaningless */
+               return 0;
+       }
+
+       /* signal status */
+       i2c_selectreadbytes(state, TOP_CONTROL, buf, sizeof(buf));
+       dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __FUNCTION__, buf[0], buf[1], buf[2]);
+
+#if 0
+       /* Alternative method to check for a signal */
+       /* using the SNR good/bad interrupts.   */
+       if ((buf[2] & 0x30) == 0x10)
+               *status |= FE_HAS_SIGNAL;
+#endif
+
+       /* sync status */
+       if ((buf[2] & 0x03) == 0x01) {
+               *status |= FE_HAS_SYNC;
+       }
+
+       /* FEC error status */
+       if ((buf[2] & 0x0c) == 0x08) {
+               *status |= FE_HAS_LOCK;
+               *status |= FE_HAS_VITERBI;
+       }
+
+       /* Carrier Recovery Lock Status Register */
+       i2c_selectreadbytes(state, CARRIER_LOCK, buf, 1);
+       dprintk("%s: CARRIER_LOCK = 0x%02x\n", __FUNCTION__, buf[0]);
+       switch (state->current_modulation) {
+       case QAM_256:
+       case QAM_64:
+               /* Need to undestand why there are 3 lock levels here */
+               if ((buf[0] & 0x07) == 0x07)
+                       *status |= FE_HAS_CARRIER;
+               break;
+       case VSB_8:
+               if ((buf[0] & 0x80) == 0x80)
+                       *status |= FE_HAS_CARRIER;
+               break;
+       default:
+               printk("KERN_WARNING lgdt3302: %s: Modulation set to unsupported value\n", __FUNCTION__);
+       }
+
+       return 0;
+}
+
+static int lgdt3302_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+       /* not directly available. */
+       return 0;
+}
+
+static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+#ifdef SNR_IN_DB
+       /*
+        * Spec sheet shows formula for SNR_EQ = 10 log10(25 * 24**2 / noise)
+        * and SNR_PH = 10 log10(25 * 32**2 / noise) for equalizer and phase tracker
+        * respectively. The following tables are built on these formulas.
+        * The usual definition is SNR = 20 log10(signal/noise)
+        * If the specification is wrong the value retuned is 1/2 the actual SNR in db.
+        *
+        * This table is a an ordered list of noise values computed by the
+        * formula from the spec sheet such that the index into the table
+        * starting at 43 or 45 is the SNR value in db. There are duplicate noise
+        * value entries at the beginning because the SNR varies more than
+        * 1 db for a change of 1 digit in noise at very small values of noise.
+        *
+        * Examples from SNR_EQ table:
+        * noise SNR
+        *   0    43
+        *   1    42
+        *   2    39
+        *   3    37
+        *   4    36
+        *   5    35
+        *   6    34
+        *   7    33
+        *   8    33
+        *   9    32
+        *   10   32
+        *   11   31
+        *   12   31
+        *   13   30
+        */
+
+       static const u32 SNR_EQ[] =
+               { 1,     2,      2,      2, 3,      3,      4,     4,     5,     7,
+                 9,     11,     13,     17, 21,     26,     33,    41,    52,    65,
+                 81,    102,    129,    162, 204,    257,    323,   406,   511,   644,
+                 810,   1020,   1284,   1616, 2035,   2561,   3224,  4059,  5110,  6433,
+                 8098,  10195,  12835,  16158, 20341,  25608,  32238, 40585, 51094, 64323,
+                 80978, 101945, 128341, 161571, 203406, 256073, 0x40000
+               };
+
+       static const u32 SNR_PH[] =
+               { 1,     2,      2,      2,      3,      3,     4,     5,     6,     8,
+                 10,    12,     15,     19,     23,     29, 37,    46,    58,    73,
+                 91,    115,    144,    182,    229,    288, 362,   456,   574,   722,
+                 909,   1144,   1440,   1813,   2282,   2873, 3617,  4553,  5732,  7216,
+                 9084,  11436,  14396,  18124,  22817,  28724,  36161, 45524, 57312, 72151,
+                 90833, 114351, 143960, 181235, 228161, 0x040000
+               };
+
+       static u8 buf[5];/* read data buffer */
+       static u32 noise;   /* noise value */
+       static u32 snr_db;  /* index into SNR_EQ[] */
+       struct lgdt3302_state* state = (struct lgdt3302_state*) fe->demodulator_priv;
+
+       /* read both equalizer and pase tracker noise data */
+       i2c_selectreadbytes(state, EQPH_ERR0, buf, sizeof(buf));
+
+       if (state->current_modulation == VSB_8) {
+               /* Equalizer Mean-Square Error Register for VSB */
+               noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
+
+               /*
+                * Look up noise value in table.
+                * A better search algorithm could be used...
+                * watch out there are duplicate entries.
+                */
+               for (snr_db = 0; snr_db < sizeof(SNR_EQ); snr_db++) {
+                       if (noise < SNR_EQ[snr_db]) {
+                               *snr = 43 - snr_db;
+                               break;
+                       }
+               }
+       } else {
+               /* Phase Tracker Mean-Square Error Register for QAM */
+               noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
+
+               /* Look up noise value in table. */
+               for (snr_db = 0; snr_db < sizeof(SNR_PH); snr_db++) {
+                       if (noise < SNR_PH[snr_db]) {
+                               *snr = 45 - snr_db;
+                               break;
+                       }
+               }
+       }
+#else
+       /* Return the raw noise value */
+       static u8 buf[5];/* read data buffer */
+       static u32 noise;   /* noise value */
+       struct lgdt3302_state* state = (struct lgdt3302_state*) fe->demodulator_priv;
+
+       /* read both equalizer and pase tracker noise data */
+       i2c_selectreadbytes(state, EQPH_ERR0, buf, sizeof(buf));
+
+       if (state->current_modulation == VSB_8) {
+               /* Equalizer Mean-Square Error Register for VSB */
+               noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
+       } else {
+               /* Phase Tracker Mean-Square Error Register for QAM */
+               noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
+       }
+
+       /* Small values for noise mean signal is better so invert noise */
+       /* Noise is 19 bit value so discard 3 LSB*/
+       *snr = ~noise>>3;
+#endif
+
+       dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
+
+       return 0;
+}
+
+static int lgdt3302_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
+{
+       /* I have no idea about this - it may not be needed */
+       fe_tune_settings->min_delay_ms = 500;
+       fe_tune_settings->step_size = 0;
+       fe_tune_settings->max_drift = 0;
+       return 0;
+}
+
+static void lgdt3302_release(struct dvb_frontend* fe)
+{
+       struct lgdt3302_state* state = (struct lgdt3302_state*) fe->demodulator_priv;
+       kfree(state);
+}
+
+static struct dvb_frontend_ops lgdt3302_ops;
+
+struct dvb_frontend* lgdt3302_attach(const struct lgdt3302_config* config,
+                                    struct i2c_adapter* i2c)
+{
+       struct lgdt3302_state* state = NULL;
+       u8 buf[1];
+
+       /* Allocate memory for the internal state */
+       state = (struct lgdt3302_state*) kmalloc(sizeof(struct lgdt3302_state), GFP_KERNEL);
+       if (state == NULL)
+               goto error;
+       memset(state,0,sizeof(*state));
+
+       /* Setup the state */
+       state->config = config;
+       state->i2c = i2c;
+       memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
+       /* Verify communication with demod chip */
+       if (i2c_selectreadbytes(state, 2, buf, 1))
+               goto error;
+
+       state->current_frequency = -1;
+       state->current_modulation = -1;
+
+       /* Create dvb_frontend */
+       state->frontend.ops = &state->ops;
+       state->frontend.demodulator_priv = state;
+       return &state->frontend;
+
+error:
+       if (state)
+               kfree(state);
+       dprintk("%s: ERROR\n",__FUNCTION__);
+       return NULL;
+}
+
+static struct dvb_frontend_ops lgdt3302_ops = {
+       .info = {
+               .name= "LG Electronics LGDT3302 VSB/QAM Frontend",
+               .type = FE_ATSC,
+               .frequency_min= 54000000,
+               .frequency_max= 858000000,
+               .frequency_stepsize= 62500,
+               /* Symbol rate is for all VSB modes need to check QAM */
+               .symbol_rate_min    = 10762000,
+               .symbol_rate_max    = 10762000,
+               .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+       },
+       .init                 = lgdt3302_init,
+       .set_frontend         = lgdt3302_set_parameters,
+       .get_frontend         = lgdt3302_get_frontend,
+       .get_tune_settings    = lgdt3302_get_tune_settings,
+       .read_status          = lgdt3302_read_status,
+       .read_ber             = lgdt3302_read_ber,
+       .read_signal_strength = lgdt3302_read_signal_strength,
+       .read_snr             = lgdt3302_read_snr,
+       .read_ucblocks        = lgdt3302_read_ucblocks,
+       .release              = lgdt3302_release,
+};
+
+MODULE_DESCRIPTION("LGDT3302 [DViCO FusionHDTV 3 Gold] (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
+MODULE_AUTHOR("Wilson Michaels");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(lgdt3302_attach);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * compile-command: "make DVB=1"
+ * End:
+ */
diff --git a/drivers/media/dvb/frontends/lgdt3302.h b/drivers/media/dvb/frontends/lgdt3302.h
new file mode 100644 (file)
index 0000000..81587a4
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * $Id: lgdt3302.h,v 1.2 2005/06/28 23:50:48 mkrufky Exp $
+ *
+ *    Support for LGDT3302 (DViCO FustionHDTV 3 Gold) - VSB/QAM
+ *
+ *    Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef LGDT3302_H
+#define LGDT3302_H
+
+#include <linux/dvb/frontend.h>
+
+struct lgdt3302_config
+{
+       /* The demodulator's i2c address */
+       u8 demod_address;
+       u8 pll_address;
+       struct dvb_pll_desc *pll_desc;
+
+       /* Need to set device param for start_dma */
+       int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
+};
+
+extern struct dvb_frontend* lgdt3302_attach(const struct lgdt3302_config* config,
+                                           struct i2c_adapter* i2c);
+
+#endif /* LGDT3302_H */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/frontends/lgdt3302_priv.h b/drivers/media/dvb/frontends/lgdt3302_priv.h
new file mode 100644 (file)
index 0000000..6193fa7
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * $Id: lgdt3302_priv.h,v 1.2 2005/06/28 23:50:48 mkrufky Exp $
+ *
+ *    Support for LGDT3302 (DViCO FustionHDTV 3 Gold) - VSB/QAM
+ *
+ *    Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.net>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef _LGDT3302_PRIV_
+#define _LGDT3302_PRIV_
+
+/* i2c control register addresses */
+enum I2C_REG {
+       TOP_CONTROL= 0x00,
+       IRQ_MASK= 0x01,
+       IRQ_STATUS= 0x02,
+       VSB_CARRIER_FREQ0= 0x16,
+       VSB_CARRIER_FREQ1= 0x17,
+       VSB_CARRIER_FREQ2= 0x18,
+       VSB_CARRIER_FREQ3= 0x19,
+       CARRIER_MSEQAM1= 0x1a,
+       CARRIER_MSEQAM2= 0x1b,
+       CARRIER_LOCK= 0x1c,
+       TIMING_RECOVERY= 0x1d,
+       AGC_DELAY0= 0x2a,
+       AGC_DELAY1= 0x2b,
+       AGC_DELAY2= 0x2c,
+       AGC_RF_BANDWIDTH0= 0x2d,
+       AGC_RF_BANDWIDTH1= 0x2e,
+       AGC_RF_BANDWIDTH2= 0x2f,
+       AGC_LOOP_BANDWIDTH0= 0x30,
+       AGC_LOOP_BANDWIDTH1= 0x31,
+       AGC_FUNC_CTRL1= 0x32,
+       AGC_FUNC_CTRL2= 0x33,
+       AGC_FUNC_CTRL3= 0x34,
+       AGC_RFIF_ACC0= 0x39,
+       AGC_RFIF_ACC1= 0x3a,
+       AGC_RFIF_ACC2= 0x3b,
+       AGC_STATUS= 0x3f,
+       SYNC_STATUS_VSB= 0x43,
+       EQPH_ERR0= 0x47,
+       EQ_ERR1= 0x48,
+       EQ_ERR2= 0x49,
+       PH_ERR1= 0x4a,
+       PH_ERR2= 0x4b,
+       DEMUX_CONTROL= 0x66,
+       PACKET_ERR_COUNTER1= 0x6a,
+       PACKET_ERR_COUNTER2= 0x6b,
+};
+
+#endif /* _LGDT3302_PRIV_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c
new file mode 100644 (file)
index 0000000..4f396ac
--- /dev/null
@@ -0,0 +1,800 @@
+/*
+Driver for Samsung S5H1420 QPSK Demodulator
+
+Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include "dvb_frontend.h"
+#include "s5h1420.h"
+
+
+
+#define TONE_FREQ 22000
+
+struct s5h1420_state {
+       struct i2c_adapter* i2c;
+       struct dvb_frontend_ops ops;
+       const struct s5h1420_config* config;
+       struct dvb_frontend frontend;
+
+       u8 postlocked:1;
+       u32 fclk;
+       u32 tunedfreq;
+       fe_code_rate_t fec_inner;
+       u32 symbol_rate;
+};
+
+static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
+static int s5h1420_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings);
+
+
+static int debug = 0;
+#define dprintk if (debug) printk
+
+static int s5h1420_writereg (struct s5h1420_state* state, u8 reg, u8 data)
+{
+       u8 buf [] = { reg, data };
+       struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+       int err;
+
+       if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+               dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+               return -EREMOTEIO;
+       }
+
+       return 0;
+}
+
+static u8 s5h1420_readreg (struct s5h1420_state* state, u8 reg)
+{
+       int ret;
+       u8 b0 [] = { reg };
+       u8 b1 [] = { 0 };
+       struct i2c_msg msg1 = { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 };
+       struct i2c_msg msg2 = { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 };
+
+       if ((ret = i2c_transfer (state->i2c, &msg1, 1)) != 1)
+               return ret;
+
+       if ((ret = i2c_transfer (state->i2c, &msg2, 1)) != 1)
+               return ret;
+
+       return b1[0];
+}
+
+static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+       struct s5h1420_state* state = fe->demodulator_priv;
+
+       switch(voltage) {
+       case SEC_VOLTAGE_13:
+               s5h1420_writereg(state, 0x3c, (s5h1420_readreg(state, 0x3c) & 0xfe) | 0x02);
+               break;
+
+       case SEC_VOLTAGE_18:
+               s5h1420_writereg(state, 0x3c, s5h1420_readreg(state, 0x3c) | 0x03);
+               break;
+
+       case SEC_VOLTAGE_OFF:
+               s5h1420_writereg(state, 0x3c, s5h1420_readreg(state, 0x3c) & 0xfd);
+               break;
+       }
+
+       return 0;
+}
+
+static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+       struct s5h1420_state* state = fe->demodulator_priv;
+
+       switch(tone) {
+       case SEC_TONE_ON:
+               s5h1420_writereg(state, 0x3b, (s5h1420_readreg(state, 0x3b) & 0x74) | 0x08);
+               break;
+
+       case SEC_TONE_OFF:
+               s5h1420_writereg(state, 0x3b, (s5h1420_readreg(state, 0x3b) & 0x74) | 0x01);
+               break;
+       }
+
+       return 0;
+}
+
+static int s5h1420_send_master_cmd (struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
+{
+       struct s5h1420_state* state = fe->demodulator_priv;
+       u8 val;
+       int i;
+       unsigned long timeout;
+       int result = 0;
+
+       /* setup for DISEQC */
+       val = s5h1420_readreg(state, 0x3b);
+       s5h1420_writereg(state, 0x3b, 0x02);
+       msleep(15);
+
+       /* write the DISEQC command bytes */
+       for(i=0; i< cmd->msg_len; i++) {
+               s5h1420_writereg(state, 0x3c + i, cmd->msg[i]);
+       }
+
+       /* kick off transmission */
+       s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | ((cmd->msg_len-1) << 4) | 0x08);
+
+       /* wait for transmission to complete */
+       timeout = jiffies + ((100*HZ) / 1000);
+       while(time_before(jiffies, timeout)) {
+               if (s5h1420_readreg(state, 0x3b) & 0x08)
+                       break;
+
+               msleep(5);
+       }
+       if (time_after(jiffies, timeout))
+               result = -ETIMEDOUT;
+
+       /* restore original settings */
+       s5h1420_writereg(state, 0x3b, val);
+       msleep(15);
+       return result;
+}
+
+static int s5h1420_recv_slave_reply (struct dvb_frontend* fe, struct dvb_diseqc_slave_reply* reply)
+{
+       struct s5h1420_state* state = fe->demodulator_priv;
+       u8 val;
+       int i;
+       int length;
+       unsigned long timeout;
+       int result = 0;
+
+       /* setup for DISEQC recieve */
+       val = s5h1420_readreg(state, 0x3b);
+       s5h1420_writereg(state, 0x3b, 0x82); /* FIXME: guess - do we need to set DIS_RDY(0x08) in receive mode? */
+       msleep(15);
+
+       /* wait for reception to complete */
+       timeout = jiffies + ((reply->timeout*HZ) / 1000);
+       while(time_before(jiffies, timeout)) {
+               if (!(s5h1420_readreg(state, 0x3b) & 0x80)) /* FIXME: do we test DIS_RDY(0x08) or RCV_EN(0x80)? */
+                       break;
+
+               msleep(5);
+       }
+       if (time_after(jiffies, timeout)) {
+               result = -ETIMEDOUT;
+               goto exit;
+       }
+
+       /* check error flag - FIXME: not sure what this does - docs do not describe
+        * beyond "error flag for diseqc receive data :( */
+       if (s5h1420_readreg(state, 0x49)) {
+               result = -EIO;
+               goto exit;
+       }
+
+       /* check length */
+       length = (s5h1420_readreg(state, 0x3b) & 0x70) >> 4;
+       if (length > sizeof(reply->msg)) {
+               result = -EOVERFLOW;
+               goto exit;
+       }
+       reply->msg_len = length;
+
+       /* extract data */
+       for(i=0; i< length; i++) {
+               reply->msg[i] = s5h1420_readreg(state, 0x3c + i);
+       }
+
+exit:
+       /* restore original settings */
+       s5h1420_writereg(state, 0x3b, val);
+       msleep(15);
+       return result;
+}
+
+static int s5h1420_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
+{
+       struct s5h1420_state* state = fe->demodulator_priv;
+       u8 val;
+       int result = 0;
+       unsigned long timeout;
+
+       /* setup for tone burst */
+       val = s5h1420_readreg(state, 0x3b);
+       s5h1420_writereg(state, 0x3b, (s5h1420_readreg(state, 0x3b) & 0x70) | 0x01);
+
+       /* set value for B position if requested */
+       if (minicmd == SEC_MINI_B) {
+               s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | 0x04);
+       }
+       msleep(15);
+
+       /* start transmission */
+       s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | 0x08);
+
+       /* wait for transmission to complete */
+       timeout = jiffies + ((20*HZ) / 1000);
+       while(time_before(jiffies, timeout)) {
+               if (!(s5h1420_readreg(state, 0x3b) & 0x08))
+                       break;
+
+               msleep(5);
+       }
+       if (time_after(jiffies, timeout))
+               result = -ETIMEDOUT;
+
+       /* restore original settings */
+       s5h1420_writereg(state, 0x3b, val);
+       msleep(15);
+       return result;
+}
+
+static fe_status_t s5h1420_get_status_bits(struct s5h1420_state* state)
+{
+       u8 val;
+       fe_status_t status = 0;
+
+       val = s5h1420_readreg(state, 0x14);
+       if (val & 0x02)
+               status |=  FE_HAS_SIGNAL; // FIXME: not sure if this is right
+       if (val & 0x01)
+               status |=  FE_HAS_CARRIER; // FIXME: not sure if this is right
+       val = s5h1420_readreg(state, 0x36);
+       if (val & 0x01)
+               status |=  FE_HAS_VITERBI;
+       if (val & 0x20)
+               status |=  FE_HAS_SYNC;
+       if (status == (FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI|FE_HAS_SYNC))
+               status |=  FE_HAS_LOCK;
+
+       return status;
+}
+
+static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+       struct s5h1420_state* state = fe->demodulator_priv;
+       u8 val;
+
+       if (status == NULL)
+               return -EINVAL;
+
+       /* determine lock state */
+       *status = s5h1420_get_status_bits(state);
+
+       /* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert the inversion,
+       wait a bit and check again */
+       if (*status == (FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI)) {
+               val = s5h1420_readreg(state, 0x32);
+               if ((val & 0x07) == 0x03) {
+                       if (val & 0x08)
+                               s5h1420_writereg(state, 0x31, 0x13);
+                       else
+                               s5h1420_writereg(state, 0x31, 0x1b);
+
+                       /* wait a bit then update lock status */
+                       mdelay(200);
+                       *status = s5h1420_get_status_bits(state);
+               }
+       }
+
+       /* perform post lock setup */
+       if ((*status & FE_HAS_LOCK) && (!state->postlocked)) {
+
+               /* calculate the data rate */
+               u32 tmp = s5h1420_getsymbolrate(state);
+               switch(s5h1420_readreg(state, 0x32) & 0x07) {
+               case 0:
+                       tmp = (tmp * 2 * 1) / 2;
+                       break;
+
+               case 1:
+                       tmp = (tmp * 2 * 2) / 3;
+                       break;
+
+               case 2:
+                       tmp = (tmp * 2 * 3) / 4;
+                       break;
+
+               case 3:
+                       tmp = (tmp * 2 * 5) / 6;
+                       break;
+
+               case 4:
+                       tmp = (tmp * 2 * 6) / 7;
+                       break;
+
+               case 5:
+                       tmp = (tmp * 2 * 7) / 8;
+                       break;
+               }
+               tmp = state->fclk / tmp;
+
+               /* set the MPEG_CLK_INTL for the calculated data rate */
+               if (tmp < 4)
+                       val = 0x00;
+               else if (tmp < 8)
+                       val = 0x01;
+               else if (tmp < 12)
+                       val = 0x02;
+               else if (tmp < 16)
+                       val = 0x03;
+               else if (tmp < 24)
+                       val = 0x04;
+               else if (tmp < 32)
+                       val = 0x05;
+               else
+                       val = 0x06;
+               s5h1420_writereg(state, 0x22, val);
+
+               /* DC freeze */
+               s5h1420_writereg(state, 0x1f, s5h1420_readreg(state, 0x1f) | 0x01);
+
+               /* kicker disable + remove DC offset */
+               s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) & 0x6f);
+
+               /* post-lock processing has been done! */
+               state->postlocked = 1;
+       }
+
+       return 0;
+}
+
+static int s5h1420_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+       struct s5h1420_state* state = fe->demodulator_priv;
+
+       s5h1420_writereg(state, 0x46, 0x1d);
+       mdelay(25);
+       return (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
+}
+
+static int s5h1420_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+       struct s5h1420_state* state = fe->demodulator_priv;
+
+       u8 val = 0xff - s5h1420_readreg(state, 0x15);
+
+       return (int) ((val << 8) | val);
+}
+
+static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+       struct s5h1420_state* state = fe->demodulator_priv;
+
+       s5h1420_writereg(state, 0x46, 0x1f);
+       mdelay(25);
+       return (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
+}
+
+static void s5h1420_reset(struct s5h1420_state* state)
+{
+       s5h1420_writereg (state, 0x01, 0x08);
+       s5h1420_writereg (state, 0x01, 0x00);
+       udelay(10);
+}
+
+static void s5h1420_setsymbolrate(struct s5h1420_state* state, struct dvb_frontend_parameters *p)
+{
+       u64 val;
+
+       val = (p->u.qpsk.symbol_rate / 1000) * (1<<24);
+       if (p->u.qpsk.symbol_rate <= 21000000) {
+               val *= 2;
+       }
+       do_div(val, (state->fclk / 1000));
+
+       s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) & 0x7f);
+       s5h1420_writereg(state, 0x11, val >> 16);
+       s5h1420_writereg(state, 0x12, val >> 8);
+       s5h1420_writereg(state, 0x13, val & 0xff);
+       s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) | 0x80);
+}
+
+static u32 s5h1420_getsymbolrate(struct s5h1420_state* state)
+{
+       u64 val;
+       int sampling = 2;
+
+       if (s5h1420_readreg(state, 0x05) & 0x2)
+               sampling = 1;
+
+       s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) | 0x08);
+       val  = s5h1420_readreg(state, 0x11) << 16;
+       val |= s5h1420_readreg(state, 0x12) << 8;
+       val |= s5h1420_readreg(state, 0x13);
+       s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) & 0xf7);
+
+       val *= (state->fclk / 1000);
+       do_div(val, ((1<<24) * sampling));
+
+       return (u32) (val * 1000);
+}
+
+static void s5h1420_setfreqoffset(struct s5h1420_state* state, int freqoffset)
+{
+       int val;
+
+       /* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
+        * divide fclk by 1000000 to get the correct value. */
+       val = -(int) ((freqoffset * (1<<24)) / (state->fclk / 1000000));
+
+       s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) & 0xbf);
+       s5h1420_writereg(state, 0x0e, val >> 16);
+       s5h1420_writereg(state, 0x0f, val >> 8);
+       s5h1420_writereg(state, 0x10, val & 0xff);
+       s5h1420_writereg(state, 0x09, s5h1420_readreg(state, 0x09) | 0x40);
+}
+
+static int s5h1420_getfreqoffset(struct s5h1420_state* state)
+{
+       int val;
+
+       s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) | 0x08);
+       val  = s5h1420_readreg(state, 0x0e) << 16;
+       val |= s5h1420_readreg(state, 0x0f) << 8;
+       val |= s5h1420_readreg(state, 0x10);
+       s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) & 0xf7);
+
+       if (val & 0x800000)
+               val |= 0xff000000;
+
+       /* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
+        * divide fclk by 1000000 to get the correct value. */
+       val = - ((val * (state->fclk/1000000)) / (1<<24));
+
+       return val;
+}
+
+static void s5h1420_setfec(struct s5h1420_state* state, struct dvb_frontend_parameters *p)
+{
+       if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
+               s5h1420_writereg(state, 0x31, 0x00);
+               s5h1420_writereg(state, 0x30, 0x3f);
+       } else {
+               switch(p->u.qpsk.fec_inner) {
+               case FEC_1_2:
+                       s5h1420_writereg(state, 0x31, 0x10);
+                       s5h1420_writereg(state, 0x30, 0x01);
+                       break;
+
+               case FEC_2_3:
+                       s5h1420_writereg(state, 0x31, 0x11);
+                       s5h1420_writereg(state, 0x30, 0x02);
+                       break;
+
+               case FEC_3_4:
+                       s5h1420_writereg(state, 0x31, 0x12);
+                       s5h1420_writereg(state, 0x30, 0x04);
+                       break;
+
+               case FEC_5_6:
+                       s5h1420_writereg(state, 0x31, 0x13);
+                       s5h1420_writereg(state, 0x30, 0x08);
+                       break;
+
+               case FEC_6_7:
+                       s5h1420_writereg(state, 0x31, 0x14);
+                       s5h1420_writereg(state, 0x30, 0x10);
+                       break;
+
+               case FEC_7_8:
+                       s5h1420_writereg(state, 0x31, 0x15);
+                       s5h1420_writereg(state, 0x30, 0x20);
+                       break;
+
+               default:
+                       return;
+               }
+       }
+}
+
+static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state)
+{
+       switch(s5h1420_readreg(state, 0x32) & 0x07) {
+       case 0:
+               return FEC_1_2;
+
+       case 1:
+               return FEC_2_3;
+
+       case 2:
+               return FEC_3_4;
+
+       case 3:
+               return FEC_5_6;
+
+       case 4:
+               return FEC_6_7;
+
+       case 5:
+               return FEC_7_8;
+       }
+
+       return FEC_NONE;
+}
+
+static void s5h1420_setinversion(struct s5h1420_state* state, struct dvb_frontend_parameters *p)
+{
+       if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
+               s5h1420_writereg(state, 0x31, 0x00);
+               s5h1420_writereg(state, 0x30, 0x3f);
+       } else {
+               u8 tmp = s5h1420_readreg(state, 0x31) & 0xf7;
+                       tmp |= 0x10;
+
+               if (p->inversion == INVERSION_ON)
+                       tmp |= 0x80;
+
+               s5h1420_writereg(state, 0x31, tmp);
+       }
+}
+
+static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state)
+{
+       if (s5h1420_readreg(state, 0x32) & 0x08)
+               return INVERSION_ON;
+
+       return INVERSION_OFF;
+}
+
+static int s5h1420_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+{
+       struct s5h1420_state* state = fe->demodulator_priv;
+       u32 frequency_delta;
+       struct dvb_frontend_tune_settings fesettings;
+
+       /* check if we should do a fast-tune */
+       memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters));
+       s5h1420_get_tune_settings(fe, &fesettings);
+       frequency_delta = p->frequency - state->tunedfreq;
+       if ((frequency_delta > -fesettings.max_drift) && (frequency_delta < fesettings.max_drift) &&
+           (frequency_delta != 0) &&
+           (state->fec_inner == p->u.qpsk.fec_inner) &&
+           (state->symbol_rate == p->u.qpsk.symbol_rate)) {
+
+               s5h1420_setfreqoffset(state, frequency_delta);
+               return 0;
+       }
+
+       /* first of all, software reset */
+       s5h1420_reset(state);
+
+       /* set tuner PLL */
+       if (state->config->pll_set) {
+               s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
+               state->config->pll_set(fe, p, &state->tunedfreq);
+               s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe);
+       }
+
+       /* set s5h1420 fclk PLL according to desired symbol rate */
+       if (p->u.qpsk.symbol_rate > 28000000) {
+               state->fclk = 88000000;
+               s5h1420_writereg(state, 0x03, 0x50);
+               s5h1420_writereg(state, 0x04, 0x40);
+               s5h1420_writereg(state, 0x05, 0xae);
+       } else if (p->u.qpsk.symbol_rate > 21000000) {
+               state->fclk = 59000000;
+               s5h1420_writereg(state, 0x03, 0x33);
+               s5h1420_writereg(state, 0x04, 0x40);
+               s5h1420_writereg(state, 0x05, 0xae);
+       } else {
+               state->fclk = 88000000;
+               s5h1420_writereg(state, 0x03, 0x50);
+               s5h1420_writereg(state, 0x04, 0x40);
+               s5h1420_writereg(state, 0x05, 0xac);
+       }
+
+       /* set misc registers */
+       s5h1420_writereg(state, 0x02, 0x00);
+       s5h1420_writereg(state, 0x07, 0xb0);
+       s5h1420_writereg(state, 0x0a, 0x67);
+       s5h1420_writereg(state, 0x0b, 0x78);
+       s5h1420_writereg(state, 0x0c, 0x48);
+       s5h1420_writereg(state, 0x0d, 0x6b);
+       s5h1420_writereg(state, 0x2e, 0x8e);
+       s5h1420_writereg(state, 0x35, 0x33);
+       s5h1420_writereg(state, 0x38, 0x01);
+       s5h1420_writereg(state, 0x39, 0x7d);
+       s5h1420_writereg(state, 0x3a, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
+       s5h1420_writereg(state, 0x3c, 0x00);
+       s5h1420_writereg(state, 0x45, 0x61);
+       s5h1420_writereg(state, 0x46, 0x1d);
+
+       /* start QPSK */
+       s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1);
+
+       /* set the frequency offset to adjust for PLL inaccuracy */
+       s5h1420_setfreqoffset(state, p->frequency - state->tunedfreq);
+
+       /* set the reset of the parameters */
+       s5h1420_setsymbolrate(state, p);
+       s5h1420_setinversion(state, p);
+       s5h1420_setfec(state, p);
+
+       state->fec_inner = p->u.qpsk.fec_inner;
+       state->symbol_rate = p->u.qpsk.symbol_rate;
+       state->postlocked = 0;
+       return 0;
+}
+
+static int s5h1420_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+{
+       struct s5h1420_state* state = fe->demodulator_priv;
+
+       p->frequency = state->tunedfreq + s5h1420_getfreqoffset(state);
+       p->inversion = s5h1420_getinversion(state);
+       p->u.qpsk.symbol_rate = s5h1420_getsymbolrate(state);
+       p->u.qpsk.fec_inner = s5h1420_getfec(state);
+
+       return 0;
+}
+
+static int s5h1420_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
+{
+       if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) {
+               fesettings->min_delay_ms = 50;
+               fesettings->step_size = 2000;
+               fesettings->max_drift = 8000;
+       } else if (fesettings->parameters.u.qpsk.symbol_rate > 12000000) {
+               fesettings->min_delay_ms = 100;
+               fesettings->step_size = 1500;
+               fesettings->max_drift = 9000;
+       } else if (fesettings->parameters.u.qpsk.symbol_rate > 8000000) {
+               fesettings->min_delay_ms = 100;
+               fesettings->step_size = 1000;
+               fesettings->max_drift = 8000;
+       } else if (fesettings->parameters.u.qpsk.symbol_rate > 4000000) {
+               fesettings->min_delay_ms = 100;
+               fesettings->step_size = 500;
+               fesettings->max_drift = 7000;
+       } else if (fesettings->parameters.u.qpsk.symbol_rate > 2000000) {
+               fesettings->min_delay_ms = 200;
+               fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
+               fesettings->max_drift = 14 * fesettings->step_size;
+       } else {
+               fesettings->min_delay_ms = 200;
+               fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
+               fesettings->max_drift = 18 * fesettings->step_size;
+       }
+
+       return 0;
+}
+
+static int s5h1420_init (struct dvb_frontend* fe)
+{
+       struct s5h1420_state* state = fe->demodulator_priv;
+
+       /* disable power down and do reset */
+       s5h1420_writereg(state, 0x02, 0x10);
+       msleep(10);
+       s5h1420_reset(state);
+
+       /* init PLL */
+       if (state->config->pll_init) {
+               s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
+               state->config->pll_init(fe);
+               s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe);
+       }
+
+       return 0;
+}
+
+static int s5h1420_sleep(struct dvb_frontend* fe)
+{
+       struct s5h1420_state* state = fe->demodulator_priv;
+
+       return s5h1420_writereg(state, 0x02, 0x12);
+}
+
+static void s5h1420_release(struct dvb_frontend* fe)
+{
+       struct s5h1420_state* state = fe->demodulator_priv;
+       kfree(state);
+}
+
+static struct dvb_frontend_ops s5h1420_ops;
+
+struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config, struct i2c_adapter* i2c)
+{
+       struct s5h1420_state* state = NULL;
+       u8 identity;
+
+       /* allocate memory for the internal state */
+       state = kmalloc(sizeof(struct s5h1420_state), GFP_KERNEL);
+       if (state == NULL)
+               goto error;
+
+       /* setup the state */
+       state->config = config;
+       state->i2c = i2c;
+       memcpy(&state->ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops));
+       state->postlocked = 0;
+       state->fclk = 88000000;
+       state->tunedfreq = 0;
+       state->fec_inner = FEC_NONE;
+       state->symbol_rate = 0;
+
+       /* check if the demod is there + identify it */
+       identity = s5h1420_readreg(state, 0x00);
+       if (identity != 0x03)
+               goto error;
+
+       /* create dvb_frontend */
+       state->frontend.ops = &state->ops;
+       state->frontend.demodulator_priv = state;
+       return &state->frontend;
+
+error:
+       kfree(state);
+       return NULL;
+}
+
+static struct dvb_frontend_ops s5h1420_ops = {
+
+       .info = {
+               .name     = "Samsung S5H1420 DVB-S",
+               .type     = FE_QPSK,
+               .frequency_min    = 950000,
+               .frequency_max    = 2150000,
+               .frequency_stepsize = 125,     /* kHz for QPSK frontends */
+               .frequency_tolerance  = 29500,
+               .symbol_rate_min  = 1000000,
+               .symbol_rate_max  = 45000000,
+               /*  .symbol_rate_tolerance  = ???,*/
+               .caps = FE_CAN_INVERSION_AUTO |
+               FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+               FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+               FE_CAN_QPSK
+       },
+
+       .release = s5h1420_release,
+
+       .init = s5h1420_init,
+       .sleep = s5h1420_sleep,
+
+       .set_frontend = s5h1420_set_frontend,
+       .get_frontend = s5h1420_get_frontend,
+       .get_tune_settings = s5h1420_get_tune_settings,
+
+       .read_status = s5h1420_read_status,
+       .read_ber = s5h1420_read_ber,
+       .read_signal_strength = s5h1420_read_signal_strength,
+       .read_ucblocks = s5h1420_read_ucblocks,
+
+       .diseqc_send_master_cmd = s5h1420_send_master_cmd,
+       .diseqc_recv_slave_reply = s5h1420_recv_slave_reply,
+       .diseqc_send_burst = s5h1420_send_burst,
+       .set_tone = s5h1420_set_tone,
+       .set_voltage = s5h1420_set_voltage,
+};
+
+module_param(debug, int, 0644);
+
+MODULE_DESCRIPTION("Samsung S5H1420 DVB-S Demodulator driver");
+MODULE_AUTHOR("Andrew de Quincey");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(s5h1420_attach);
diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb/frontends/s5h1420.h
new file mode 100644 (file)
index 0000000..b687fc7
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+    Driver for S5H1420 QPSK Demodulators
+
+    Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef S5H1420_H
+#define S5H1420_H
+
+#include <linux/dvb/frontend.h>
+
+struct s5h1420_config
+{
+       /* the demodulator's i2c address */
+       u8 demod_address;
+
+       /* PLL maintenance */
+       int (*pll_init)(struct dvb_frontend* fe);
+       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout);
+};
+
+extern struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
+             struct i2c_adapter* i2c);
+
+#endif // S5H1420_H
index e681263bf07986bb4252402c185069bf4960aaa3..928aca052afe355c3dc6106d8c2e3dfc2a133d0f 100644 (file)
@@ -617,7 +617,7 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
 
        /* wait for WGAGC lock */
        starttime = jiffies;
-       timeout = jiffies + (200 * HZ) / 1000;
+       timeout = jiffies + msecs_to_jiffies(2000);
        while (time_before(jiffies, timeout)) {
                msleep(10);
                if (stv0297_readreg(state, 0x43) & 0x08)
@@ -629,7 +629,7 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
        msleep(20);
 
        /* wait for equaliser partial convergence */
-       timeout = jiffies + (50 * HZ) / 1000;
+       timeout = jiffies + msecs_to_jiffies(500);
        while (time_before(jiffies, timeout)) {
                msleep(10);
 
@@ -642,7 +642,7 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
        }
 
        /* wait for equaliser full convergence */
-       timeout = jiffies + (delay * HZ) / 1000;
+       timeout = jiffies + msecs_to_jiffies(delay);
        while (time_before(jiffies, timeout)) {
                msleep(10);
 
@@ -659,7 +659,7 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
        stv0297_writereg_mask(state, 0x88, 8, 0);
 
        /* wait for main lock */
-       timeout = jiffies + (20 * HZ) / 1000;
+       timeout = jiffies + msecs_to_jiffies(20);
        while (time_before(jiffies, timeout)) {
                msleep(10);
 
index 0beb370792ae30584d42398ccdb98273ecb86f91..ab0c032472cc01bdb6f02eefdb05966df1ba014d 100644 (file)
@@ -49,10 +49,8 @@ struct tda1004x_state {
        /* private demod data */
        u8 initialised;
        enum tda1004x_demod demod_type;
-       u8 fw_version;
 };
 
-
 static int debug;
 #define dprintk(args...) \
        do { \
@@ -122,6 +120,8 @@ static int debug;
 #define TDA10046H_GPIO_OUT_SEL  0x41
 #define TDA10046H_GPIO_SELECT   0x42
 #define TDA10046H_AGC_CONF      0x43
+#define TDA10046H_AGC_THR       0x44
+#define TDA10046H_AGC_RENORM    0x45
 #define TDA10046H_AGC_GAINS     0x46
 #define TDA10046H_AGC_TUN_MIN   0x47
 #define TDA10046H_AGC_TUN_MAX   0x48
@@ -274,14 +274,26 @@ static int tda10046h_set_bandwidth(struct tda1004x_state *state,
        switch (bandwidth) {
        case BANDWIDTH_6_MHZ:
                tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz, sizeof(bandwidth_6mhz));
+               if (state->config->if_freq == TDA10046_FREQ_045) {
+                       tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x09);
+                       tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x4f);
+               }
                break;
 
        case BANDWIDTH_7_MHZ:
                tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz, sizeof(bandwidth_7mhz));
+               if (state->config->if_freq == TDA10046_FREQ_045) {
+                       tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0a);
+                       tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x79);
+               }
                break;
 
        case BANDWIDTH_8_MHZ:
                tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz, sizeof(bandwidth_8mhz));
+               if (state->config->if_freq == TDA10046_FREQ_045) {
+                       tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0b);
+                       tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xa3);
+               }
                break;
 
        default:
@@ -315,20 +327,35 @@ static int tda1004x_do_upload(struct tda1004x_state *state,
                memcpy(buf + 1, mem + pos, tx_size);
                fw_msg.len = tx_size + 1;
                if (i2c_transfer(state->i2c, &fw_msg, 1) != 1) {
-                       printk("tda1004x: Error during firmware upload\n");
+                       printk(KERN_ERR "tda1004x: Error during firmware upload\n");
                        return -EIO;
                }
                pos += tx_size;
 
                dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, pos);
        }
+       // give the DSP a chance to settle 03/10/05 Hac
+       msleep(100);
 
        return 0;
 }
 
-static int tda1004x_check_upload_ok(struct tda1004x_state *state, u8 dspVersion)
+static int tda1004x_check_upload_ok(struct tda1004x_state *state)
 {
        u8 data1, data2;
+       unsigned long timeout;
+
+       if (state->demod_type == TDA1004X_DEMOD_TDA10046) {
+               timeout = jiffies + 2 * HZ;
+               while(!(tda1004x_read_byte(state, TDA1004X_STATUS_CD) & 0x20)) {
+                       if (time_after(jiffies, timeout)) {
+                               printk(KERN_ERR "tda1004x: timeout waiting for DSP ready\n");
+                               break;
+                       }
+                       msleep(1);
+               }
+       } else
+               msleep(100);
 
        // check upload was OK
        tda1004x_write_mask(state, TDA1004X_CONFC4, 0x10, 0); // we want to read from the DSP
@@ -336,9 +363,11 @@ static int tda1004x_check_upload_ok(struct tda1004x_state *state, u8 dspVersion)
 
        data1 = tda1004x_read_byte(state, TDA1004X_DSP_DATA1);
        data2 = tda1004x_read_byte(state, TDA1004X_DSP_DATA2);
-       if ((data1 != 0x67) || (data2 != dspVersion))
+       if (data1 != 0x67 || data2 < 0x20 || data2 > 0x2e) {
+               printk(KERN_INFO "tda1004x: found firmware revision %x -- invalid\n", data2);
                return -EIO;
-
+       }
+       printk(KERN_INFO "tda1004x: found firmware revision %x -- ok\n", data2);
        return 0;
 }
 
@@ -349,14 +378,14 @@ static int tda10045_fwupload(struct dvb_frontend* fe)
        const struct firmware *fw;
 
        /* don't re-upload unless necessary */
-       if (tda1004x_check_upload_ok(state, 0x2c) == 0)
+       if (tda1004x_check_upload_ok(state) == 0)
                return 0;
 
        /* request the firmware, this will block until someone uploads it */
-       printk("tda1004x: waiting for firmware upload (%s)...\n", TDA10045_DEFAULT_FIRMWARE);
+       printk(KERN_INFO "tda1004x: waiting for firmware upload (%s)...\n", TDA10045_DEFAULT_FIRMWARE);
        ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE);
        if (ret) {
-               printk("tda1004x: no firmware upload (timeout or file not found?)\n");
+               printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n");
                return ret;
        }
 
@@ -370,95 +399,93 @@ static int tda10045_fwupload(struct dvb_frontend* fe)
        tda10045h_set_bandwidth(state, BANDWIDTH_8_MHZ);
 
        ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10045H_FWPAGE, TDA10045H_CODE_IN);
+       release_firmware(fw);
        if (ret)
                return ret;
-       printk("tda1004x: firmware upload complete\n");
+       printk(KERN_INFO "tda1004x: firmware upload complete\n");
 
        /* wait for DSP to initialise */
        /* DSPREADY doesn't seem to work on the TDA10045H */
        msleep(100);
 
-       return tda1004x_check_upload_ok(state, 0x2c);
+       return tda1004x_check_upload_ok(state);
 }
 
-static int tda10046_get_fw_version(struct tda1004x_state *state,
-                                  const struct firmware *fw)
+static void tda10046_init_plls(struct dvb_frontend* fe)
 {
-       const unsigned char pattern[] = { 0x67, 0x00, 0x50, 0x62, 0x5e, 0x18, 0x67 };
-       unsigned int i;
-
-       /* area guessed from firmware v20, v21 and v25 */
-       for (i = 0x660; i < 0x700; i++) {
-               if (!memcmp(&fw->data[i], pattern, sizeof(pattern))) {
-                       state->fw_version = fw->data[i + sizeof(pattern)];
-                       printk(KERN_INFO "tda1004x: using firmware v%02x\n",
-                                       state->fw_version);
-                       return 0;
-               }
-       }
+       struct tda1004x_state* state = fe->demodulator_priv;
 
-       return -EINVAL;
+       tda1004x_write_byteI(state, TDA10046H_CONFPLL1, 0xf0);
+       tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 10); // PLL M = 10
+       if (state->config->xtal_freq == TDA10046_XTAL_4M ) {
+               dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __FUNCTION__);
+               tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0
+       } else {
+               dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __FUNCTION__);
+               tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 3); // PLL P = 0, N = 3
+       }
+       tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 99);
+       switch (state->config->if_freq) {
+       case TDA10046_FREQ_3617:
+               tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4);
+               tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x2c);
+               break;
+       case TDA10046_FREQ_3613:
+               tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4);
+               tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x13);
+               break;
+       case TDA10046_FREQ_045:
+               tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0b);
+               tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xa3);
+               break;
+       case TDA10046_FREQ_052:
+               tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
+               tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x06);
+               break;
+       }
+       tda10046h_set_bandwidth(state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz
 }
 
 static int tda10046_fwupload(struct dvb_frontend* fe)
 {
        struct tda1004x_state* state = fe->demodulator_priv;
-       unsigned long timeout;
        int ret;
        const struct firmware *fw;
 
        /* reset + wake up chip */
-       tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 0);
+       tda1004x_write_byteI(state, TDA1004X_CONFC4, 0);
        tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 1, 0);
-       msleep(100);
+       /* let the clocks recover from sleep */
+       msleep(5);
 
        /* don't re-upload unless necessary */
-       if (tda1004x_check_upload_ok(state, state->fw_version) == 0)
+       if (tda1004x_check_upload_ok(state) == 0)
                return 0;
 
-       /* request the firmware, this will block until someone uploads it */
-       printk("tda1004x: waiting for firmware upload (%s)...\n", TDA10046_DEFAULT_FIRMWARE);
-       ret = state->config->request_firmware(fe, &fw, TDA10046_DEFAULT_FIRMWARE);
-       if (ret) {
-               printk("tda1004x: no firmware upload (timeout or file not found?)\n");
-               return ret;
-       }
-
-       if (fw->size < 24478) { /* size of firmware v20, which is the smallest of v20, v21 and v25 */
-               printk("tda1004x: firmware file seems to be too small (%d bytes)\n", fw->size);
-               return -EINVAL;
-       }
-
-       ret = tda10046_get_fw_version(state, fw);
-       if (ret < 0) {
-               printk("tda1004x: unable to find firmware version\n");
-               return ret;
-       }
-
        /* set parameters */
-       tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 10);
-       tda1004x_write_byteI(state, TDA10046H_CONFPLL3, state->config->n_i2c);
-       tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 99);
-       tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4);
-       tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x2c);
-       tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST
-
-       ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10046H_CODE_CPT, TDA10046H_CODE_IN);
-       if (ret)
-               return ret;
-       printk("tda1004x: firmware upload complete\n");
-
-       /* wait for DSP to initialise */
-       timeout = jiffies + HZ;
-       while (!(tda1004x_read_byte(state, TDA1004X_STATUS_CD) & 0x20)) {
-               if (time_after(jiffies, timeout)) {
-                       printk("tda1004x: DSP failed to initialised.\n");
-                       return -EIO;
+       tda10046_init_plls(fe);
+
+       if (state->config->request_firmware != NULL) {
+               /* request the firmware, this will block until someone uploads it */
+               printk(KERN_INFO "tda1004x: waiting for firmware upload...\n");
+               ret = state->config->request_firmware(fe, &fw, TDA10046_DEFAULT_FIRMWARE);
+               if (ret) {
+                       printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n");
+                       return ret;
                }
-               msleep(1);
+               tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST
+               ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10046H_CODE_CPT, TDA10046H_CODE_IN);
+               release_firmware(fw);
+               if (ret)
+                       return ret;
+       } else {
+               /* boot from firmware eeprom */
+               /* Hac Note: we might need to do some GPIO Magic here */
+               printk(KERN_INFO "tda1004x: booting from eeprom\n");
+               tda1004x_write_mask(state, TDA1004X_CONFC4, 4, 4);
+               msleep(300);
        }
-
-       return tda1004x_check_upload_ok(state, state->fw_version);
+       return tda1004x_check_upload_ok(state);
 }
 
 static int tda1004x_encode_fec(int fec)
@@ -560,12 +587,10 @@ static int tda10046_init(struct dvb_frontend* fe)
 
        if (tda10046_fwupload(fe)) {
                printk("tda1004x: firmware upload failed\n");
-               return -EIO;
+                       return -EIO;
        }
 
-       tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 0); // wake up the chip
-
-       // Init the PLL
+       // Init the tuner PLL
        if (state->config->pll_init) {
                tda1004x_enable_tuner_i2c(state);
                state->config->pll_init(fe);
@@ -574,32 +599,44 @@ static int tda10046_init(struct dvb_frontend* fe)
 
        // tda setup
        tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
-       tda1004x_write_mask(state, TDA1004X_CONFC1, 0x40, 0x40);
-       tda1004x_write_mask(state, TDA1004X_AUTO, 8, 0); // select HP stream
-       tda1004x_write_mask(state, TDA1004X_CONFC1, 0x80, 0); // disable pulse killer
-       tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 10); // PLL M = 10
-       tda1004x_write_byteI(state, TDA10046H_CONFPLL3, state->config->n_i2c); // PLL P = N = 0
-       tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 99); // FREQOFFS = 99
-       tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4); // } PHY2 = -11221
-       tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x2c); // }
-       tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0); // AGC setup
-       tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x60, 0x60); // set AGC polarities
+       tda1004x_write_byteI(state, TDA1004X_AUTO, 7); // select HP stream
+       tda1004x_write_byteI(state, TDA1004X_CONFC1, 8); // disable pulse killer
+
+       tda10046_init_plls(fe);
+       switch (state->config->agc_config) {
+       case TDA10046_AGC_DEFAULT:
+               tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x00); // AGC setup
+               tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities
+               break;
+       case TDA10046_AGC_IFO_AUTO_NEG:
+               tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup
+               tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities
+               break;
+       case TDA10046_AGC_IFO_AUTO_POS:
+               tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup
+               tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x00); // set AGC polarities
+               break;
+       case TDA10046_AGC_TDA827X:
+               tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02);   // AGC setup
+               tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70);    // AGC Threshold
+               tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x0E); // Gain Renormalize
+               tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities
+               break;
+       }
+       tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on
        tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MIN, 0);    // }
        tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values
        tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0);     // }
        tda1004x_write_byteI(state, TDA10046H_AGC_IF_MAX, 0xff);  // }
-       tda1004x_write_mask(state, TDA10046H_CVBER_CTRL, 0x30, 0x10); // 10^6 VBER measurement bits
        tda1004x_write_byteI(state, TDA10046H_AGC_GAINS, 1); // IF gain 2, TUN gain 1
-       tda1004x_write_mask(state, TDA1004X_AUTO, 0x80, 0); // crystal is 50ppm
+       tda1004x_write_byteI(state, TDA10046H_CVBER_CTRL, 0x1a); // 10^6 VBER measurement bits
        tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config
-       tda1004x_write_mask(state, TDA1004X_CONF_TS2, 0x31, 0); // MPEG2 interface config
-       tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 0x9e, 0); // disable AGC_TUN
+       tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0xc0); // MPEG2 interface config
+       tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7);
+
        tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE2, 0xe1); // tristate setup
        tda1004x_write_byteI(state, TDA10046H_GPIO_OUT_SEL, 0xcc); // GPIO output config
-       tda1004x_write_mask(state, TDA10046H_GPIO_SELECT, 8, 8); // GPIO select
-       tda10046h_set_bandwidth(state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz
-
-       tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7);
+       tda1004x_write_byteI(state, TDA10046H_GPIO_SELECT, 8); // GPIO select
 
        state->initialised = 1;
        return 0;
@@ -629,9 +666,6 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
        state->config->pll_set(fe, fe_params);
        tda1004x_disable_tuner_i2c(state);
 
-       if (state->demod_type == TDA1004X_DEMOD_TDA10046)
-               tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 4);
-
        // Hardcoded to use auto as much as possible on the TDA10045 as it
        // is very unreliable if AUTO mode is _not_ used.
        if (state->demod_type == TDA1004X_DEMOD_TDA10045) {
@@ -1089,6 +1123,11 @@ static int tda1004x_sleep(struct dvb_frontend* fe)
                break;
 
        case TDA1004X_DEMOD_TDA10046:
+               if (state->config->pll_sleep != NULL) {
+                       tda1004x_enable_tuner_i2c(state);
+                       state->config->pll_sleep(fe);
+                       tda1004x_disable_tuner_i2c(state);
+               }
                tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1);
                break;
        }
@@ -1100,8 +1139,9 @@ static int tda1004x_sleep(struct dvb_frontend* fe)
 static int tda1004x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
 {
        fesettings->min_delay_ms = 800;
-       fesettings->step_size = 166667;
-       fesettings->max_drift = 166667*2;
+       /* Drift compensation makes no sense for DVB-T */
+       fesettings->step_size = 0;
+       fesettings->max_drift = 0;
        return 0;
 }
 
@@ -1216,7 +1256,6 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
        memcpy(&state->ops, &tda10046_ops, sizeof(struct dvb_frontend_ops));
        state->initialised = 0;
        state->demod_type = TDA1004X_DEMOD_TDA10046;
-       state->fw_version = 0x20;       /* dummy default value */
 
        /* check if the demod is there */
        if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x46) {
index c8e1d54ff26283b0b9a475f1fa2a5006d34922a4..8659c52647adf839139a7e1ae38e95071ff800a5 100644 (file)
 #include <linux/dvb/frontend.h>
 #include <linux/firmware.h>
 
+enum tda10046_xtal {
+       TDA10046_XTAL_4M,
+       TDA10046_XTAL_16M,
+};
+
+enum tda10046_agc {
+       TDA10046_AGC_DEFAULT,           /* original configuration */
+       TDA10046_AGC_IFO_AUTO_NEG,      /* IF AGC only, automatic, negtive */
+       TDA10046_AGC_IFO_AUTO_POS,      /* IF AGC only, automatic, positive */
+       TDA10046_AGC_TDA827X,       /* IF AGC only, special setup for tda827x */
+};
+
+enum tda10046_if {
+       TDA10046_FREQ_3617,             /* original config, 36,166 MHZ */
+       TDA10046_FREQ_3613,             /* 36,13 MHZ */
+       TDA10046_FREQ_045,              /* low IF, 4.0, 4.5, or 5.0 MHZ */
+       TDA10046_FREQ_052,              /* low IF, 5.1667 MHZ for tda9889 */
+};
+
 struct tda1004x_config
 {
        /* the demodulator's i2c address */
@@ -37,14 +56,22 @@ struct tda1004x_config
        /* Does the OCLK signal need inverted? */
        u8 invert_oclk;
 
-       /* value of N_I2C of the CONF_PLL3 register */
-       u8 n_i2c;
+       /* Xtal frequency, 4 or 16MHz*/
+       enum tda10046_xtal xtal_freq;
+
+       /* IF frequency */
+       enum tda10046_if if_freq;
+
+       /* AGC configuration */
+       enum tda10046_agc agc_config;
 
        /* PLL maintenance */
        int (*pll_init)(struct dvb_frontend* fe);
+       void (*pll_sleep)(struct dvb_frontend* fe);
        int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 
        /* request firmware for device */
+       /* set this to NULL if the card has a firmware EEPROM */
        int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
 };
 
diff --git a/drivers/media/dvb/pluto2/Kconfig b/drivers/media/dvb/pluto2/Kconfig
new file mode 100644 (file)
index 0000000..f02842b
--- /dev/null
@@ -0,0 +1,16 @@
+config DVB_PLUTO2
+       tristate "Pluto2 cards"
+       depends on DVB_CORE && PCI
+       select I2C
+       select I2C_ALGOBIT
+       select DVB_TDA1004X
+       help
+         Support for PCI cards based on the Pluto2 FPGA like the Satelco
+         Easywatch Mobile Terrestrial DVB-T Receiver.
+
+          Since these cards have no MPEG decoder onboard, they transmit
+         only compressed MPEG data over the PCI bus, so you need
+         an external software decoder to watch TV on your computer.
+
+         Say Y or M if you own such a device and want to use it.
+
diff --git a/drivers/media/dvb/pluto2/Makefile b/drivers/media/dvb/pluto2/Makefile
new file mode 100644 (file)
index 0000000..86ca84b
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_DVB_PLUTO2) = pluto2.o
+
+EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
new file mode 100644 (file)
index 0000000..706e0bc
--- /dev/null
@@ -0,0 +1,809 @@
+/*
+ * pluto2.c - Satelco Easywatch Mobile Terrestrial Receiver [DVB-T]
+ *
+ * Copyright (C) 2005 Andreas Oberritter <obi@linuxtv.org>
+ *
+ * based on pluto2.c 1.10 - http://instinct-wp8.no-ip.org/pluto/
+ *     by Dany Salman <salmandany@yahoo.fr>
+ *     Copyright (c) 2004 TDF
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+
+#include "demux.h"
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+#include "dvbdev.h"
+#include "tda1004x.h"
+
+#define DRIVER_NAME            "pluto2"
+
+#define REG_PIDn(n)            ((n) << 2)      /* PID n pattern registers */
+#define REG_PCAR               0x0020          /* PC address register */
+#define REG_TSCR               0x0024          /* TS ctrl & status */
+#define REG_MISC               0x0028          /* miscellaneous */
+#define REG_MMAC               0x002c          /* MSB MAC address */
+#define REG_IMAC               0x0030          /* ISB MAC address */
+#define REG_LMAC               0x0034          /* LSB MAC address */
+#define REG_SPID               0x0038          /* SPI data */
+#define REG_SLCS               0x003c          /* serial links ctrl/status */
+
+#define PID0_NOFIL             (0x0001 << 16)
+#define PIDn_ENP               (0x0001 << 15)
+#define PID0_END               (0x0001 << 14)
+#define PID0_AFIL              (0x0001 << 13)
+#define PIDn_PID               (0x1fff <<  0)
+
+#define TSCR_NBPACKETS         (0x00ff << 24)
+#define TSCR_DEM               (0x0001 << 17)
+#define TSCR_DE                        (0x0001 << 16)
+#define TSCR_RSTN              (0x0001 << 15)
+#define TSCR_MSKO              (0x0001 << 14)
+#define TSCR_MSKA              (0x0001 << 13)
+#define TSCR_MSKL              (0x0001 << 12)
+#define TSCR_OVR               (0x0001 << 11)
+#define TSCR_AFUL              (0x0001 << 10)
+#define TSCR_LOCK              (0x0001 <<  9)
+#define TSCR_IACK              (0x0001 <<  8)
+#define TSCR_ADEF              (0x007f <<  0)
+
+#define MISC_DVR               (0x0fff <<  4)
+#define MISC_ALED              (0x0001 <<  3)
+#define MISC_FRST              (0x0001 <<  2)
+#define MISC_LED1              (0x0001 <<  1)
+#define MISC_LED0              (0x0001 <<  0)
+
+#define SPID_SPIDR             (0x00ff <<  0)
+
+#define SLCS_SCL               (0x0001 <<  7)
+#define SLCS_SDA               (0x0001 <<  6)
+#define SLCS_CSN               (0x0001 <<  2)
+#define SLCS_OVR               (0x0001 <<  1)
+#define SLCS_SWC               (0x0001 <<  0)
+
+#define TS_DMA_PACKETS         (8)
+#define TS_DMA_BYTES           (188 * TS_DMA_PACKETS)
+
+#define I2C_ADDR_TDA10046      0x10
+#define I2C_ADDR_TUA6034       0xc2
+#define NHWFILTERS             8
+
+struct pluto {
+       /* pci */
+       struct pci_dev *pdev;
+       u8 __iomem *io_mem;
+
+       /* dvb */
+       struct dmx_frontend hw_frontend;
+       struct dmx_frontend mem_frontend;
+       struct dmxdev dmxdev;
+       struct dvb_adapter dvb_adapter;
+       struct dvb_demux demux;
+       struct dvb_frontend *fe;
+       struct dvb_net dvbnet;
+       unsigned int full_ts_users;
+       unsigned int users;
+
+       /* i2c */
+       struct i2c_algo_bit_data i2c_bit;
+       struct i2c_adapter i2c_adap;
+       unsigned int i2cbug;
+
+       /* irq */
+       unsigned int overflow;
+
+       /* dma */
+       dma_addr_t dma_addr;
+       u8 dma_buf[TS_DMA_BYTES];
+       u8 dummy[4096];
+};
+
+static inline struct pluto *feed_to_pluto(struct dvb_demux_feed *feed)
+{
+       return container_of(feed->demux, struct pluto, demux);
+}
+
+static inline struct pluto *frontend_to_pluto(struct dvb_frontend *fe)
+{
+       return container_of(fe->dvb, struct pluto, dvb_adapter);
+}
+
+static inline u32 pluto_readreg(struct pluto *pluto, u32 reg)
+{
+       return readl(&pluto->io_mem[reg]);
+}
+
+static inline void pluto_writereg(struct pluto *pluto, u32 reg, u32 val)
+{
+       writel(val, &pluto->io_mem[reg]);
+}
+
+static inline void pluto_rw(struct pluto *pluto, u32 reg, u32 mask, u32 bits)
+{
+       u32 val = readl(&pluto->io_mem[reg]);
+       val &= ~mask;
+       val |= bits;
+       writel(val, &pluto->io_mem[reg]);
+}
+
+static void pluto_setsda(void *data, int state)
+{
+       struct pluto *pluto = data;
+
+       if (state)
+               pluto_rw(pluto, REG_SLCS, SLCS_SDA, SLCS_SDA);
+       else
+               pluto_rw(pluto, REG_SLCS, SLCS_SDA, 0);
+}
+
+static void pluto_setscl(void *data, int state)
+{
+       struct pluto *pluto = data;
+
+       if (state)
+               pluto_rw(pluto, REG_SLCS, SLCS_SCL, SLCS_SCL);
+       else
+               pluto_rw(pluto, REG_SLCS, SLCS_SCL, 0);
+
+       /* try to detect i2c_inb() to workaround hardware bug:
+        * reset SDA to high after SCL has been set to low */
+       if ((state) && (pluto->i2cbug == 0)) {
+               pluto->i2cbug = 1;
+       } else {
+               if ((!state) && (pluto->i2cbug == 1))
+                       pluto_setsda(pluto, 1);
+               pluto->i2cbug = 0;
+       }
+}
+
+static int pluto_getsda(void *data)
+{
+       struct pluto *pluto = data;
+
+       return pluto_readreg(pluto, REG_SLCS) & SLCS_SDA;
+}
+
+static int pluto_getscl(void *data)
+{
+       struct pluto *pluto = data;
+
+       return pluto_readreg(pluto, REG_SLCS) & SLCS_SCL;
+}
+
+static void pluto_reset_frontend(struct pluto *pluto, int reenable)
+{
+       u32 val = pluto_readreg(pluto, REG_MISC);
+
+       if (val & MISC_FRST) {
+               val &= ~MISC_FRST;
+               pluto_writereg(pluto, REG_MISC, val);
+       }
+       if (reenable) {
+               val |= MISC_FRST;
+               pluto_writereg(pluto, REG_MISC, val);
+       }
+}
+
+static void pluto_reset_ts(struct pluto *pluto, int reenable)
+{
+       u32 val = pluto_readreg(pluto, REG_TSCR);
+
+       if (val & TSCR_RSTN) {
+               val &= ~TSCR_RSTN;
+               pluto_writereg(pluto, REG_TSCR, val);
+       }
+       if (reenable) {
+               val |= TSCR_RSTN;
+               pluto_writereg(pluto, REG_TSCR, val);
+       }
+}
+
+static void pluto_set_dma_addr(struct pluto *pluto)
+{
+       pluto_writereg(pluto, REG_PCAR, cpu_to_le32(pluto->dma_addr));
+}
+
+static int __devinit pluto_dma_map(struct pluto *pluto)
+{
+       pluto->dma_addr = pci_map_single(pluto->pdev, pluto->dma_buf,
+                       TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
+
+       return pci_dma_mapping_error(pluto->dma_addr);
+}
+
+static void pluto_dma_unmap(struct pluto *pluto)
+{
+       pci_unmap_single(pluto->pdev, pluto->dma_addr,
+                       TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
+}
+
+static int pluto_start_feed(struct dvb_demux_feed *f)
+{
+       struct pluto *pluto = feed_to_pluto(f);
+
+       /* enable PID filtering */
+       if (pluto->users++ == 0)
+               pluto_rw(pluto, REG_PIDn(0), PID0_AFIL | PID0_NOFIL, 0);
+
+       if ((f->pid < 0x2000) && (f->index < NHWFILTERS))
+               pluto_rw(pluto, REG_PIDn(f->index), PIDn_ENP | PIDn_PID, PIDn_ENP | f->pid);
+       else if (pluto->full_ts_users++ == 0)
+               pluto_rw(pluto, REG_PIDn(0), PID0_NOFIL, PID0_NOFIL);
+
+       return 0;
+}
+
+static int pluto_stop_feed(struct dvb_demux_feed *f)
+{
+       struct pluto *pluto = feed_to_pluto(f);
+
+       /* disable PID filtering */
+       if (--pluto->users == 0)
+               pluto_rw(pluto, REG_PIDn(0), PID0_AFIL, PID0_AFIL);
+
+       if ((f->pid < 0x2000) && (f->index < NHWFILTERS))
+               pluto_rw(pluto, REG_PIDn(f->index), PIDn_ENP | PIDn_PID, 0x1fff);
+       else if (--pluto->full_ts_users == 0)
+               pluto_rw(pluto, REG_PIDn(0), PID0_NOFIL, 0);
+
+       return 0;
+}
+
+static void pluto_dma_end(struct pluto *pluto, unsigned int nbpackets)
+{
+       /* synchronize the DMA transfer with the CPU
+        * first so that we see updated contents. */
+       pci_dma_sync_single_for_cpu(pluto->pdev, pluto->dma_addr,
+                       TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
+
+       /* Workaround for broken hardware:
+        * [1] On startup NBPACKETS seems to contain an uninitialized value,
+        *     but no packets have been transfered.
+        * [2] Sometimes (actually very often) NBPACKETS stays at zero
+        *     although one packet has been transfered.
+        */
+       if ((nbpackets == 0) || (nbpackets > TS_DMA_PACKETS)) {
+               unsigned int i = 0, valid;
+               while (pluto->dma_buf[i] == 0x47)
+                       i += 188;
+               valid = i / 188;
+               if (nbpackets != valid) {
+                       dev_err(&pluto->pdev->dev, "nbpackets=%u valid=%u\n",
+                                       nbpackets, valid);
+                       nbpackets = valid;
+               }
+       }
+
+       dvb_dmx_swfilter_packets(&pluto->demux, pluto->dma_buf, nbpackets);
+
+       /* clear the dma buffer. this is needed to be able to identify
+        * new valid ts packets above */
+       memset(pluto->dma_buf, 0, nbpackets * 188);
+
+       /* reset the dma address */
+       pluto_set_dma_addr(pluto);
+
+       /* sync the buffer and give it back to the card */
+       pci_dma_sync_single_for_device(pluto->pdev, pluto->dma_addr,
+                       TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
+}
+
+static irqreturn_t pluto_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct pluto *pluto = dev_id;
+       u32 tscr;
+
+       /* check whether an interrupt occured on this device */
+       tscr = pluto_readreg(pluto, REG_TSCR);
+       if (!(tscr & (TSCR_DE | TSCR_OVR)))
+               return IRQ_NONE;
+
+       if (tscr == 0xffffffff) {
+               // FIXME: maybe recover somehow
+               dev_err(&pluto->pdev->dev, "card hung up :(\n");
+               return IRQ_HANDLED;
+       }
+
+       /* dma end interrupt */
+       if (tscr & TSCR_DE) {
+               pluto_dma_end(pluto, (tscr & TSCR_NBPACKETS) >> 24);
+               /* overflow interrupt */
+               if (tscr & TSCR_OVR)
+                       pluto->overflow++;
+               if (pluto->overflow) {
+                       dev_err(&pluto->pdev->dev, "overflow irq (%d)\n",
+                                       pluto->overflow);
+                       pluto_reset_ts(pluto, 1);
+                       pluto->overflow = 0;
+               }
+       } else if (tscr & TSCR_OVR) {
+               pluto->overflow++;
+       }
+
+       /* ACK the interrupt */
+       pluto_writereg(pluto, REG_TSCR, tscr | TSCR_IACK);
+
+       return IRQ_HANDLED;
+}
+
+static void __devinit pluto_enable_irqs(struct pluto *pluto)
+{
+       u32 val = pluto_readreg(pluto, REG_TSCR);
+
+       /* set the number of packets */
+       val &= ~TSCR_ADEF;
+       val |= TS_DMA_PACKETS / 2;
+       /* disable AFUL and LOCK interrupts */
+       val |= (TSCR_MSKA | TSCR_MSKL);
+       /* enable DMA and OVERFLOW interrupts */
+       val &= ~(TSCR_DEM | TSCR_MSKO);
+       /* clear pending interrupts */
+       val |= TSCR_IACK;
+
+       pluto_writereg(pluto, REG_TSCR, val);
+}
+
+static void pluto_disable_irqs(struct pluto *pluto)
+{
+       u32 val = pluto_readreg(pluto, REG_TSCR);
+
+       /* disable all interrupts */
+       val |= (TSCR_DEM | TSCR_MSKO | TSCR_MSKA | TSCR_MSKL);
+       /* clear pending interrupts */
+       val |= TSCR_IACK;
+
+       pluto_writereg(pluto, REG_TSCR, val);
+}
+
+static int __devinit pluto_hw_init(struct pluto *pluto)
+{
+       pluto_reset_frontend(pluto, 1);
+
+       /* set automatic LED control by FPGA */
+       pluto_rw(pluto, REG_MISC, MISC_ALED, MISC_ALED);
+
+       /* set data endianess */
+#ifdef __LITTLE_ENDIAN
+       pluto_rw(pluto, REG_PIDn(0), PID0_END, PID0_END);
+#else
+       pluto_rw(pluto, REG_PIDn(0), PID0_END, 0);
+#endif
+       /* map DMA and set address */
+       pluto_dma_map(pluto);
+       pluto_set_dma_addr(pluto);
+
+       /* enable interrupts */
+       pluto_enable_irqs(pluto);
+
+       /* reset TS logic */
+       pluto_reset_ts(pluto, 1);
+
+       return 0;
+}
+
+static void pluto_hw_exit(struct pluto *pluto)
+{
+       /* disable interrupts */
+       pluto_disable_irqs(pluto);
+
+       pluto_reset_ts(pluto, 0);
+
+       /* LED: disable automatic control, enable yellow, disable green */
+       pluto_rw(pluto, REG_MISC, MISC_ALED | MISC_LED1 | MISC_LED0, MISC_LED1);
+
+       /* unmap DMA */
+       pluto_dma_unmap(pluto);
+
+       pluto_reset_frontend(pluto, 0);
+}
+
+static inline u32 divide(u32 numerator, u32 denominator)
+{
+       if (denominator == 0)
+               return ~0;
+
+       return (numerator + denominator / 2) / denominator;
+}
+
+/* LG Innotek TDTE-E001P (Infineon TUA6034) */
+static int lg_tdtpe001p_pll_set(struct dvb_frontend *fe,
+                               struct dvb_frontend_parameters *p)
+{
+       struct pluto *pluto = frontend_to_pluto(fe);
+       struct i2c_msg msg;
+       int ret;
+       u8 buf[4];
+       u32 div;
+
+       // Fref = 166.667 Hz
+       // Fref * 3 = 500.000 Hz
+       // IF = 36166667
+       // IF / Fref = 217
+       //div = divide(p->frequency + 36166667, 166667);
+       div = divide(p->frequency * 3, 500000) + 217;
+       buf[0] = (div >> 8) & 0x7f;
+       buf[1] = (div >> 0) & 0xff;
+
+       if (p->frequency < 611000000)
+               buf[2] = 0xb4;
+       else if (p->frequency < 811000000)
+               buf[2] = 0xbc;
+       else
+               buf[2] = 0xf4;
+
+       // VHF: 174-230 MHz
+       // center: 350 MHz
+       // UHF: 470-862 MHz
+       if (p->frequency < 350000000)
+               buf[3] = 0x02;
+       else
+               buf[3] = 0x04;
+
+       if (p->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
+               buf[3] |= 0x08;
+
+       if (sizeof(buf) == 6) {
+               buf[4] = buf[2];
+               buf[4] &= ~0x1c;
+               buf[4] |=  0x18;
+
+               buf[5] = (0 << 7) | (2 << 4);
+       }
+
+       msg.addr = I2C_ADDR_TUA6034 >> 1;
+       msg.flags = 0;
+       msg.buf = buf;
+       msg.len = sizeof(buf);
+
+       ret = i2c_transfer(&pluto->i2c_adap, &msg, 1);
+       if (ret < 0)
+               return ret;
+       else if (ret == 0)
+               return -EREMOTEIO;
+
+       return 0;
+}
+
+static int pluto2_request_firmware(struct dvb_frontend *fe,
+                                  const struct firmware **fw, char *name)
+{
+       struct pluto *pluto = frontend_to_pluto(fe);
+
+       return request_firmware(fw, name, &pluto->pdev->dev);
+}
+
+static struct tda1004x_config pluto2_fe_config __devinitdata = {
+       .demod_address = I2C_ADDR_TDA10046 >> 1,
+       .invert = 1,
+       .invert_oclk = 0,
+       .xtal_freq = TDA10046_XTAL_16M,
+       .agc_config = TDA10046_AGC_DEFAULT,
+       .if_freq = TDA10046_FREQ_3617,
+       .pll_set = lg_tdtpe001p_pll_set,
+       .pll_sleep = NULL,
+       .request_firmware = pluto2_request_firmware,
+};
+
+static int __devinit frontend_init(struct pluto *pluto)
+{
+       int ret;
+
+       pluto->fe = tda10046_attach(&pluto2_fe_config, &pluto->i2c_adap);
+       if (!pluto->fe) {
+               dev_err(&pluto->pdev->dev, "could not attach frontend\n");
+               return -ENODEV;
+       }
+
+       ret = dvb_register_frontend(&pluto->dvb_adapter, pluto->fe);
+       if (ret < 0) {
+               if (pluto->fe->ops->release)
+                       pluto->fe->ops->release(pluto->fe);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void __devinit pluto_read_rev(struct pluto *pluto)
+{
+       u32 val = pluto_readreg(pluto, REG_MISC) & MISC_DVR;
+       dev_info(&pluto->pdev->dev, "board revision %d.%d\n",
+                       (val >> 12) & 0x0f, (val >> 4) & 0xff);
+}
+
+static void __devinit pluto_read_mac(struct pluto *pluto, u8 *mac)
+{
+       u32 val = pluto_readreg(pluto, REG_MMAC);
+       mac[0] = (val >> 8) & 0xff;
+       mac[1] = (val >> 0) & 0xff;
+
+       val = pluto_readreg(pluto, REG_IMAC);
+       mac[2] = (val >> 8) & 0xff;
+       mac[3] = (val >> 0) & 0xff;
+
+       val = pluto_readreg(pluto, REG_LMAC);
+       mac[4] = (val >> 8) & 0xff;
+       mac[5] = (val >> 0) & 0xff;
+
+       dev_info(&pluto->pdev->dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+                       mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+}
+
+static int __devinit pluto_read_serial(struct pluto *pluto)
+{
+       struct pci_dev *pdev = pluto->pdev;
+       unsigned int i, j;
+       u8 __iomem *cis;
+
+       cis = pci_iomap(pdev, 1, 0);
+       if (!cis)
+               return -EIO;
+
+       dev_info(&pdev->dev, "S/N ");
+
+       for (i = 0xe0; i < 0x100; i += 4) {
+               u32 val = readl(&cis[i]);
+               for (j = 0; j < 32; j += 8) {
+                       if ((val & 0xff) == 0xff)
+                               goto out;
+                       printk("%c", val & 0xff);
+                       val >>= 8;
+               }
+       }
+out:
+       printk("\n");
+       pci_iounmap(pdev, cis);
+
+       return 0;
+}
+
+static int __devinit pluto2_probe(struct pci_dev *pdev,
+                                 const struct pci_device_id *ent)
+{
+       struct pluto *pluto;
+       struct dvb_adapter *dvb_adapter;
+       struct dvb_demux *dvbdemux;
+       struct dmx_demux *dmx;
+       int ret = -ENOMEM;
+
+       pluto = kmalloc(sizeof(struct pluto), GFP_KERNEL);
+       if (!pluto)
+               goto out;
+
+       memset(pluto, 0, sizeof(struct pluto));
+       pluto->pdev = pdev;
+
+       ret = pci_enable_device(pdev);
+       if (ret < 0)
+               goto err_kfree;
+
+       /* enable interrupts */
+       pci_write_config_dword(pdev, 0x6c, 0x8000);
+
+       ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+       if (ret < 0)
+               goto err_pci_disable_device;
+
+       pci_set_master(pdev);
+
+       ret = pci_request_regions(pdev, DRIVER_NAME);
+       if (ret < 0)
+               goto err_pci_disable_device;
+
+       pluto->io_mem = pci_iomap(pdev, 0, 0x40);
+       if (!pluto->io_mem) {
+               ret = -EIO;
+               goto err_pci_release_regions;
+       }
+
+       pci_set_drvdata(pdev, pluto);
+
+       ret = request_irq(pdev->irq, pluto_irq, SA_SHIRQ, DRIVER_NAME, pluto);
+       if (ret < 0)
+               goto err_pci_iounmap;
+
+       ret = pluto_hw_init(pluto);
+       if (ret < 0)
+               goto err_free_irq;
+
+       /* i2c */
+       i2c_set_adapdata(&pluto->i2c_adap, pluto);
+       strcpy(pluto->i2c_adap.name, DRIVER_NAME);
+       pluto->i2c_adap.owner = THIS_MODULE;
+       pluto->i2c_adap.id = I2C_ALGO_BIT;
+       pluto->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
+       pluto->i2c_adap.dev.parent = &pdev->dev;
+       pluto->i2c_adap.algo_data = &pluto->i2c_bit;
+       pluto->i2c_bit.data = pluto;
+       pluto->i2c_bit.setsda = pluto_setsda;
+       pluto->i2c_bit.setscl = pluto_setscl;
+       pluto->i2c_bit.getsda = pluto_getsda;
+       pluto->i2c_bit.getscl = pluto_getscl;
+       pluto->i2c_bit.udelay = 10;
+       pluto->i2c_bit.timeout = 10;
+
+       /* Raise SCL and SDA */
+       pluto_setsda(pluto, 1);
+       pluto_setscl(pluto, 1);
+
+       ret = i2c_bit_add_bus(&pluto->i2c_adap);
+       if (ret < 0)
+               goto err_pluto_hw_exit;
+
+       /* dvb */
+       ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE);
+       if (ret < 0)
+               goto err_i2c_bit_del_bus;
+
+       dvb_adapter = &pluto->dvb_adapter;
+
+       pluto_read_rev(pluto);
+       pluto_read_serial(pluto);
+       pluto_read_mac(pluto, dvb_adapter->proposed_mac);
+
+       dvbdemux = &pluto->demux;
+       dvbdemux->filternum = 256;
+       dvbdemux->feednum = 256;
+       dvbdemux->start_feed = pluto_start_feed;
+       dvbdemux->stop_feed = pluto_stop_feed;
+       dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
+                       DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
+       ret = dvb_dmx_init(dvbdemux);
+       if (ret < 0)
+               goto err_dvb_unregister_adapter;
+
+       dmx = &dvbdemux->dmx;
+
+       pluto->hw_frontend.source = DMX_FRONTEND_0;
+       pluto->mem_frontend.source = DMX_MEMORY_FE;
+       pluto->dmxdev.filternum = NHWFILTERS;
+       pluto->dmxdev.demux = dmx;
+
+       ret = dvb_dmxdev_init(&pluto->dmxdev, dvb_adapter);
+       if (ret < 0)
+               goto err_dvb_dmx_release;
+
+       ret = dmx->add_frontend(dmx, &pluto->hw_frontend);
+       if (ret < 0)
+               goto err_dvb_dmxdev_release;
+
+       ret = dmx->add_frontend(dmx, &pluto->mem_frontend);
+       if (ret < 0)
+               goto err_remove_hw_frontend;
+
+       ret = dmx->connect_frontend(dmx, &pluto->hw_frontend);
+       if (ret < 0)
+               goto err_remove_mem_frontend;
+
+       ret = frontend_init(pluto);
+       if (ret < 0)
+               goto err_disconnect_frontend;
+
+       dvb_net_init(dvb_adapter, &pluto->dvbnet, dmx);
+out:
+       return ret;
+
+err_disconnect_frontend:
+       dmx->disconnect_frontend(dmx);
+err_remove_mem_frontend:
+       dmx->remove_frontend(dmx, &pluto->mem_frontend);
+err_remove_hw_frontend:
+       dmx->remove_frontend(dmx, &pluto->hw_frontend);
+err_dvb_dmxdev_release:
+       dvb_dmxdev_release(&pluto->dmxdev);
+err_dvb_dmx_release:
+       dvb_dmx_release(dvbdemux);
+err_dvb_unregister_adapter:
+       dvb_unregister_adapter(dvb_adapter);
+err_i2c_bit_del_bus:
+       i2c_bit_del_bus(&pluto->i2c_adap);
+err_pluto_hw_exit:
+       pluto_hw_exit(pluto);
+err_free_irq:
+       free_irq(pdev->irq, pluto);
+err_pci_iounmap:
+       pci_iounmap(pdev, pluto->io_mem);
+err_pci_release_regions:
+       pci_release_regions(pdev);
+err_pci_disable_device:
+       pci_disable_device(pdev);
+err_kfree:
+       pci_set_drvdata(pdev, NULL);
+       kfree(pluto);
+       goto out;
+}
+
+static void __devexit pluto2_remove(struct pci_dev *pdev)
+{
+       struct pluto *pluto = pci_get_drvdata(pdev);
+       struct dvb_adapter *dvb_adapter = &pluto->dvb_adapter;
+       struct dvb_demux *dvbdemux = &pluto->demux;
+       struct dmx_demux *dmx = &dvbdemux->dmx;
+
+       dmx->close(dmx);
+       dvb_net_release(&pluto->dvbnet);
+       if (pluto->fe)
+               dvb_unregister_frontend(pluto->fe);
+
+       dmx->disconnect_frontend(dmx);
+       dmx->remove_frontend(dmx, &pluto->mem_frontend);
+       dmx->remove_frontend(dmx, &pluto->hw_frontend);
+       dvb_dmxdev_release(&pluto->dmxdev);
+       dvb_dmx_release(dvbdemux);
+       dvb_unregister_adapter(dvb_adapter);
+       i2c_bit_del_bus(&pluto->i2c_adap);
+       pluto_hw_exit(pluto);
+       free_irq(pdev->irq, pluto);
+       pci_iounmap(pdev, pluto->io_mem);
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+       pci_set_drvdata(pdev, NULL);
+       kfree(pluto);
+}
+
+#ifndef PCI_VENDOR_ID_SCM
+#define PCI_VENDOR_ID_SCM      0x0432
+#endif
+#ifndef PCI_DEVICE_ID_PLUTO2
+#define PCI_DEVICE_ID_PLUTO2   0x0001
+#endif
+
+static struct pci_device_id pluto2_id_table[] __devinitdata = {
+       {
+               .vendor = PCI_VENDOR_ID_SCM,
+               .device = PCI_DEVICE_ID_PLUTO2,
+               .subvendor = PCI_ANY_ID,
+               .subdevice = PCI_ANY_ID,
+       }, {
+               /* empty */
+       },
+};
+
+MODULE_DEVICE_TABLE(pci, pluto2_id_table);
+
+static struct pci_driver pluto2_driver = {
+       .name = DRIVER_NAME,
+       .id_table = pluto2_id_table,
+       .probe = pluto2_probe,
+       .remove = __devexit_p(pluto2_remove),
+};
+
+static int __init pluto2_init(void)
+{
+       return pci_register_driver(&pluto2_driver);
+}
+
+static void __exit pluto2_exit(void)
+{
+       pci_unregister_driver(&pluto2_driver);
+}
+
+module_init(pluto2_init);
+module_exit(pluto2_exit);
+
+MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
+MODULE_DESCRIPTION("Pluto2 driver");
+MODULE_LICENSE("GPL");
index 7ffa2c7315b385e61ca10d823f000f3450c5b350..bf3c011d2cfb3cbc77852c36712d665fe5e25e6f 100644 (file)
@@ -12,7 +12,7 @@ config DVB_AV7110
        select DVB_STV0297
        select DVB_L64781
        help
-         Support for SAA7146 and AV7110 based DVB cards as produced 
+         Support for SAA7146 and AV7110 based DVB cards as produced
          by Fujitsu-Siemens, Technotrend, Hauppauge and others.
 
          This driver only supports the fullfeatured cards with
@@ -33,7 +33,7 @@ config DVB_AV7110_FIRMWARE
          If you want to compile the firmware into the driver you need to say
          Y here and provide the correct path of the firmware. You need this
          option if you want to compile the whole driver statically into the
-         kernel. 
+         kernel.
 
          All other people say N.
 
@@ -66,6 +66,7 @@ config DVB_BUDGET
        select DVB_L64781
        select DVB_TDA8083
        select DVB_TDA10021
+       select DVB_S5H1420
        help
          Support for simple SAA7146 based DVB cards
          (so called Budget- or Nova-PCI cards) without onboard
@@ -119,9 +120,9 @@ config DVB_BUDGET_PATCH
        select DVB_VES1X93
        select DVB_TDA8083
        help
-         Support for Budget Patch (full TS) modification on 
+         Support for Budget Patch (full TS) modification on
          SAA7146+AV7110 based cards (DVB-S cards). This
-         driver doesn't use onboard MPEG2 decoder. The 
+         driver doesn't use onboard MPEG2 decoder. The
          card is driven in Budget-only mode. Card is
          required to have loaded firmware to tune properly.
          Firmware can be loaded by insertion and removal of
index 8e33a850e13ebf4696689664cce737843f3b1239..e4c6e87f6c5d6228ea8f1594bc94d76391f3dfc7 100644 (file)
@@ -116,13 +116,18 @@ static int av7110_num = 0;
 
 static void init_av7110_av(struct av7110 *av7110)
 {
+       int ret;
        struct saa7146_dev *dev = av7110->dev;
 
        /* set internal volume control to maximum */
        av7110->adac_type = DVB_ADAC_TI;
-       av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
+       ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
+       if (ret < 0)
+               printk("dvb-ttpci:cannot set internal volume to maximum:%d\n",ret);
 
-       av7710_set_video_mode(av7110, vidmode);
+       ret = av7710_set_video_mode(av7110, vidmode);
+       if (ret < 0)
+               printk("dvb-ttpci:cannot set video mode:%d\n",ret);
 
        /* handle different card types */
        /* remaining inits according to card and frontend type */
@@ -156,8 +161,12 @@ static void init_av7110_av(struct av7110 *av7110)
 
        if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP) {
                // switch DVB SCART on
-               av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
-               av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1);
+               ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
+               if (ret < 0)
+                       printk("dvb-ttpci:cannot switch on SCART(Main):%d\n",ret);
+               ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1);
+               if (ret < 0)
+                       printk("dvb-ttpci:cannot switch on SCART(AD):%d\n",ret);
                if (rgb_on &&
                    (av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) {
                        saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
@@ -165,8 +174,12 @@ static void init_av7110_av(struct av7110 *av7110)
                }
        }
 
-       av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
-       av7110_setup_irc_config(av7110, 0);
+       ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
+       if (ret < 0)
+               printk("dvb-ttpci:cannot set volume :%d\n",ret);
+       ret = av7110_setup_irc_config(av7110, 0);
+       if (ret < 0)
+               printk("dvb-ttpci:cannot setup irc config :%d\n",ret);
 }
 
 static void recover_arm(struct av7110 *av7110)
@@ -258,8 +271,9 @@ static int arm_thread(void *data)
  *
  *  If we want to support multiple controls we would have to do much more...
  */
-void av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config)
+int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config)
 {
+       int ret = 0;
        static struct av7110 *last;
 
        dprintk(4, "%p\n", av7110);
@@ -270,9 +284,10 @@ void av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config)
                last = av7110;
 
        if (av7110) {
-               av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config);
+               ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config);
                av7110->ir_config = ir_config;
        }
+       return ret;
 }
 
 static void (*irc_handler)(u32);
@@ -765,13 +780,14 @@ static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
                             pcrpid, vpid, apid, ttpid, subpid);
 }
 
-void ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
+int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
                u16 subpid, u16 pcrpid)
 {
+       int ret = 0;
        dprintk(4, "%p\n", av7110);
 
        if (down_interruptible(&av7110->pid_mutex))
-               return;
+               return -ERESTARTSYS;
 
        if (!(vpid & 0x8000))
                av7110->pids[DMX_PES_VIDEO] = vpid;
@@ -786,10 +802,11 @@ void ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
 
        if (av7110->fe_synced) {
                pcrpid = av7110->pids[DMX_PES_PCR];
-               SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
+               ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
        }
 
        up(&av7110->pid_mutex);
+       return ret;
 }
 
 
@@ -832,11 +849,13 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
        ret = av7110_fw_request(av7110, buf, 20, &handle, 1);
        if (ret != 0 || handle >= 32) {
                printk("dvb-ttpci: %s error  buf %04x %04x %04x %04x  "
-                               "ret %x  handle %04x\n",
+                               "ret %d  handle %04x\n",
                                __FUNCTION__, buf[0], buf[1], buf[2], buf[3],
                                ret, handle);
                dvbdmxfilter->hw_handle = 0xffff;
-               return -1;
+               if (!ret)
+                       ret = -1;
+               return ret;
        }
 
        av7110->handle2filter[handle] = dvbdmxfilter;
@@ -859,7 +878,7 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
        if (handle >= 32) {
                printk("%s tried to stop invalid filter %04x, filter type = %x\n",
                                __FUNCTION__, handle, dvbdmxfilter->type);
-               return 0;
+               return -EINVAL;
        }
 
        av7110->handle2filter[handle] = NULL;
@@ -873,18 +892,20 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
                                "resp %04x %04x  pid %d\n",
                                __FUNCTION__, buf[0], buf[1], buf[2], ret,
                                answ[0], answ[1], dvbdmxfilter->feed->pid);
-               ret = -1;
+               if (!ret)
+                       ret = -1;
        }
        return ret;
 }
 
 
-static void dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
+static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
 {
        struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
        struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv;
        u16 *pid = dvbdmx->pids, npids[5];
        int i;
+       int ret = 0;
 
        dprintk(4, "%p\n", av7110);
 
@@ -893,36 +914,49 @@ static void dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
        npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
        if ((i == 2) && npids[i] && (dvbdmxfeed->ts_type & TS_PACKET)) {
                npids[i] = 0;
-               ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
-               StartHWFilter(dvbdmxfeed->filter);
-               return;
+               ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
+               if (!ret)
+                       ret = StartHWFilter(dvbdmxfeed->filter);
+               return ret;
+       }
+       if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4) {
+               ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
+               if (ret)
+                       return ret;
        }
-       if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4)
-               ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
 
        if (dvbdmxfeed->pes_type < 2 && npids[0])
                if (av7110->fe_synced)
-                       av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
+               {
+                       ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
+                       if (ret)
+                               return ret;
+               }
 
        if ((dvbdmxfeed->ts_type & TS_PACKET)) {
                if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
-                       av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
+                       ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
                if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
-                       av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed);
+                       ret = av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed);
        }
+       return ret;
 }
 
-static void dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
+static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
 {
        struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
        struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv;
        u16 *pid = dvbdmx->pids, npids[5];
        int i;
 
+       int ret = 0;
+
        dprintk(4, "%p\n", av7110);
 
        if (dvbdmxfeed->pes_type <= 1) {
-               av7110_av_stop(av7110, dvbdmxfeed->pes_type ?  RP_VIDEO : RP_AUDIO);
+               ret = av7110_av_stop(av7110, dvbdmxfeed->pes_type ?  RP_VIDEO : RP_AUDIO);
+               if (ret)
+                       return ret;
                if (!av7110->rec_mode)
                        dvbdmx->recording = 0;
                if (!av7110->playing)
@@ -933,24 +967,27 @@ static void dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
        switch (i) {
        case 2: //teletext
                if (dvbdmxfeed->ts_type & TS_PACKET)
-                       StopHWFilter(dvbdmxfeed->filter);
+                       ret = StopHWFilter(dvbdmxfeed->filter);
                npids[2] = 0;
                break;
        case 0:
        case 1:
        case 4:
                if (!pids_off)
-                       return;
+                       return 0;
                npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
                break;
        }
-       ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
+       if (!ret)
+               ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
+       return ret;
 }
 
 static int av7110_start_feed(struct dvb_demux_feed *feed)
 {
        struct dvb_demux *demux = feed->demux;
        struct av7110 *av7110 = demux->priv;
+       int ret = 0;
 
        dprintk(4, "%p\n", av7110);
 
@@ -971,21 +1008,22 @@ static int av7110_start_feed(struct dvb_demux_feed *feed)
                                           !(demux->pids[1] & 0x8000)) {
                                               dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
                                               dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
-                                              av7110_av_start_play(av7110,RP_AV);
-                                              demux->playing = 1;
+                                              ret = av7110_av_start_play(av7110,RP_AV);
+                                              if (!ret)
+                                                      demux->playing = 1;
                                        }
                                break;
                        default:
-                               dvb_feed_start_pid(feed);
+                               ret = dvb_feed_start_pid(feed);
                                break;
                        }
                } else if ((feed->ts_type & TS_PACKET) &&
                           (demux->dmx.frontend->source != DMX_MEMORY_FE)) {
-                       StartHWFilter(feed->filter);
+                       ret = StartHWFilter(feed->filter);
                }
        }
 
-       if (feed->type == DMX_TYPE_SEC) {
+       else if (feed->type == DMX_TYPE_SEC) {
                int i;
 
                for (i = 0; i < demux->filternum; i++) {
@@ -996,12 +1034,15 @@ static int av7110_start_feed(struct dvb_demux_feed *feed)
                        if (demux->filter[i].filter.parent != &feed->feed.sec)
                                continue;
                        demux->filter[i].state = DMX_STATE_GO;
-                       if (demux->dmx.frontend->source != DMX_MEMORY_FE)
-                               StartHWFilter(&demux->filter[i]);
+                       if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
+                               ret = StartHWFilter(&demux->filter[i]);
+                               if (ret)
+                                       break;
+                       }
                }
        }
 
-       return 0;
+       return ret;
 }
 
 
@@ -1009,7 +1050,7 @@ static int av7110_stop_feed(struct dvb_demux_feed *feed)
 {
        struct dvb_demux *demux = feed->demux;
        struct av7110 *av7110 = demux->priv;
-
+       int i, rc, ret = 0;
        dprintk(4, "%p\n", av7110);
 
        if (feed->type == DMX_TYPE_TS) {
@@ -1022,26 +1063,29 @@ static int av7110_stop_feed(struct dvb_demux_feed *feed)
                }
                if (feed->ts_type & TS_DECODER &&
                    feed->pes_type < DMX_TS_PES_OTHER) {
-                       dvb_feed_stop_pid(feed);
+                       ret = dvb_feed_stop_pid(feed);
                } else
                        if ((feed->ts_type & TS_PACKET) &&
                            (demux->dmx.frontend->source != DMX_MEMORY_FE))
-                               StopHWFilter(feed->filter);
+                               ret = StopHWFilter(feed->filter);
        }
 
-       if (feed->type == DMX_TYPE_SEC) {
-               int i;
-
-               for (i = 0; i<demux->filternum; i++)
+       if (!ret && feed->type == DMX_TYPE_SEC) {
+               for (i = 0; i<demux->filternum; i++) {
                        if (demux->filter[i].state == DMX_STATE_GO &&
                            demux->filter[i].filter.parent == &feed->feed.sec) {
                                demux->filter[i].state = DMX_STATE_READY;
-                               if (demux->dmx.frontend->source != DMX_MEMORY_FE)
-                                       StopHWFilter(&demux->filter[i]);
+                               if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
+                                       rc = StopHWFilter(&demux->filter[i]);
+                                       if (!ret)
+                                               ret = rc;
+                                       /* keep going, stop as many filters as possible */
+                               }
+                       }
                }
        }
 
-       return 0;
+       return ret;
 }
 
 
@@ -1093,7 +1137,7 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
        ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
        if (ret) {
                printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__);
-               return -EIO;
+               return ret;
        }
        dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
                fwstc[0], fwstc[1], fwstc[2], fwstc[3]);
@@ -1119,18 +1163,14 @@ static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 
        switch (tone) {
        case SEC_TONE_ON:
-               Set22K(av7110, 1);
-               break;
+               return Set22K(av7110, 1);
 
        case SEC_TONE_OFF:
-               Set22K(av7110, 0);
-               break;
+               return Set22K(av7110, 0);
 
        default:
                return -EINVAL;
        }
-
-       return 0;
 }
 
 static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe,
@@ -1138,9 +1178,7 @@ static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe,
 {
        struct av7110* av7110 = fe->dvb->priv;
 
-       av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
-
-       return 0;
+       return av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
 }
 
 static int av7110_diseqc_send_burst(struct dvb_frontend* fe,
@@ -1148,9 +1186,7 @@ static int av7110_diseqc_send_burst(struct dvb_frontend* fe,
 {
        struct av7110* av7110 = fe->dvb->priv;
 
-       av7110_diseqc_send(av7110, 0, NULL, minicmd);
-
-       return 0;
+       return av7110_diseqc_send(av7110, 0, NULL, minicmd);
 }
 
 /* simplified code from budget-core.c */
@@ -1992,76 +2028,85 @@ static struct l64781_config grundig_29504_401_config = {
 
 
 
-static void av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
+static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
 {
+       int ret = 0;
        int synced = (status & FE_HAS_LOCK) ? 1 : 0;
 
        av7110->fe_status = status;
 
        if (av7110->fe_synced == synced)
-               return;
-
-       av7110->fe_synced = synced;
+               return 0;
 
        if (av7110->playing)
-               return;
+               return 0;
 
        if (down_interruptible(&av7110->pid_mutex))
-               return;
+               return -ERESTARTSYS;
 
-       if (av7110->fe_synced) {
-               SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
+       if (synced) {
+               ret = SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
                        av7110->pids[DMX_PES_AUDIO],
                        av7110->pids[DMX_PES_TELETEXT], 0,
                        av7110->pids[DMX_PES_PCR]);
-               av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
+               if (!ret)
+                       ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
        } else {
-               SetPIDs(av7110, 0, 0, 0, 0, 0);
-               av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
-               av7110_wait_msgstate(av7110, GPMQBusy);
+               ret = SetPIDs(av7110, 0, 0, 0, 0, 0);
+               if (!ret) {
+                       ret = av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
+                       if (!ret)
+                               ret = av7110_wait_msgstate(av7110, GPMQBusy);
+               }
        }
 
+       if (!ret)
+               av7110->fe_synced = synced;
+
        up(&av7110->pid_mutex);
+       return ret;
 }
 
 static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct av7110* av7110 = fe->dvb->priv;
-       av7110_fe_lock_fix(av7110, 0);
-       return av7110->fe_set_frontend(fe, params);
+
+       int ret = av7110_fe_lock_fix(av7110, 0);
+       if (!ret)
+               ret = av7110->fe_set_frontend(fe, params);
+       return ret;
 }
 
 static int av7110_fe_init(struct dvb_frontend* fe)
 {
        struct av7110* av7110 = fe->dvb->priv;
 
-       av7110_fe_lock_fix(av7110, 0);
-       return av7110->fe_init(fe);
+       int ret = av7110_fe_lock_fix(av7110, 0);
+       if (!ret)
+               ret = av7110->fe_init(fe);
+       return ret;
 }
 
 static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
        struct av7110* av7110 = fe->dvb->priv;
-       int ret;
 
        /* call the real implementation */
-       ret = av7110->fe_read_status(fe, status);
-       if (ret)
-               return ret;
-
-       if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK)) {
-               av7110_fe_lock_fix(av7110, *status);
-       }
-
-       return 0;
+       int ret = av7110->fe_read_status(fe, status);
+       if (!ret)
+               if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK))
+                       ret = av7110_fe_lock_fix(av7110, *status);
+       return ret;
 }
 
 static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe)
 {
        struct av7110* av7110 = fe->dvb->priv;
 
-       av7110_fe_lock_fix(av7110, 0);
-       return av7110->fe_diseqc_reset_overload(fe);
+       int ret = av7110_fe_lock_fix(av7110, 0);
+       if (!ret)
+               ret = av7110->fe_diseqc_reset_overload(fe);
+       return ret;
 }
 
 static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
@@ -2069,40 +2114,50 @@ static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
 {
        struct av7110* av7110 = fe->dvb->priv;
 
-       av7110_fe_lock_fix(av7110, 0);
-       return av7110->fe_diseqc_send_master_cmd(fe, cmd);
+       int ret = av7110_fe_lock_fix(av7110, 0);
+       if (!ret)
+               ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
+       return ret;
 }
 
 static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
 {
        struct av7110* av7110 = fe->dvb->priv;
 
-       av7110_fe_lock_fix(av7110, 0);
-       return av7110->fe_diseqc_send_burst(fe, minicmd);
+       int ret = av7110_fe_lock_fix(av7110, 0);
+       if (!ret)
+               ret = av7110->fe_diseqc_send_burst(fe, minicmd);
+       return ret;
 }
 
 static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 {
        struct av7110* av7110 = fe->dvb->priv;
 
-       av7110_fe_lock_fix(av7110, 0);
-       return av7110->fe_set_tone(fe, tone);
+       int ret = av7110_fe_lock_fix(av7110, 0);
+       if (!ret)
+               ret = av7110->fe_set_tone(fe, tone);
+       return ret;
 }
 
 static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
 {
        struct av7110* av7110 = fe->dvb->priv;
 
-       av7110_fe_lock_fix(av7110, 0);
-       return av7110->fe_set_voltage(fe, voltage);
+       int ret = av7110_fe_lock_fix(av7110, 0);
+       if (!ret)
+               ret = av7110->fe_set_voltage(fe, voltage);
+       return ret;
 }
 
 static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned int cmd)
 {
        struct av7110* av7110 = fe->dvb->priv;
 
-       av7110_fe_lock_fix(av7110, 0);
-       return av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
+       int ret = av7110_fe_lock_fix(av7110, 0);
+       if (!ret)
+               ret = av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
+       return ret;
 }
 
 static u8 read_pwm(struct av7110* av7110)
index 4f69b4d01479232c6a3eb7e4460aab3290ffd158..508b7739c6096db2c6d647b86a627a5f23117e4d 100644 (file)
@@ -119,8 +119,7 @@ struct av7110 {
        volatile int            bmp_state;
 #define BMP_NONE     0
 #define BMP_LOADING  1
-#define BMP_LOADINGS 2
-#define BMP_LOADED   3
+#define BMP_LOADED   2
        wait_queue_head_t       bmpq;
 
 
@@ -255,12 +254,12 @@ struct av7110 {
 };
 
 
-extern void ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
+extern int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
                       u16 subpid, u16 pcrpid);
 
 extern void av7110_register_irc_handler(void (*func)(u32));
 extern void av7110_unregister_irc_handler(void (*func)(u32));
-extern void av7110_setup_irc_config (struct av7110 *av7110, u32 ir_config);
+extern int av7110_setup_irc_config (struct av7110 *av7110, u32 ir_config);
 
 extern int av7110_ir_init (void);
 extern void av7110_ir_exit (void);
index ccf946125d028fb2f22273143d4e62bdfd35fbb9..0696a5a4f85594c963758fdc53b9b2932a320fe4 100644 (file)
@@ -121,6 +121,7 @@ static int dvb_filter_pes2ts_cb(void *priv, unsigned char *data)
 int av7110_av_start_record(struct av7110 *av7110, int av,
                           struct dvb_demux_feed *dvbdmxfeed)
 {
+       int ret = 0;
        struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 
        dprintk(2, "av7110:%p, , dvb_demux_feed:%p\n", av7110, dvbdmxfeed);
@@ -137,7 +138,7 @@ int av7110_av_start_record(struct av7110 *av7110, int av,
                                       dvbdmx->pesfilter[0]->pid,
                                       dvb_filter_pes2ts_cb,
                                       (void *) dvbdmx->pesfilter[0]);
-               av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0);
+               ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0);
                break;
 
        case RP_VIDEO:
@@ -145,7 +146,7 @@ int av7110_av_start_record(struct av7110 *av7110, int av,
                                       dvbdmx->pesfilter[1]->pid,
                                       dvb_filter_pes2ts_cb,
                                       (void *) dvbdmx->pesfilter[1]);
-               av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0);
+               ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0);
                break;
 
        case RP_AV:
@@ -157,14 +158,15 @@ int av7110_av_start_record(struct av7110 *av7110, int av,
                                       dvbdmx->pesfilter[1]->pid,
                                       dvb_filter_pes2ts_cb,
                                       (void *) dvbdmx->pesfilter[1]);
-               av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AV_PES, 0);
+               ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AV_PES, 0);
                break;
        }
-       return 0;
+       return ret;
 }
 
 int av7110_av_start_play(struct av7110 *av7110, int av)
 {
+       int ret = 0;
        dprintk(2, "av7110:%p, \n", av7110);
 
        if (av7110->rec_mode)
@@ -182,54 +184,57 @@ int av7110_av_start_play(struct av7110 *av7110, int av)
        av7110->playing |= av;
        switch (av7110->playing) {
        case RP_AUDIO:
-               av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AudioPES, 0);
+               ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AudioPES, 0);
                break;
        case RP_VIDEO:
-               av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, VideoPES, 0);
+               ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, VideoPES, 0);
                av7110->sinfo = 0;
                break;
        case RP_AV:
                av7110->sinfo = 0;
-               av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AV_PES, 0);
+               ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AV_PES, 0);
                break;
        }
-       return av7110->playing;
+       if (!ret)
+               ret = av7110->playing;
+       return ret;
 }
 
-void av7110_av_stop(struct av7110 *av7110, int av)
+int av7110_av_stop(struct av7110 *av7110, int av)
 {
+       int ret = 0;
        dprintk(2, "av7110:%p, \n", av7110);
 
        if (!(av7110->playing & av) && !(av7110->rec_mode & av))
-               return;
-
+               return 0;
        av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
        if (av7110->playing) {
                av7110->playing &= ~av;
                switch (av7110->playing) {
                case RP_AUDIO:
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AudioPES, 0);
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AudioPES, 0);
                        break;
                case RP_VIDEO:
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, VideoPES, 0);
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, VideoPES, 0);
                        break;
                case RP_NONE:
-                       av7110_set_vidmode(av7110, av7110->vidmode);
+                       ret = av7110_set_vidmode(av7110, av7110->vidmode);
                        break;
                }
        } else {
                av7110->rec_mode &= ~av;
                switch (av7110->rec_mode) {
                case RP_AUDIO:
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0);
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0);
                        break;
                case RP_VIDEO:
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0);
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0);
                        break;
                case RP_NONE:
                        break;
                }
        }
+       return ret;
 }
 
 
@@ -317,19 +322,22 @@ int av7110_set_volume(struct av7110 *av7110, int volleft, int volright)
        return 0;
 }
 
-void av7110_set_vidmode(struct av7110 *av7110, int mode)
+int av7110_set_vidmode(struct av7110 *av7110, int mode)
 {
+       int ret;
        dprintk(2, "av7110:%p, \n", av7110);
 
-       av7110_fw_cmd(av7110, COMTYPE_ENCODER, LoadVidCode, 1, mode);
+       ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, LoadVidCode, 1, mode);
 
-       if (!av7110->playing) {
-               ChangePIDs(av7110, av7110->pids[DMX_PES_VIDEO],
+       if (!ret && !av7110->playing) {
+               ret = ChangePIDs(av7110, av7110->pids[DMX_PES_VIDEO],
                           av7110->pids[DMX_PES_AUDIO],
                           av7110->pids[DMX_PES_TELETEXT],
                           0, av7110->pids[DMX_PES_PCR]);
-               av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
+               if (!ret)
+                       ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
        }
+       return ret;
 }
 
 
@@ -340,17 +348,18 @@ static int sw2mode[16] = {
        VIDEO_MODE_PAL, VIDEO_MODE_PAL, VIDEO_MODE_PAL, VIDEO_MODE_PAL,
 };
 
-static void get_video_format(struct av7110 *av7110, u8 *buf, int count)
+static int get_video_format(struct av7110 *av7110, u8 *buf, int count)
 {
        int i;
        int hsize, vsize;
        int sw;
        u8 *p;
+       int ret = 0;
 
        dprintk(2, "av7110:%p, \n", av7110);
 
        if (av7110->sinfo)
-               return;
+               return 0;
        for (i = 7; i < count - 10; i++) {
                p = buf + i;
                if (p[0] || p[1] || p[2] != 0x01 || p[3] != 0xb3)
@@ -359,11 +368,14 @@ static void get_video_format(struct av7110 *av7110, u8 *buf, int count)
                hsize = ((p[1] &0xF0) >> 4) | (p[0] << 4);
                vsize = ((p[1] &0x0F) << 8) | (p[2]);
                sw = (p[3] & 0x0F);
-               av7110_set_vidmode(av7110, sw2mode[sw]);
-               dprintk(2, "playback %dx%d fr=%d\n", hsize, vsize, sw);
-               av7110->sinfo = 1;
+               ret = av7110_set_vidmode(av7110, sw2mode[sw]);
+               if (!ret) {
+                       dprintk(2, "playback %dx%d fr=%d\n", hsize, vsize, sw);
+                       av7110->sinfo = 1;
+               }
                break;
        }
+       return ret;
 }
 
 
@@ -974,7 +986,7 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file,
        unsigned long arg = (unsigned long) parg;
        int ret = 0;
 
-       dprintk(2, "av7110:%p, \n", av7110);
+       dprintk(1, "av7110:%p, cmd=%04x\n", av7110,cmd);
 
        if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
                if ( cmd != VIDEO_GET_STATUS && cmd != VIDEO_GET_EVENT &&
@@ -987,49 +999,57 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file,
        case VIDEO_STOP:
                av7110->videostate.play_state = VIDEO_STOPPED;
                if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY)
-                       av7110_av_stop(av7110, RP_VIDEO);
+                       ret = av7110_av_stop(av7110, RP_VIDEO);
                else
-                       vidcom(av7110, VIDEO_CMD_STOP,
+                       ret = vidcom(av7110, VIDEO_CMD_STOP,
                               av7110->videostate.video_blank ? 0 : 1);
-               av7110->trickmode = TRICK_NONE;
+               if (!ret)
+                       av7110->trickmode = TRICK_NONE;
                break;
 
        case VIDEO_PLAY:
                av7110->trickmode = TRICK_NONE;
                if (av7110->videostate.play_state == VIDEO_FREEZED) {
                        av7110->videostate.play_state = VIDEO_PLAYING;
-                       vidcom(av7110, VIDEO_CMD_PLAY, 0);
+                       ret = vidcom(av7110, VIDEO_CMD_PLAY, 0);
+                       if (ret)
+                               break;
                }
 
                if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY) {
                        if (av7110->playing == RP_AV) {
-                               av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
+                               ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
+                               if (ret)
+                                       break;
                                av7110->playing &= ~RP_VIDEO;
                        }
-                       av7110_av_start_play(av7110, RP_VIDEO);
-                       vidcom(av7110, VIDEO_CMD_PLAY, 0);
-               } else {
-                       //av7110_av_stop(av7110, RP_VIDEO);
-                       vidcom(av7110, VIDEO_CMD_PLAY, 0);
+                       ret = av7110_av_start_play(av7110, RP_VIDEO);
                }
-               av7110->videostate.play_state = VIDEO_PLAYING;
+               if (!ret)
+                       ret = vidcom(av7110, VIDEO_CMD_PLAY, 0);
+               if (!ret)
+                       av7110->videostate.play_state = VIDEO_PLAYING;
                break;
 
        case VIDEO_FREEZE:
                av7110->videostate.play_state = VIDEO_FREEZED;
                if (av7110->playing & RP_VIDEO)
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Pause, 0);
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Pause, 0);
                else
-                       vidcom(av7110, VIDEO_CMD_FREEZE, 1);
-               av7110->trickmode = TRICK_FREEZE;
+                       ret = vidcom(av7110, VIDEO_CMD_FREEZE, 1);
+               if (!ret)
+                       av7110->trickmode = TRICK_FREEZE;
                break;
 
        case VIDEO_CONTINUE:
                if (av7110->playing & RP_VIDEO)
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Continue, 0);
-               vidcom(av7110, VIDEO_CMD_PLAY, 0);
-               av7110->videostate.play_state = VIDEO_PLAYING;
-               av7110->trickmode = TRICK_NONE;
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Continue, 0);
+               if (!ret)
+                       ret = vidcom(av7110, VIDEO_CMD_PLAY, 0);
+               if (!ret) {
+                       av7110->videostate.play_state = VIDEO_PLAYING;
+                       av7110->trickmode = TRICK_NONE;
+               }
                break;
 
        case VIDEO_SELECT_SOURCE:
@@ -1045,7 +1065,7 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file,
                break;
 
        case VIDEO_GET_EVENT:
-               ret=dvb_video_get_event(av7110, parg, file->f_flags);
+               ret = dvb_video_get_event(av7110, parg, file->f_flags);
                break;
 
        case VIDEO_GET_SIZE:
@@ -1105,25 +1125,32 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file,
        case VIDEO_FAST_FORWARD:
                //note: arg is ignored by firmware
                if (av7110->playing & RP_VIDEO)
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
-                                     __Scan_I, 2, AV_PES, 0);
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
+                                           __Scan_I, 2, AV_PES, 0);
                else
-                       vidcom(av7110, VIDEO_CMD_FFWD, arg);
-               av7110->trickmode = TRICK_FAST;
-               av7110->videostate.play_state = VIDEO_PLAYING;
+                       ret = vidcom(av7110, VIDEO_CMD_FFWD, arg);
+               if (!ret) {
+                       av7110->trickmode = TRICK_FAST;
+                       av7110->videostate.play_state = VIDEO_PLAYING;
+               }
                break;
 
        case VIDEO_SLOWMOTION:
                if (av7110->playing&RP_VIDEO) {
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Slow, 2, 0, 0);
-                       vidcom(av7110, VIDEO_CMD_SLOW, arg);
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Slow, 2, 0, 0);
+                       if (!ret)
+                               ret = vidcom(av7110, VIDEO_CMD_SLOW, arg);
                } else {
-                       vidcom(av7110, VIDEO_CMD_PLAY, 0);
-                       vidcom(av7110, VIDEO_CMD_STOP, 0);
-                       vidcom(av7110, VIDEO_CMD_SLOW, arg);
+                       ret = vidcom(av7110, VIDEO_CMD_PLAY, 0);
+                       if (!ret)
+                               ret = vidcom(av7110, VIDEO_CMD_STOP, 0);
+                       if (!ret)
+                               ret = vidcom(av7110, VIDEO_CMD_SLOW, arg);
+               }
+               if (!ret) {
+                       av7110->trickmode = TRICK_SLOW;
+                       av7110->videostate.play_state = VIDEO_PLAYING;
                }
-               av7110->trickmode = TRICK_SLOW;
-               av7110->videostate.play_state = VIDEO_PLAYING;
                break;
 
        case VIDEO_GET_CAPABILITIES:
@@ -1136,18 +1163,21 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file,
                av7110_ipack_reset(&av7110->ipack[1]);
 
                if (av7110->playing == RP_AV) {
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
-                                     __Play, 2, AV_PES, 0);
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
+                                           __Play, 2, AV_PES, 0);
+                       if (ret)
+                               break;
                        if (av7110->trickmode == TRICK_FAST)
-                               av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
-                                             __Scan_I, 2, AV_PES, 0);
+                               ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
+                                                   __Scan_I, 2, AV_PES, 0);
                        if (av7110->trickmode == TRICK_SLOW) {
-                               av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
-                                             __Slow, 2, 0, 0);
-                               vidcom(av7110, VIDEO_CMD_SLOW, arg);
+                               ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
+                                                   __Slow, 2, 0, 0);
+                               if (!ret)
+                                       ret = vidcom(av7110, VIDEO_CMD_SLOW, arg);
                        }
                        if (av7110->trickmode == TRICK_FREEZE)
-                               vidcom(av7110, VIDEO_CMD_STOP, 1);
+                               ret = vidcom(av7110, VIDEO_CMD_STOP, 1);
                }
                break;
 
@@ -1170,7 +1200,7 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
        unsigned long arg = (unsigned long) parg;
        int ret = 0;
 
-       dprintk(2, "av7110:%p, \n", av7110);
+       dprintk(1, "av7110:%p, cmd=%04x\n", av7110,cmd);
 
        if (((file->f_flags & O_ACCMODE) == O_RDONLY) &&
            (cmd != AUDIO_GET_STATUS))
@@ -1179,28 +1209,32 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
        switch (cmd) {
        case AUDIO_STOP:
                if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY)
-                       av7110_av_stop(av7110, RP_AUDIO);
+                       ret = av7110_av_stop(av7110, RP_AUDIO);
                else
-                       audcom(av7110, AUDIO_CMD_MUTE);
-               av7110->audiostate.play_state = AUDIO_STOPPED;
+                       ret = audcom(av7110, AUDIO_CMD_MUTE);
+               if (!ret)
+                       av7110->audiostate.play_state = AUDIO_STOPPED;
                break;
 
        case AUDIO_PLAY:
                if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY)
-                       av7110_av_start_play(av7110, RP_AUDIO);
-               audcom(av7110, AUDIO_CMD_UNMUTE);
-               av7110->audiostate.play_state = AUDIO_PLAYING;
+                       ret = av7110_av_start_play(av7110, RP_AUDIO);
+               if (!ret)
+                       ret = audcom(av7110, AUDIO_CMD_UNMUTE);
+               if (!ret)
+                       av7110->audiostate.play_state = AUDIO_PLAYING;
                break;
 
        case AUDIO_PAUSE:
-               audcom(av7110, AUDIO_CMD_MUTE);
-               av7110->audiostate.play_state = AUDIO_PAUSED;
+               ret = audcom(av7110, AUDIO_CMD_MUTE);
+               if (!ret)
+                       av7110->audiostate.play_state = AUDIO_PAUSED;
                break;
 
        case AUDIO_CONTINUE:
                if (av7110->audiostate.play_state == AUDIO_PAUSED) {
                        av7110->audiostate.play_state = AUDIO_PLAYING;
-                       audcom(av7110, AUDIO_CMD_MUTE | AUDIO_CMD_PCM16);
+                       ret = audcom(av7110, AUDIO_CMD_UNMUTE | AUDIO_CMD_PCM16);
                }
                break;
 
@@ -1210,14 +1244,15 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
 
        case AUDIO_SET_MUTE:
        {
-               audcom(av7110, arg ? AUDIO_CMD_MUTE : AUDIO_CMD_UNMUTE);
-               av7110->audiostate.mute_state = (int) arg;
+               ret = audcom(av7110, arg ? AUDIO_CMD_MUTE : AUDIO_CMD_UNMUTE);
+               if (!ret)
+                       av7110->audiostate.mute_state = (int) arg;
                break;
        }
 
        case AUDIO_SET_AV_SYNC:
                av7110->audiostate.AV_sync_state = (int) arg;
-               audcom(av7110, arg ? AUDIO_CMD_SYNC_ON : AUDIO_CMD_SYNC_OFF);
+               ret = audcom(av7110, arg ? AUDIO_CMD_SYNC_ON : AUDIO_CMD_SYNC_OFF);
                break;
 
        case AUDIO_SET_BYPASS_MODE:
@@ -1229,21 +1264,24 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
 
                switch(av7110->audiostate.channel_select) {
                case AUDIO_STEREO:
-                       audcom(av7110, AUDIO_CMD_STEREO);
-                       if (av7110->adac_type == DVB_ADAC_CRYSTAL)
-                               i2c_writereg(av7110, 0x20, 0x02, 0x49);
+                       ret = audcom(av7110, AUDIO_CMD_STEREO);
+                       if (!ret)
+                               if (av7110->adac_type == DVB_ADAC_CRYSTAL)
+                                       i2c_writereg(av7110, 0x20, 0x02, 0x49);
                        break;
 
                case AUDIO_MONO_LEFT:
-                       audcom(av7110, AUDIO_CMD_MONO_L);
-                       if (av7110->adac_type == DVB_ADAC_CRYSTAL)
-                               i2c_writereg(av7110, 0x20, 0x02, 0x4a);
+                       ret = audcom(av7110, AUDIO_CMD_MONO_L);
+                       if (!ret)
+                               if (av7110->adac_type == DVB_ADAC_CRYSTAL)
+                                       i2c_writereg(av7110, 0x20, 0x02, 0x4a);
                        break;
 
                case AUDIO_MONO_RIGHT:
-                       audcom(av7110, AUDIO_CMD_MONO_R);
-                       if (av7110->adac_type == DVB_ADAC_CRYSTAL)
-                               i2c_writereg(av7110, 0x20, 0x02, 0x45);
+                       ret = audcom(av7110, AUDIO_CMD_MONO_R);
+                       if (!ret)
+                               if (av7110->adac_type == DVB_ADAC_CRYSTAL)
+                                       i2c_writereg(av7110, 0x20, 0x02, 0x45);
                        break;
 
                default:
@@ -1264,8 +1302,8 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
                dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
                av7110_ipack_reset(&av7110->ipack[0]);
                if (av7110->playing == RP_AV)
-                       av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
-                              __Play, 2, AV_PES, 0);
+                       ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
+                                           __Play, 2, AV_PES, 0);
                break;
        case AUDIO_SET_ID:
 
@@ -1274,7 +1312,7 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
        {
                struct audio_mixer *amix = (struct audio_mixer *)parg;
 
-               av7110_set_volume(av7110, amix->volume_left, amix->volume_right);
+               ret = av7110_set_volume(av7110, amix->volume_left, amix->volume_right);
                break;
        }
        case AUDIO_SET_STREAMTYPE:
index cc5e7a7e87c399e2629b003b011b484947dbb5f8..45dc144b8b435c1425b52b26da8f639e4888fba6 100644 (file)
@@ -3,14 +3,14 @@
 
 struct av7110;
 
-extern void av7110_set_vidmode(struct av7110 *av7110, int mode);
+extern int av7110_set_vidmode(struct av7110 *av7110, int mode);
 
 extern int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len);
 extern int av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen);
 extern int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len);
 
 extern int av7110_set_volume(struct av7110 *av7110, int volleft, int volright);
-extern void av7110_av_stop(struct av7110 *av7110, int av);
+extern int av7110_av_stop(struct av7110 *av7110, int av);
 extern int av7110_av_start_record(struct av7110 *av7110, int av,
                          struct dvb_demux_feed *dvbdmxfeed);
 extern int av7110_av_start_play(struct av7110 *av7110, int av);
index 7fa4a0ebe133db1e2976be272245a4ba1dd61efe..1220826696c5f2ba2a50a69e0b81a183c847f6a3 100644 (file)
@@ -137,7 +137,7 @@ static int waitdebi(struct av7110 *av7110, int adr, int state)
                        return 0;
                udelay(5);
        }
-       return -1;
+       return -ETIMEDOUT;
 }
 
 static int load_dram(struct av7110 *av7110, u32 *data, int len)
@@ -155,7 +155,7 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len)
        for (i = 0; i < blocks; i++) {
                if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
                        printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i);
-                       return -1;
+                       return -ETIMEDOUT;
                }
                dprintk(4, "writing DRAM block %d\n", i);
                mwdebi(av7110, DEBISWAB, bootblock,
@@ -170,7 +170,7 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len)
        if (rest > 0) {
                if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
                        printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n");
-                       return -1;
+                       return -ETIMEDOUT;
                }
                if (rest > 4)
                        mwdebi(av7110, DEBISWAB, bootblock,
@@ -185,13 +185,13 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len)
        }
        if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
                printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n");
-               return -1;
+               return -ETIMEDOUT;
        }
        iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, 0, 2);
        iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
        if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BOOT_COMPLETE) < 0) {
                printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n");
-               return -1;
+               return -ETIMEDOUT;
        }
        return 0;
 }
@@ -263,7 +263,7 @@ int av7110_bootarm(struct av7110 *av7110)
        if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
                printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
                       "saa7146_wait_for_debi_done() timed out\n");
-               return -1;
+               return -ETIMEDOUT;
        }
        saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
        mdelay(1);
@@ -284,7 +284,7 @@ int av7110_bootarm(struct av7110 *av7110)
        if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
                printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
                       "saa7146_wait_for_debi_done() timed out after loading DRAM\n");
-               return -1;
+               return -ETIMEDOUT;
        }
        saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
        msleep(30);     /* the firmware needs some time to initialize */
@@ -308,6 +308,7 @@ int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
 {
        unsigned long start;
        u32 stat;
+       int err;
 
        if (FW_VERSION(av7110->arm_app) <= 0x261c) {
                /* not supported by old firmware */
@@ -318,17 +319,17 @@ int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
        /* new firmware */
        start = jiffies;
        for (;;) {
+               err = time_after(jiffies, start + ARM_WAIT_FREE);
                if (down_interruptible(&av7110->dcomlock))
                        return -ERESTARTSYS;
                stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
                up(&av7110->dcomlock);
-               if ((stat & flags) == 0) {
+               if ((stat & flags) == 0)
                        break;
-               }
-               if (time_after(jiffies, start + ARM_WAIT_FREE)) {
+               if (err) {
                        printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
                                __FUNCTION__, stat & flags);
-                       return -1;
+                       return -ETIMEDOUT;
                }
                msleep(1);
        }
@@ -342,6 +343,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
        char *type = NULL;
        u16 flags[2] = {0, 0};
        u32 stat;
+       int err;
 
 //     dprintk(4, "%p\n", av7110);
 
@@ -351,24 +353,30 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
        }
 
        start = jiffies;
-       while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) {
-               msleep(1);
-               if (time_after(jiffies, start + ARM_WAIT_FREE)) {
+       while (1) {
+               err = time_after(jiffies, start + ARM_WAIT_FREE);
+               if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
+                       break;
+               if (err) {
                        printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
                        return -ETIMEDOUT;
                }
+               msleep(1);
        }
 
        wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
 
 #ifndef _NOHANDSHAKE
        start = jiffies;
-       while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) {
-               msleep(1);
-               if (time_after(jiffies, start + ARM_WAIT_SHAKE)) {
+       while (1) {
+               err = time_after(jiffies, start + ARM_WAIT_SHAKE);
+               if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
+                       break;
+               if (err) {
                        printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
                        return -ETIMEDOUT;
                }
+               msleep(1);
        }
 #endif
 
@@ -401,6 +409,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
                /* non-immediate COMMAND type */
                start = jiffies;
                for (;;) {
+                       err = time_after(jiffies, start + ARM_WAIT_FREE);
                        stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
                        if (stat & flags[0]) {
                                printk(KERN_ERR "%s: %s QUEUE overflow\n",
@@ -409,10 +418,10 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
                        }
                        if ((stat & flags[1]) == 0)
                                break;
-                       if (time_after(jiffies, start + ARM_WAIT_FREE)) {
+                       if (err) {
                                printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
                                        __FUNCTION__, type);
-                               return -1;
+                               return -ETIMEDOUT;
                        }
                        msleep(1);
                }
@@ -432,13 +441,16 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
 
 #ifdef COM_DEBUG
        start = jiffies;
-       while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) {
-               msleep(1);
-               if (time_after(jiffies, start + ARM_WAIT_FREE)) {
-                       printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND to complete\n",
-                              __FUNCTION__);
+       while (1) {
+               err = time_after(jiffies, start + ARM_WAIT_FREE);
+               if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
+                       break;
+               if (err) {
+                       printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
+                              __FUNCTION__, (buf[0] >> 8) & 0xff);
                        return -ETIMEDOUT;
                }
+               msleep(1);
        }
 
        stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
@@ -470,7 +482,7 @@ static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
 
        ret = __av7110_send_fw_cmd(av7110, buf, length);
        up(&av7110->dcomlock);
-       if (ret)
+       if (ret && ret!=-ERESTARTSYS)
                printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
                       __FUNCTION__, ret);
        return ret;
@@ -495,7 +507,7 @@ int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...)
        }
 
        ret = av7110_send_fw_cmd(av7110, buf, num + 2);
-       if (ret)
+       if (ret && ret != -ERESTARTSYS)
                printk(KERN_ERR "dvb-ttpci: av7110_fw_cmd error %d\n", ret);
        return ret;
 }
@@ -518,7 +530,7 @@ int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len)
        }
 
        ret = av7110_send_fw_cmd(av7110, cmd, 18);
-       if (ret)
+       if (ret && ret != -ERESTARTSYS)
                printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret);
        return ret;
 }
@@ -551,26 +563,32 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
        }
 
        start = jiffies;
-       while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2)) {
-#ifdef _NOHANDSHAKE
-               msleep(1);
-#endif
-               if (time_after(jiffies, start + ARM_WAIT_FREE)) {
+       while (1) {
+               err = time_after(jiffies, start + ARM_WAIT_FREE);
+               if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
+                       break;
+               if (err) {
                        printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
                        up(&av7110->dcomlock);
-                       return -1;
+                       return -ETIMEDOUT;
                }
+#ifdef _NOHANDSHAKE
+               msleep(1);
+#endif
        }
 
 #ifndef _NOHANDSHAKE
        start = jiffies;
-       while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) {
-               msleep(1);
-               if (time_after(jiffies, start + ARM_WAIT_SHAKE)) {
+       while (1) {
+               err = time_after(jiffies, start + ARM_WAIT_SHAKE);
+               if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
+                       break;
+               if (err) {
                        printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
                        up(&av7110->dcomlock);
-                       return -1;
+                       return -ETIMEDOUT;
                }
+               msleep(1);
        }
 #endif
 
@@ -667,10 +685,10 @@ int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long bu
        for (i = 0; i < len; i++)
                buf[i + 4] = msg[i];
 
-       if ((ret = av7110_send_fw_cmd(av7110, buf, 18)))
+       ret = av7110_send_fw_cmd(av7110, buf, 18);
+       if (ret && ret!=-ERESTARTSYS)
                printk(KERN_ERR "dvb-ttpci: av7110_diseqc_send error %d\n", ret);
-
-       return 0;
+       return ret;
 }
 
 
@@ -705,18 +723,22 @@ static inline int SetFont(struct av7110 *av7110, u8 windownr, u8 fontsize,
 static int FlushText(struct av7110 *av7110)
 {
        unsigned long start;
+       int err;
 
        if (down_interruptible(&av7110->dcomlock))
                return -ERESTARTSYS;
        start = jiffies;
-       while (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2)) {
-               msleep(1);
-               if (time_after(jiffies, start + ARM_WAIT_OSD)) {
+       while (1) {
+               err = time_after(jiffies, start + ARM_WAIT_OSD);
+               if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
+                       break;
+               if (err) {
                        printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
                               __FUNCTION__);
                        up(&av7110->dcomlock);
-                       return -1;
+                       return -ETIMEDOUT;
                }
+               msleep(1);
        }
        up(&av7110->dcomlock);
        return 0;
@@ -733,25 +755,31 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf)
                return -ERESTARTSYS;
 
        start = jiffies;
-       while (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2)) {
-               msleep(1);
-               if (time_after(jiffies, start + ARM_WAIT_OSD)) {
+       while (1) {
+               ret = time_after(jiffies, start + ARM_WAIT_OSD);
+               if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
+                       break;
+               if (ret) {
                        printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
                               __FUNCTION__);
                        up(&av7110->dcomlock);
-                       return -1;
+                       return -ETIMEDOUT;
                }
+               msleep(1);
        }
 #ifndef _NOHANDSHAKE
        start = jiffies;
-       while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2)) {
-               msleep(1);
-               if (time_after(jiffies, start + ARM_WAIT_SHAKE)) {
+       while (1) {
+               ret = time_after(jiffies, start + ARM_WAIT_SHAKE);
+               if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
+                       break;
+               if (ret) {
                        printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
                               __FUNCTION__);
                        up(&av7110->dcomlock);
-                       return -1;
+                       return -ETIMEDOUT;
                }
+               msleep(1);
        }
 #endif
        for (i = 0; i < length / 2; i++)
@@ -761,7 +789,7 @@ static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf)
                wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2);
        ret = __av7110_send_fw_cmd(av7110, cbuf, 5);
        up(&av7110->dcomlock);
-       if (ret)
+       if (ret && ret!=-ERESTARTSYS)
                printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret);
        return ret;
 }
@@ -816,9 +844,25 @@ static osd_raw_window_t bpp2bit[8] = {
        OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8
 };
 
-static inline int LoadBitmap(struct av7110 *av7110, u16 format,
+static inline int WaitUntilBmpLoaded(struct av7110 *av7110)
+{
+       int ret = wait_event_interruptible_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);
+               av7110->bmp_state = BMP_NONE;
+               return -ETIMEDOUT;
+       }
+       return 0;
+}
+
+static inline int LoadBitmap(struct av7110 *av7110,
                             u16 dx, u16 dy, int inc, u8 __user * data)
 {
+       u16 format;
        int bpp;
        int i;
        int d, delta;
@@ -827,14 +871,7 @@ static inline int LoadBitmap(struct av7110 *av7110, u16 format,
 
        dprintk(4, "%p\n", av7110);
 
-       ret = wait_event_interruptible_timeout(av7110->bmpq, av7110->bmp_state != BMP_LOADING, HZ);
-       if (ret == -ERESTARTSYS || ret == 0) {
-               printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
-                      ret, av7110->bmp_state);
-               av7110->bmp_state = BMP_NONE;
-               return -1;
-       }
-       BUG_ON (av7110->bmp_state == BMP_LOADING);
+       format = bpp2bit[av7110->osdbpp[av7110->osdwin]];
 
        av7110->bmp_state = BMP_LOADING;
        if      (format == OSD_BITMAP8) {
@@ -847,18 +884,18 @@ static inline int LoadBitmap(struct av7110 *av7110, u16 format,
                bpp=1; delta = 8;
        } else {
                av7110->bmp_state = BMP_NONE;
-               return -1;
+               return -EINVAL;
        }
        av7110->bmplen = ((dx * dy * bpp + 7) & ~7) / 8;
        av7110->bmpp = 0;
        if (av7110->bmplen > 32768) {
                av7110->bmp_state = BMP_NONE;
-               return -1;
+               return -EINVAL;
        }
        for (i = 0; i < dy; i++) {
                if (copy_from_user(av7110->bmpbuf + 1024 + i * dx, data + i * inc, dx)) {
                        av7110->bmp_state = BMP_NONE;
-                       return -1;
+                       return -EINVAL;
                }
        }
        if (format != OSD_BITMAP8) {
@@ -873,37 +910,27 @@ static inline int LoadBitmap(struct av7110 *av7110, u16 format,
        }
        av7110->bmplen += 1024;
        dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110->bmplen);
-       return av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
+       ret = av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
+       if (!ret)
+               ret = WaitUntilBmpLoaded(av7110);
+       return ret;
 }
 
-static int BlitBitmap(struct av7110 *av7110, u16 win, u16 x, u16 y, u16 trans)
+static int BlitBitmap(struct av7110 *av7110, u16 x, u16 y)
 {
-       int ret;
-
        dprintk(4, "%p\n", av7110);
 
-       BUG_ON (av7110->bmp_state == BMP_NONE);
-
-       ret = wait_event_interruptible_timeout(av7110->bmpq,
-                               av7110->bmp_state != BMP_LOADING, 10*HZ);
-       if (ret == -ERESTARTSYS || ret == 0) {
-               printk("dvb-ttpci: warning: timeout waiting in BlitBitmap: %d, %d\n",
-                      ret, av7110->bmp_state);
-               av7110->bmp_state = BMP_NONE;
-               return (ret == 0) ? -ETIMEDOUT : ret;
-       }
-
-       BUG_ON (av7110->bmp_state != BMP_LOADED);
-
-       return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, win, x, y, trans);
+       return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, av7110->osdwin, x, y, 0);
 }
 
 static inline int ReleaseBitmap(struct av7110 *av7110)
 {
        dprintk(4, "%p\n", av7110);
 
-       if (av7110->bmp_state != BMP_LOADED)
+       if (av7110->bmp_state != BMP_LOADED && FW_VERSION(av7110->arm_app) < 0x261e)
                return -1;
+       if (av7110->bmp_state == BMP_LOADING)
+               dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
        av7110->bmp_state = BMP_NONE;
        return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0);
 }
@@ -924,18 +951,22 @@ static u32 RGB2YUV(u16 R, u16 G, u16 B)
        return Cr | (Cb << 16) | (Y << 8);
 }
 
-static void OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend)
+static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend)
 {
+       int ret;
+
        u16 ch, cl;
        u32 yuv;
 
        yuv = blend ? RGB2YUV(r,g,b) : 0;
        cl = (yuv & 0xffff);
        ch = ((yuv >> 16) & 0xffff);
-       SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
-                 color, ch, cl);
-       SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
-                 color, ((blend >> 4) & 0x0f));
+       ret = SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
+                       color, ch, cl);
+       if (!ret)
+               ret = SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
+                               color, ((blend >> 4) & 0x0f));
+       return ret;
 }
 
 static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last)
@@ -968,14 +999,14 @@ static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
 {
        uint w, h, bpp, bpl, size, lpb, bnum, brest;
        int i;
-       int rc;
+       int rc,release_rc;
 
        w = x1 - x0 + 1;
        h = y1 - y0 + 1;
        if (inc <= 0)
                inc = w;
        if (w <= 0 || w > 720 || h <= 0 || h > 576)
-               return -1;
+               return -EINVAL;
        bpp = av7110->osdbpp[av7110->osdwin] + 1;
        bpl = ((w * bpp + 7) & ~7) / 8;
        size = h * bpl;
@@ -983,176 +1014,186 @@ static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
        bnum = size / (lpb * bpl);
        brest = size - bnum * lpb * bpl;
 
-       for (i = 0; i < bnum; i++) {
-               rc = LoadBitmap(av7110, bpp2bit[av7110->osdbpp[av7110->osdwin]],
-                          w, lpb, inc, data);
-               if (rc)
-                       return rc;
-               rc = BlitBitmap(av7110, av7110->osdwin, x0, y0 + i * lpb, 0);
+       if (av7110->bmp_state == BMP_LOADING) {
+               /* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
+               BUG_ON (FW_VERSION(av7110->arm_app) >= 0x261e);
+               rc = WaitUntilBmpLoaded(av7110);
                if (rc)
                        return rc;
-               data += lpb * inc;
+               /* just continue. This should work for all fw versions
+                * if bnum==1 && !brest && LoadBitmap was successful
+                */
        }
-       if (brest) {
-               rc = LoadBitmap(av7110, bpp2bit[av7110->osdbpp[av7110->osdwin]],
-                          w, brest / bpl, inc, data);
+
+       rc = 0;
+       for (i = 0; i < bnum; i++) {
+               rc = LoadBitmap(av7110, w, lpb, inc, data);
                if (rc)
-                       return rc;
-               rc = BlitBitmap(av7110, av7110->osdwin, x0, y0 + bnum * lpb, 0);
+                       break;
+               rc = BlitBitmap(av7110, x0, y0 + i * lpb);
                if (rc)
-                       return rc;
+                       break;
+               data += lpb * inc;
        }
-       ReleaseBitmap(av7110);
-       return 0;
+       if (!rc && brest) {
+               rc = LoadBitmap(av7110, w, brest / bpl, inc, data);
+               if (!rc)
+                       rc = BlitBitmap(av7110, x0, y0 + bnum * lpb);
+       }
+       release_rc = ReleaseBitmap(av7110);
+       if (!rc)
+               rc = release_rc;
+       if (rc)
+               dprintk(1,"returns %d\n",rc);
+       return rc;
 }
 
 int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
 {
        int ret;
 
-       ret = down_interruptible(&av7110->osd_sema);
-       if (ret)
+       if (down_interruptible(&av7110->osd_sema))
                return -ERESTARTSYS;
 
-       /* stupid, but OSD functions don't provide a return code anyway */
-       ret = 0;
-
        switch (dc->cmd) {
        case OSD_Close:
-               DestroyOSDWindow(av7110, av7110->osdwin);
-               goto out;
+               ret = DestroyOSDWindow(av7110, av7110->osdwin);
+               break;
        case OSD_Open:
                av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7;
-               CreateOSDWindow(av7110, av7110->osdwin,
+               ret = CreateOSDWindow(av7110, av7110->osdwin,
                                bpp2bit[av7110->osdbpp[av7110->osdwin]],
                                dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
+               if (ret)
+                       break;
                if (!dc->data) {
-                       MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
-                       SetColorBlend(av7110, av7110->osdwin);
+                       ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
+                       if (ret)
+                               break;
+                       ret = SetColorBlend(av7110, av7110->osdwin);
                }
-               goto out;
+               break;
        case OSD_Show:
-               MoveWindowRel(av7110, av7110->osdwin, 0, 0);
-               goto out;
+               ret = MoveWindowRel(av7110, av7110->osdwin, 0, 0);
+               break;
        case OSD_Hide:
-               HideWindow(av7110, av7110->osdwin);
-               goto out;
+               ret = HideWindow(av7110, av7110->osdwin);
+               break;
        case OSD_Clear:
-               DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0);
-               goto out;
+               ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0);
+               break;
        case OSD_Fill:
-               DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color);
-               goto out;
+               ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color);
+               break;
        case OSD_SetColor:
-               OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1);
-               goto out;
+               ret = OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1);
+               break;
        case OSD_SetPalette:
-       {
-               if (FW_VERSION(av7110->arm_app) >= 0x2618) {
+               if (FW_VERSION(av7110->arm_app) >= 0x2618)
                        ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0);
-                       goto out;
-               } else {
+               else {
                        int i, len = dc->x0-dc->color+1;
                        u8 __user *colors = (u8 __user *)dc->data;
                        u8 r, g, b, blend;
-
+                       ret = 0;
                        for (i = 0; i<len; i++) {
                                if (get_user(r, colors + i * 4) ||
                                    get_user(g, colors + i * 4 + 1) ||
                                    get_user(b, colors + i * 4 + 2) ||
                                    get_user(blend, colors + i * 4 + 3)) {
                                        ret = -EFAULT;
-                                       goto out;
+                                       break;
                                    }
-                               OSDSetColor(av7110, dc->color + i, r, g, b, blend);
+                               ret = OSDSetColor(av7110, dc->color + i, r, g, b, blend);
+                               if (ret)
+                                       break;
                        }
                }
-               ret = 0;
-               goto out;
-       }
-       case OSD_SetTrans:
-               goto out;
+               break;
        case OSD_SetPixel:
-               DrawLine(av7110, av7110->osdwin,
+               ret = DrawLine(av7110, av7110->osdwin,
                         dc->x0, dc->y0, 0, 0, dc->color);
-               goto out;
-       case OSD_GetPixel:
-               goto out;
+               break;
        case OSD_SetRow:
                dc->y1 = dc->y0;
                /* fall through */
        case OSD_SetBlock:
                ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data);
-               goto out;
+               break;
        case OSD_FillRow:
-               DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
+               ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
                          dc->x1-dc->x0+1, dc->y1, dc->color);
-               goto out;
+               break;
        case OSD_FillBlock:
-               DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
+               ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
                          dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color);
-               goto out;
+               break;
        case OSD_Line:
-               DrawLine(av7110, av7110->osdwin,
+               ret = DrawLine(av7110, av7110->osdwin,
                         dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color);
-               goto out;
-       case OSD_Query:
-               goto out;
-       case OSD_Test:
-               goto out;
+               break;
        case OSD_Text:
        {
                char textbuf[240];
 
                if (strncpy_from_user(textbuf, dc->data, 240) < 0) {
                        ret = -EFAULT;
-                       goto out;
+                       break;
                }
                textbuf[239] = 0;
                if (dc->x1 > 3)
                        dc->x1 = 3;
-               SetFont(av7110, av7110->osdwin, dc->x1,
+               ret = SetFont(av7110, av7110->osdwin, dc->x1,
                        (u16) (dc->color & 0xffff), (u16) (dc->color >> 16));
-               FlushText(av7110);
-               WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf);
-               goto out;
+               if (!ret)
+                       ret = FlushText(av7110);
+               if (!ret)
+                       ret = WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf);
+               break;
        }
        case OSD_SetWindow:
-               if (dc->x0 < 1 || dc->x0 > 7) {
+               if (dc->x0 < 1 || dc->x0 > 7)
                        ret = -EINVAL;
-                       goto out;
+               else {
+                       av7110->osdwin = dc->x0;
+                       ret = 0;
                }
-               av7110->osdwin = dc->x0;
-               goto out;
+               break;
        case OSD_MoveWindow:
-               MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
-               SetColorBlend(av7110, av7110->osdwin);
-               goto out;
+               ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
+               if (!ret)
+                       ret = SetColorBlend(av7110, av7110->osdwin);
+               break;
        case OSD_OpenRaw:
                if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) {
                        ret = -EINVAL;
-                       goto out;
+                       break;
                }
-               if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR) {
+               if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR)
                        av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1;
-               }
-               else {
+               else
                        av7110->osdbpp[av7110->osdwin] = 0;
-               }
-               CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color,
+               ret = CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color,
                                dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
+               if (ret)
+                       break;
                if (!dc->data) {
-                       MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
-                       SetColorBlend(av7110, av7110->osdwin);
+                       ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
+                       if (!ret)
+                               ret = SetColorBlend(av7110, av7110->osdwin);
                }
-               goto out;
+               break;
        default:
                ret = -EINVAL;
-               goto out;
+               break;
        }
 
-out:
        up(&av7110->osd_sema);
+       if (ret==-ERESTARTSYS)
+               dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc->cmd);
+       else if (ret)
+               dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc->cmd,ret);
+
        return ret;
 }
 
index 52061e17c6dd8607a2990b2b770a69ea8ba91855..fedd20f9815d69632f75dbe9918dccce6061a06a 100644 (file)
@@ -458,27 +458,27 @@ static inline int SendDAC(struct av7110 *av7110, u8 addr, u8 data)
        return av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, AudioDAC, 2, addr, data);
 }
 
-static inline void av7710_set_video_mode(struct av7110 *av7110, int mode)
+static inline int av7710_set_video_mode(struct av7110 *av7110, int mode)
 {
-       av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetVidMode, 1, mode);
+       return av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetVidMode, 1, mode);
 }
 
-static int inline vidcom(struct av7110 *av7110, u32 com, u32 arg)
+static inline int vidcom(struct av7110 *av7110, u32 com, u32 arg)
 {
        return av7110_fw_cmd(av7110, COMTYPE_MISC, AV7110_FW_VIDEO_COMMAND, 4,
                             (com>>16), (com&0xffff),
                             (arg>>16), (arg&0xffff));
 }
 
-static int inline audcom(struct av7110 *av7110, u32 com)
+static inline int audcom(struct av7110 *av7110, u32 com)
 {
        return av7110_fw_cmd(av7110, COMTYPE_MISC, AV7110_FW_AUDIO_COMMAND, 2,
                             (com>>16), (com&0xffff));
 }
 
-static inline void Set22K(struct av7110 *av7110, int state)
+static inline int Set22K(struct av7110 *av7110, int state)
 {
-       av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, (state ? ON22K : OFF22K), 0);
+       return av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, (state ? ON22K : OFF22K), 0);
 }
 
 
index 2466407418886c0936279474dc4bdb7e694e46c8..699ef8b5b99ac9ac3ea720419777ffaa2b5e8dcf 100644 (file)
@@ -24,7 +24,7 @@ int av7110_ipack_init(struct ipack *p, int size,
                      void (*func)(u8 *buf, int size, void *priv))
 {
        if (!(p->buf = vmalloc(size*sizeof(u8)))) {
-               printk ("Couldn't allocate memory for ipack\n");
+               printk(KERN_WARNING "Couldn't allocate memory for ipack\n");
                return -ENOMEM;
        }
        p->size = size;
index 6e0f5d307c52de21c56ce2fa499272a85a6ed801..b65f4b0a481f65a5627e9bcc6fc226a1b77f14bf 100644 (file)
@@ -570,9 +570,9 @@ static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_p
 
        buf[0] = (div >> 8) & 0x7f;
        buf[1] = div & 0xff;
-       buf[2] = 0x8e;
-       buf[3] = (params->frequency < 174500000 ? 0xa1 :
-                 params->frequency < 454000000 ? 0x92 : 0x34);
+       buf[2] = 0x86;
+       buf[3] = (params->frequency < 150000000 ? 0x01 :
+                 params->frequency < 445000000 ? 0x02 : 0x04);
 
        if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
                return -EIO;
@@ -695,8 +695,12 @@ static struct tda1004x_config philips_tu1216_config = {
        .demod_address = 0x8,
        .invert = 1,
        .invert_oclk = 1,
+       .xtal_freq = TDA10046_XTAL_4M,
+       .agc_config = TDA10046_AGC_DEFAULT,
+       .if_freq = TDA10046_FREQ_3617,
        .pll_init = philips_tu1216_pll_init,
        .pll_set = philips_tu1216_pll_set,
+       .pll_sleep = NULL,
        .request_firmware = philips_tu1216_request_firmware,
 };
 
index dce116111376e8c7322d5c35604e7882c3b67423..a1267054bc018f7cde8b428dfe7fdd9d3d71b50a 100644 (file)
@@ -69,6 +69,7 @@ struct budget_ci {
        int slot_status;
        struct dvb_ca_en50221 ca;
        char ir_dev_name[50];
+       u8 tuner_pll_address; /* used for philips_tdm1316l configs */
 };
 
 /* from reading the following remotes:
@@ -723,7 +724,7 @@ static int philips_tdm1316l_pll_init(struct dvb_frontend *fe)
        struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
        static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
        static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
-       struct i2c_msg tuner_msg = {.addr = 0x63,.flags = 0,.buf = td1316_init,.len =
+       struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = td1316_init,.len =
                        sizeof(td1316_init) };
 
        // setup PLL configuration
@@ -746,7 +747,7 @@ static int philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend
 {
        struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
        u8 tuner_buf[4];
-       struct i2c_msg tuner_msg = {.addr = 0x63,.flags = 0,.buf = tuner_buf,.len = sizeof(tuner_buf) };
+       struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = tuner_buf,.len = sizeof(tuner_buf) };
        int tuner_frequency = 0;
        u8 band, cp, filter;
 
@@ -838,8 +839,12 @@ static struct tda1004x_config philips_tdm1316l_config = {
        .demod_address = 0x8,
        .invert = 0,
        .invert_oclk = 0,
+       .xtal_freq = TDA10046_XTAL_4M,
+       .agc_config = TDA10046_AGC_DEFAULT,
+       .if_freq = TDA10046_FREQ_3617,
        .pll_init = philips_tdm1316l_pll_init,
        .pll_set = philips_tdm1316l_pll_set,
+       .pll_sleep = NULL,
        .request_firmware = philips_tdm1316l_request_firmware,
 };
 
@@ -865,12 +870,22 @@ static void frontend_init(struct budget_ci *budget_ci)
                break;
 
        case 0x1011:            // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
+               budget_ci->tuner_pll_address = 0x63;
                budget_ci->budget.dvb_frontend =
                        tda10045_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
                        break;
                }
                break;
+
+       case 0x1012:            // Hauppauge/TT Nova-T CI budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
+               budget_ci->tuner_pll_address = 0x60;
+               budget_ci->budget.dvb_frontend =
+                       tda10046_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
+               if (budget_ci->budget.dvb_frontend) {
+                       break;
+               }
+               break;
        }
 
        if (budget_ci->budget.dvb_frontend == NULL) {
@@ -950,11 +965,13 @@ static struct saa7146_extension budget_extension;
 
 MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
 MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T         PCI", BUDGET_TT);
+MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
 
 static struct pci_device_id pci_tbl[] = {
        MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
        MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
        MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
+       MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
        {
         .vendor = 0,
         }
index 083fd44e5f905e539abe8e83fe1f3d2f3ec98cdd..9961917e8a7fd9c99501a15317c69cbcbd5e3bb4 100644 (file)
@@ -40,6 +40,7 @@
 #include "ves1820.h"
 #include "l64781.h"
 #include "tda8083.h"
+#include "s5h1420.h"
 
 static void Set22K (struct budget *budget, int state)
 {
@@ -177,6 +178,62 @@ static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t m
        return 0;
 }
 
+static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+       struct budget* budget = (struct budget*) fe->dvb->priv;
+       u8 buf;
+       struct i2c_msg msg = { .addr = 0x08, .flags = I2C_M_RD, .buf = &buf, .len = sizeof(buf) };
+
+       if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
+
+       switch(voltage) {
+       case SEC_VOLTAGE_13:
+               buf = (buf & 0xf7) | 0x04;
+               break;
+
+       case SEC_VOLTAGE_18:
+               buf = (buf & 0xf7) | 0x0c;
+               break;
+
+       case SEC_VOLTAGE_OFF:
+               buf = buf & 0xf0;
+               break;
+       }
+
+       msg.flags = 0;
+       if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
+
+       return 0;
+}
+
+static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend* fe, int arg)
+{
+       struct budget* budget = (struct budget*) fe->dvb->priv;
+       u8 buf;
+       struct i2c_msg msg = { .addr = 0x08, .flags = I2C_M_RD, .buf = &buf, .len = sizeof(buf) };
+
+       if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
+
+       if (arg) {
+               buf = buf | 0x10;
+       } else {
+               buf = buf & 0xef;
+       }
+
+       msg.flags = 0;
+       if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
+
+       return 0;
+}
+
+static void lnbp21_init(struct budget* budget)
+{
+       u8 buf = 0x00;
+       struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = &buf, .len = sizeof(buf) };
+
+       i2c_transfer (&budget->i2c_adap, &msg, 1);
+}
+
 static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct budget* budget = (struct budget*) fe->dvb->priv;
@@ -395,6 +452,38 @@ static struct tda8083_config grundig_29504_451_config = {
        .pll_set = grundig_29504_451_pll_set,
 };
 
+static int s5h1420_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout)
+{
+       struct budget* budget = (struct budget*) fe->dvb->priv;
+       u32 div;
+       u8 data[4];
+       struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+
+       div = params->frequency / 1000;
+       data[0] = (div >> 8) & 0x7f;
+       data[1] = div & 0xff;
+       data[2] = 0xc2;
+
+       if (div < 1450)
+               data[3] = 0x00;
+       else if (div < 1850)
+               data[3] = 0x40;
+       else if (div < 2000)
+               data[3] = 0x80;
+       else
+               data[3] = 0xc0;
+
+       if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
+
+       *freqout = div * 1000;
+       return 0;
+}
+
+static struct s5h1420_config s5h1420_config = {
+       .demod_address = 0x53,
+       .pll_set = s5h1420_pll_set,
+};
+
 static u8 read_pwm(struct budget* budget)
 {
        u8 b = 0xff;
@@ -459,6 +548,15 @@ static void frontend_init(struct budget *budget)
                        break;
                }
                break;
+
+       case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
+               budget->dvb_frontend = s5h1420_attach(&s5h1420_config, &budget->i2c_adap);
+               if (budget->dvb_frontend) {
+                       budget->dvb_frontend->ops->set_voltage = lnbp21_set_voltage;
+                       budget->dvb_frontend->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
+                       lnbp21_init(budget);
+                       break;
+               }
        }
 
        if (budget->dvb_frontend == NULL) {
@@ -532,6 +630,7 @@ static struct pci_device_id pci_tbl[] = {
        MAKE_EXTENSION_PCI(ttbc,  0x13c2, 0x1004),
        MAKE_EXTENSION_PCI(ttbt,  0x13c2, 0x1005),
        MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
+       MAKE_EXTENSION_PCI(ttbs,  0x13c2, 0x1016),
        MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
        MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
        {
index 4aa714ab4c28bc674bbf4848dbe62a52efe8ae0b..c6c1d41a2efb70c77b46db6a80450282d7fe4fdf 100644 (file)
@@ -3,6 +3,7 @@ config DVB_TTUSB_BUDGET
        depends on DVB_CORE && USB
        select DVB_CX22700
        select DVB_TDA1004X
+       select DVB_VES1820
        select DVB_TDA8083
        select DVB_STV0299
        help
index afa0e7a0e5067a68180e595a0cd88b4e8c13b904..2c17a5f58340d05c7999e567d5ad146daa79648a 100644 (file)
@@ -24,6 +24,7 @@
 #include "dmxdev.h"
 #include "dvb_demux.h"
 #include "dvb_net.h"
+#include "ves1820.h"
 #include "cx22700.h"
 #include "tda1004x.h"
 #include "stv0299.h"
@@ -1367,6 +1368,47 @@ static struct tda8083_config ttusb_novas_grundig_29504_491_config = {
        .pll_set = ttusb_novas_grundig_29504_491_pll_set,
 };
 
+static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+{
+       struct ttusb* ttusb = fe->dvb->priv;
+       u32 div;
+       u8 data[4];
+       struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
+
+       div = (params->frequency + 35937500 + 31250) / 62500;
+
+       data[0] = (div >> 8) & 0x7f;
+       data[1] = div & 0xff;
+       data[2] = 0x85 | ((div >> 10) & 0x60);
+       data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
+
+       if (i2c_transfer (&ttusb->i2c_adap, &msg, 1) != 1)
+               return -EIO;
+
+       return 0;
+}
+
+
+static struct ves1820_config alps_tdbe2_config = {
+       .demod_address = 0x09,
+       .xin = 57840000UL,
+       .invert = 1,
+       .selagc = VES1820_SELAGC_SIGNAMPERR,
+       .pll_set = alps_tdbe2_pll_set,
+};
+
+static u8 read_pwm(struct ttusb* ttusb)
+{
+       u8 b = 0xff;
+       u8 pwm;
+       struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
+                               { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
+
+       if ((i2c_transfer(&ttusb->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
+               pwm = 0x48;
+
+       return pwm;
+}
 
 
 static void frontend_init(struct ttusb* ttusb)
@@ -1394,6 +1436,12 @@ static void frontend_init(struct ttusb* ttusb)
 
                break;
 
+       case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
+               ttusb->fe = ves1820_attach(&alps_tdbe2_config, &ttusb->i2c_adap, read_pwm(ttusb));
+               if (ttusb->fe != NULL)
+                       break;
+               break;
+
        case 0x1005: // Hauppauge/TT Nova-USB-t budget (tda10046/Philips td1316(tda6651tt) OR cx22700/ALPS TDMB7(??))
                // try the ALPS TDMB7 first
                ttusb->fe = cx22700_attach(&alps_tdmb7_config, &ttusb->i2c_adap);
@@ -1570,7 +1618,7 @@ static void ttusb_disconnect(struct usb_interface *intf)
 
 static struct usb_device_id ttusb_table[] = {
        {USB_DEVICE(0xb48, 0x1003)},
-/*     {USB_DEVICE(0xb48, 0x1004)},UNDEFINED HARDWARE - mail linuxtv.org list*/        /* to be confirmed ????  */
+       {USB_DEVICE(0xb48, 0x1004)},
        {USB_DEVICE(0xb48, 0x1005)},
        {}
 };
index 505bdaff5a7eea16ff148ba87d9f74d7ea93043b..45c9a9a08e4d8ecea7b940d149cef87d609ad310 100644 (file)
@@ -1281,6 +1281,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
        if (firmware_size < 60) {
                printk("%s: firmware size too small for DSP code (%zu < 60).\n",
                        __FUNCTION__, firmware_size);
+               release_firmware(fw_entry);
                return -1;
        }
 
@@ -1294,6 +1295,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
                printk("%s: crc32 check of DSP code failed (calculated "
                       "0x%08x != 0x%08x in file), file invalid.\n",
                        __FUNCTION__, crc32_csum, crc32_check);
+               release_firmware(fw_entry);
                return -1;
        }
        memcpy(idstring, &firmware[36], 20);
@@ -1308,15 +1310,19 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
 
        result = ttusb_dec_send_command(dec, 0x41, sizeof(b0), b0, NULL, NULL);
 
-       if (result)
+       if (result) {
+               release_firmware(fw_entry);
                return result;
+       }
 
        trans_count = 0;
        j = 0;
 
        b = kmalloc(ARM_PACKET_SIZE, GFP_KERNEL);
-       if (b == NULL)
+       if (b == NULL) {
+               release_firmware(fw_entry);
                return -ENOMEM;
+       }
 
        for (i = 0; i < firmware_size; i += COMMAND_PACKET_SIZE) {
                size = firmware_size - i;
@@ -1345,6 +1351,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
 
        result = ttusb_dec_send_command(dec, 0x43, sizeof(b1), b1, NULL, NULL);
 
+       release_firmware(fw_entry);
        kfree(b);
 
        return result;
index 1699cc9f6bb0ddd563d4f49d8ce5b0609e95455a..725af3af5b27105f5c2e8555e68de691272e41fc 100644 (file)
@@ -157,7 +157,8 @@ struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* conf
 
        /* allocate memory for the internal state */
        state = (struct ttusbdecfe_state*) kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
-       if (state == NULL) goto error;
+       if (state == NULL)
+               return NULL;
 
        /* setup the state */
        state->config = config;
@@ -167,10 +168,6 @@ struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* conf
        state->frontend.ops = &state->ops;
        state->frontend.demodulator_priv = state;
        return &state->frontend;
-
-error:
-       kfree(state);
-       return NULL;
 }
 
 static struct dvb_frontend_ops ttusbdecfe_dvbs_ops;
@@ -181,7 +178,8 @@ struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* conf
 
        /* allocate memory for the internal state */
        state = (struct ttusbdecfe_state*) kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
-       if (state == NULL) goto error;
+       if (state == NULL)
+               return NULL;
 
        /* setup the state */
        state->config = config;
@@ -193,10 +191,6 @@ struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* conf
        state->frontend.ops = &state->ops;
        state->frontend.demodulator_priv = state;
        return &state->frontend;
-
-error:
-       kfree(state);
-       return NULL;
 }
 
 static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
index 1b70f8b0feb9fa1f32d10715a657edc114dc73a3..e771064689e6e1756013537eb952f384d36b3e7a 100644 (file)
@@ -344,6 +344,7 @@ config VIDEO_CX88_DVB
        select DVB_MT352
        select DVB_OR51132
        select DVB_CX22702
+       select DVB_LGDT3302
        ---help---
          This adds support for DVB/ATSC cards based on the
          Connexant 2388x chip.
index b3fb04356b719cdeeab67f2939e4f6ee4a155512..b0b47c3cde3c8cce18954bc7ee3844d77645c82d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88-cards.c,v 1.76 2005/06/08 01:28:09 mchehab Exp $
+ * $Id: cx88-cards.c,v 1.85 2005/07/04 19:35:05 mkrufky Exp $
  *
  * device driver for Conexant 2388x based TV cards
  * card-specific stuff.
@@ -401,7 +401,7 @@ struct cx88_board cx88_boards[] = {
                .dvb            = 1,
        },
        [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = {
-               .name           = "DVICO FusionHDTV DVB-T1",
+               .name           = "DViCO FusionHDTV DVB-T1",
                .tuner_type     = TUNER_ABSENT, /* No analog tuner */
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
@@ -445,8 +445,8 @@ struct cx88_board cx88_boards[] = {
                         .gpio0  = 0x000007f8,
                 },
        },
-       [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD] = {
-               .name           = "DViCO - FusionHDTV 3 Gold",
+       [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q] = {
+               .name           = "DViCO FusionHDTV 3 Gold-Q",
                .tuner_type     = TUNER_MICROTUNE_4042FI5,
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
@@ -464,6 +464,9 @@ struct cx88_board cx88_boards[] = {
                   GPIO[3] selects RF input connector on tuner module
                    0 - RF connector labeled CABLE
                    1 - RF connector labeled ANT
+                  GPIO[4] selects high RF for QAM256 mode
+                   0 - normal RF
+                   1 - high RF
                */
                .input          = {{
                        .type   = CX88_VMUX_TELEVISION,
@@ -482,6 +485,7 @@ struct cx88_board cx88_boards[] = {
                        .vmux   = 2,
                        .gpio0  = 0x0f00,
                }},
+               .dvb            = 1,
        },
         [CX88_BOARD_HAUPPAUGE_DVB_T1] = {
                .name           = "Hauppauge Nova-T DVB-T",
@@ -520,7 +524,7 @@ struct cx88_board cx88_boards[] = {
                .blackbird = 1,
        },
        [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = {
-               .name           = "DVICO FusionHDTV DVB-T Plus",
+               .name           = "DViCO FusionHDTV DVB-T Plus",
                .tuner_type     = TUNER_ABSENT, /* No analog tuner */
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
@@ -700,20 +704,16 @@ struct cx88_board cx88_boards[] = {
                 },
        },
         [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = {
-                .name           = "DViCO - FusionHDTV 3 Gold-T",
+               .name           = "DViCO FusionHDTV 3 Gold-T",
                .tuner_type     = TUNER_THOMSON_DTT7611,
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
-               /*  See DViCO FusionHDTV 3 Gold for GPIO documentation.  */
-                .input          = {{
+               /*  See DViCO FusionHDTV 3 Gold-Q for GPIO documentation.  */
+               .input          = {{
                         .type   = CX88_VMUX_TELEVISION,
                         .vmux   = 0,
                         .gpio0  = 0x0f0d,
-                },{
-                        .type   = CX88_VMUX_CABLE,
-                        .vmux   = 0,
-                        .gpio0  = 0x0f05,
                 },{
                         .type   = CX88_VMUX_COMPOSITE1,
                         .vmux   = 1,
@@ -723,7 +723,36 @@ struct cx88_board cx88_boards[] = {
                         .vmux   = 2,
                         .gpio0  = 0x0f00,
                 }},
+               .dvb            = 1,
         },
+        [CX88_BOARD_ADSTECH_DVB_T_PCI] = {
+                .name           = "ADS Tech Instant TV DVB-T PCI",
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                        .type   = CX88_VMUX_COMPOSITE1,
+                        .vmux   = 1,
+                       .gpio0  = 0x0700,
+                       .gpio2  = 0x0101,
+                },{
+                        .type   = CX88_VMUX_SVIDEO,
+                        .vmux   = 2,
+                       .gpio0  = 0x0700,
+                       .gpio2  = 0x0101,
+                }},
+               .dvb            = 1,
+       },
+       [CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1] = {
+               .name           = "TerraTec Cinergy 1400 DVB-T",
+               .tuner_type     = TUNER_ABSENT,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               }},
+               .dvb            = 1,
+       },
 };
 const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
 
@@ -794,7 +823,7 @@ struct cx88_subid cx88_subids[] = {
        },{
                .subvendor = 0x18ac,
                .subdevice = 0xd810,
-               .card      = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD,
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q,
        },{
                .subvendor = 0x18ac,
                .subdevice = 0xd820,
@@ -843,7 +872,15 @@ struct cx88_subid cx88_subids[] = {
                .subvendor = 0x10fc,
                .subdevice = 0xd035,
                .card      = CX88_BOARD_IODATA_GVBCTV7E,
-       }
+       },{
+               .subvendor = 0x1421,
+               .subdevice = 0x0334,
+               .card      = CX88_BOARD_ADSTECH_DVB_T_PCI,
+       },{
+               .subvendor = 0x153b,
+               .subdevice = 0x1166,
+               .card      = CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1,
+       },
 };
 const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
 
index c046a23537d35ed22923e833c8ebcd7306c62213..96cb0ff33bbde01111a2eadb5d0eb0f483e3f86f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88-core.c,v 1.28 2005/06/12 04:19:19 mchehab Exp $
+ * $Id: cx88-core.c,v 1.31 2005/06/22 22:58:04 mchehab Exp $
  *
  * device driver for Conexant 2388x based TV cards
  * driver core
@@ -545,12 +545,14 @@ void cx88_sram_channel_dump(struct cx88_core *core,
               core->name,cx_read(ch->cnt2_reg));
 }
 
+/* Used only on cx88-core */
 static char *cx88_pci_irqs[32] = {
        "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
        "src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
        "brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
        "i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
 };
+/* Used only on cx88-video */
 char *cx88_vid_irqs[32] = {
        "y_risci1", "u_risci1", "v_risci1", "vbi_risc1",
        "y_risci2", "u_risci2", "v_risci2", "vbi_risc2",
@@ -558,6 +560,7 @@ char *cx88_vid_irqs[32] = {
        "y_sync",   "u_sync",   "v_sync",   "vbi_sync",
        "opc_err",  "par_err",  "rip_err",  "pci_abort",
 };
+/* Used only on cx88-mpeg */
 char *cx88_mpeg_irqs[32] = {
        "ts_risci1", NULL, NULL, NULL,
        "ts_risci2", NULL, NULL, NULL,
@@ -1006,21 +1009,7 @@ int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
        set_tvaudio(core);
 
        // tell i2c chips
-#ifdef V4L2_I2C_CLIENTS
        cx88_call_i2c_clients(core,VIDIOC_S_STD,&norm->id);
-#else
-       {
-               struct video_channel c;
-               memset(&c,0,sizeof(c));
-               c.channel = core->input;
-               c.norm = VIDEO_MODE_PAL;
-               if ((norm->id & (V4L2_STD_NTSC_M|V4L2_STD_NTSC_M_JP)))
-                       c.norm = VIDEO_MODE_NTSC;
-               if (norm->id & V4L2_STD_SECAM)
-                       c.norm = VIDEO_MODE_SECAM;
-               cx88_call_i2c_clients(core,VIDIOCSCHAN,&c);
-       }
-#endif
 
        // done
        return 0;
index 1a259c3966cd748ff6d0130a0262ba02e7b1da52..690477a679178ee321a5dbba01671cc63197f674 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88-dvb.c,v 1.33 2005/06/12 04:19:19 mchehab Exp $
+ * $Id: cx88-dvb.c,v 1.39 2005/07/02 20:00:46 mkrufky Exp $
  *
  * device driver for Conexant 2388x based TV cards
  * MPEG Transport Stream (DVB) routines
 #include <linux/file.h>
 #include <linux/suspend.h>
 
-/* those two frontends need merging via linuxtv cvs ... */
+/* these three frontends need merging via linuxtv cvs ... */
 #define HAVE_CX22702 1
 #define HAVE_OR51132 1
+#define HAVE_LGDT3302 1
 
 #include "cx88.h"
 #include "dvb-pll.h"
@@ -44,6 +45,9 @@
 #if HAVE_OR51132
 # include "or51132.h"
 #endif
+#if HAVE_LGDT3302
+# include "lgdt3302.h"
+#endif
 
 MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
 MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
@@ -199,6 +203,32 @@ static struct or51132_config pchdtv_hd3000 = {
 };
 #endif
 
+#if HAVE_LGDT3302
+static int lgdt3302_set_ts_param(struct dvb_frontend* fe, int is_punctured)
+{
+       struct cx8802_dev *dev= fe->dvb->priv;
+       if (is_punctured)
+               dev->ts_gen_cntrl |= 0x04;
+       else
+               dev->ts_gen_cntrl &= ~0x04;
+       return 0;
+}
+
+static struct lgdt3302_config fusionhdtv_3_gold_q = {
+       .demod_address    = 0x0e,
+       .pll_address      = 0x61,
+       .pll_desc         = &dvb_pll_microtune_4042,
+       .set_ts_params    = lgdt3302_set_ts_param,
+};
+
+static struct lgdt3302_config fusionhdtv_3_gold_t = {
+       .demod_address    = 0x0e,
+       .pll_address      = 0x61,
+       .pll_desc         = &dvb_pll_thomson_dtt7611,
+       .set_ts_params    = lgdt3302_set_ts_param,
+};
+#endif
+
 static int dvb_register(struct cx8802_dev *dev)
 {
        /* init struct videobuf_dvb */
@@ -212,6 +242,7 @@ static int dvb_register(struct cx8802_dev *dev)
                dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config,
                                                   &dev->core->i2c_adap);
                break;
+       case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
        case CX88_BOARD_CONEXANT_DVB_T1:
                dev->dvb.frontend = cx22702_attach(&connexant_refboard_config,
                                                   &dev->core->i2c_adap);
@@ -231,6 +262,7 @@ static int dvb_register(struct cx8802_dev *dev)
                break;
        case CX88_BOARD_KWORLD_DVB_T:
        case CX88_BOARD_DNTV_LIVE_DVB_T:
+       case CX88_BOARD_ADSTECH_DVB_T_PCI:
                dev->core->pll_addr = 0x61;
                dev->core->pll_desc = &dvb_pll_unknown_1;
                dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config,
@@ -241,6 +273,36 @@ static int dvb_register(struct cx8802_dev *dev)
                dev->dvb.frontend = or51132_attach(&pchdtv_hd3000,
                                                 &dev->core->i2c_adap);
                break;
+#endif
+#if HAVE_LGDT3302
+       case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
+               dev->ts_gen_cntrl = 0x08;
+               {
+               /* Do a hardware reset of chip before using it. */
+               struct cx88_core *core = dev->core;
+
+               cx_clear(MO_GP0_IO, 1);
+               mdelay(100);
+               cx_set(MO_GP0_IO, 9); // ANT connector too FIXME
+               mdelay(200);
+               dev->dvb.frontend = lgdt3302_attach(&fusionhdtv_3_gold_q,
+                                                   &dev->core->i2c_adap);
+               }
+               break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
+               dev->ts_gen_cntrl = 0x08;
+               {
+               /* Do a hardware reset of chip before using it. */
+               struct cx88_core *core = dev->core;
+
+               cx_clear(MO_GP0_IO, 1);
+               mdelay(100);
+               cx_set(MO_GP0_IO, 9); /* ANT connector too FIXME */
+               mdelay(200);
+               dev->dvb.frontend = lgdt3302_attach(&fusionhdtv_3_gold_t,
+                                                   &dev->core->i2c_adap);
+               }
+               break;
 #endif
        default:
                printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
index e20adefcfc6c76d233c54eb3edb29908ac9cfabc..b5342234b3059585723a5470641caf27154a4922 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    $Id: cx88-i2c.c,v 1.23 2005/06/12 04:19:19 mchehab Exp $
+    $Id: cx88-i2c.c,v 1.24 2005/06/17 18:46:23 mkrufky Exp $
 
     cx88-i2c.c  --  all the i2c code is here
 
@@ -157,6 +157,7 @@ static struct i2c_client cx8800_i2c_client_template = {
 };
 
 static char *i2c_devs[128] = {
+       [ 0x1c >> 1 ] = "lgdt3302",
        [ 0x86 >> 1 ] = "tda9887/cx22702",
        [ 0xa0 >> 1 ] = "eeprom",
        [ 0xc0 >> 1 ] = "tuner (analog)",
index dc0dcf249aacfe63fdf01b5a08c241a06ea1785c..bdc26e75ab5fd22a6da7c48ad3f7b7ceff623164 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88-input.c,v 1.11 2005/05/22 20:57:56 nsh Exp $
+ * $Id: cx88-input.c,v 1.13 2005/06/13 16:07:46 nsh Exp $
  *
  * Device driver for GPIO attached remote control interfaces
  * on Conexant 2388x based TV/DVB cards.
@@ -125,6 +125,86 @@ static IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = {
 
 /* ---------------------------------------------------------------------- */
 
+/* ADS Tech Instant TV DVB-T PCI Remote */
+static IR_KEYTAB_TYPE ir_codes_adstech_dvb_t_pci[IR_KEYTAB_SIZE] = {
+       [ 0x5b ] = KEY_POWER,
+       [ 0x5f ] = KEY_MUTE,
+       [ 0x57 ] = KEY_1,
+       [ 0x4f ] = KEY_2,
+       [ 0x53 ] = KEY_3,
+       [ 0x56 ] = KEY_4,
+       [ 0x4e ] = KEY_5,
+       [ 0x5e ] = KEY_6,
+       [ 0x54 ] = KEY_7,
+       [ 0x4c ] = KEY_8,
+       [ 0x5c ] = KEY_9,
+       [ 0x4d ] = KEY_0,
+       [ 0x55 ] = KEY_GOTO,
+       [ 0x5d ] = KEY_SEARCH,
+       [ 0x17 ] = KEY_EPG,             // Guide
+       [ 0x1f ] = KEY_MENU,
+       [ 0x0f ] = KEY_UP,
+       [ 0x46 ] = KEY_DOWN,
+       [ 0x16 ] = KEY_LEFT,
+       [ 0x1e ] = KEY_RIGHT,
+       [ 0x0e ] = KEY_SELECT,          // Enter
+       [ 0x5a ] = KEY_INFO,
+       [ 0x52 ] = KEY_EXIT,
+       [ 0x59 ] = KEY_PREVIOUS,
+       [ 0x51 ] = KEY_NEXT,
+       [ 0x58 ] = KEY_REWIND,
+       [ 0x50 ] = KEY_FORWARD,
+       [ 0x44 ] = KEY_PLAYPAUSE,
+       [ 0x07 ] = KEY_STOP,
+       [ 0x1b ] = KEY_RECORD,
+       [ 0x13 ] = KEY_TUNER,           // Live
+       [ 0x0a ] = KEY_A,
+       [ 0x12 ] = KEY_B,
+       [ 0x03 ] = KEY_PROG1,           // 1
+       [ 0x01 ] = KEY_PROG2,           // 2
+       [ 0x00 ] = KEY_PROG3,           // 3
+       [ 0x06 ] = KEY_DVD,
+       [ 0x48 ] = KEY_AUX,             // Photo
+       [ 0x40 ] = KEY_VIDEO,
+       [ 0x19 ] = KEY_AUDIO,           // Music
+       [ 0x0b ] = KEY_CHANNELUP,
+       [ 0x08 ] = KEY_CHANNELDOWN,
+       [ 0x15 ] = KEY_VOLUMEUP,
+       [ 0x1c ] = KEY_VOLUMEDOWN,
+};
+
+/* ---------------------------------------------------------------------- */
+
+/* MSI TV@nywhere remote */
+static IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = {
+       [ 0x00 ] = KEY_0,           /* '0' */
+       [ 0x01 ] = KEY_1,           /* '1' */
+       [ 0x02 ] = KEY_2,           /* '2' */
+       [ 0x03 ] = KEY_3,           /* '3' */
+       [ 0x04 ] = KEY_4,           /* '4' */
+       [ 0x05 ] = KEY_5,           /* '5' */
+       [ 0x06 ] = KEY_6,           /* '6' */
+       [ 0x07 ] = KEY_7,           /* '7' */
+       [ 0x08 ] = KEY_8,           /* '8' */
+       [ 0x09 ] = KEY_9,           /* '9' */
+       [ 0x0c ] = KEY_MUTE,        /* 'Mute' */
+       [ 0x0f ] = KEY_SCREEN,      /* 'Full Screen' */
+       [ 0x10 ] = KEY_F,           /* 'Funtion' */
+       [ 0x11 ] = KEY_T,           /* 'Time shift' */
+       [ 0x12 ] = KEY_POWER,       /* 'Power' */
+       [ 0x13 ] = KEY_MEDIA,       /* 'MTS' */
+       [ 0x14 ] = KEY_SLOW,        /* 'Slow' */
+       [ 0x16 ] = KEY_REWIND,      /* 'backward <<' */
+       [ 0x17 ] = KEY_ENTER,       /* 'Return' */
+       [ 0x18 ] = KEY_FASTFORWARD, /* 'forward >>' */
+       [ 0x1a ] = KEY_CHANNELUP,   /* 'Channel+' */
+       [ 0x1b ] = KEY_VOLUMEUP,    /* 'Volume+' */
+       [ 0x1e ] = KEY_CHANNELDOWN, /* 'Channel-' */
+       [ 0x1f ] = KEY_VOLUMEDOWN,  /* 'Volume-' */
+};
+
+/* ---------------------------------------------------------------------- */
+
 struct cx88_IR {
        struct cx88_core        *core;
        struct input_dev        input;
@@ -269,6 +349,20 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
                ir->mask_keyup   = 0x80;
                ir->polling      = 1; // ms
                break;
+       case CX88_BOARD_ADSTECH_DVB_T_PCI:
+               ir_codes         = ir_codes_adstech_dvb_t_pci;
+               ir->gpio_addr    = MO_GP1_IO;
+               ir->mask_keycode = 0xbf;
+               ir->mask_keyup   = 0x40;
+               ir->polling      = 50; // ms
+               break;
+        case CX88_BOARD_MSI_TVANYWHERE_MASTER:
+                ir_codes         = ir_codes_msi_tvanywhere;
+                ir->gpio_addr    = MO_GP1_IO;
+                ir->mask_keycode = 0x1f;
+                ir->mask_keyup   = 0x40;
+                ir->polling      = 1;
+                break;
        }
 
        if (NULL == ir_codes) {
index 9ade2ae91e9bfef1b787d1179cbd7234e5a9eb52..85da6dc8d0e0e81c50268526ef2b254914b7bda5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88-mpeg.c,v 1.26 2005/06/03 13:31:51 mchehab Exp $
+ * $Id: cx88-mpeg.c,v 1.30 2005/07/05 19:44:40 mkrufky Exp $
  *
  *  Support for the mpeg transport stream transfers
  *  PCI function #2 of the cx2388x.
@@ -70,11 +70,16 @@ static int cx8802_start_dma(struct cx8802_dev    *dev,
 
        if (cx88_boards[core->board].dvb) {
                /* negedge driven & software reset */
-               cx_write(TS_GEN_CNTRL, 0x40);
+               cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl);
                udelay(100);
                cx_write(MO_PINMUX_IO, 0x00);
-               cx_write(TS_HW_SOP_CNTRL,47<<16|188<<4|0x00);
-               cx_write(TS_SOP_STAT,0x00);
+               cx_write(TS_HW_SOP_CNTRL,0x47<<16|188<<4|0x01);
+               if ((core->board == CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q) ||
+                   (core->board == CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T)) {
+                       cx_write(TS_SOP_STAT, 0<<16 | 0<<14 | 1<<13 | 0<<12);
+               } else {
+                       cx_write(TS_SOP_STAT,0x00);
+               }
                cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
                udelay(100);
        }
index e4ca7350df1510f4e4e3eb58f83aa2a3101a840c..dc997549b6340fef3751563ed692070167cc2c68 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88-video.c,v 1.63 2005/06/12 04:19:19 mchehab Exp $
+ * $Id: cx88-video.c,v 1.70 2005/06/20 03:36:00 mkrufky Exp $
  *
  * device driver for Conexant 2388x based TV cards
  * video4linux video interface
@@ -261,7 +261,7 @@ static struct cx88_ctrl cx8800_ctls[] = {
                        .default_value = 0,
                        .type          = V4L2_CTRL_TYPE_INTEGER,
                },
-               .off                   = 0,
+               .off                   = 128,
                .reg                   = MO_HUE,
                .mask                  = 0x00ff,
                .shift                 = 0,
@@ -1350,9 +1350,6 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
                        V4L2_CAP_READWRITE     |
                        V4L2_CAP_STREAMING     |
                        V4L2_CAP_VBI_CAPTURE   |
-#if 0
-                       V4L2_TUNER_CAP_LOW     |
-#endif
 #if 0
                        V4L2_CAP_VIDEO_OVERLAY |
 #endif
@@ -1475,7 +1472,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
                        }
                        break;
                case 1:
-                       if (CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD == core->board) {
+                       if (CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q == core->board) {
                                strcpy(a->name,"Line In");
                                a->capability = V4L2_AUDCAP_STEREO;
                                return 0;
@@ -1588,11 +1585,11 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
        {
                struct v4l2_frequency *f = arg;
 
+               memset(f,0,sizeof(*f));
+
                if (UNSET == core->tuner_type)
                        return -EINVAL;
-               if (f->tuner != 0)
-                       return -EINVAL;
-               memset(f,0,sizeof(*f));
+
                f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
                f->frequency = dev->freq;
                return 0;
@@ -1612,11 +1609,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
                down(&dev->lock);
                dev->freq = f->frequency;
                cx88_newstation(core);
-#ifdef V4L2_I2C_CLIENTS
                cx88_call_i2c_clients(dev->core,VIDIOC_S_FREQUENCY,f);
-#else
-               cx88_call_i2c_clients(dev->core,VIDIOCSFREQ,&dev->freq);
-#endif
                up(&dev->lock);
                return 0;
        }
@@ -1714,11 +1707,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
                        sizeof(cap->card));
                sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
                cap->version = CX88_VERSION_CODE;
-               cap->capabilities = V4L2_CAP_TUNER
-#if 0
-                                   | V4L2_TUNER_CAP_LOW
-#endif
-                                   ;
+               cap->capabilities = V4L2_CAP_TUNER;
                return 0;
        }
        case VIDIOC_G_TUNER:
@@ -1730,19 +1719,8 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
 
                memset(t,0,sizeof(*t));
                strcpy(t->name, "Radio");
-                t->rangelow  = (int)(65*16);
-                t->rangehigh = (int)(108*16);
 
-#ifdef V4L2_I2C_CLIENTS
                cx88_call_i2c_clients(dev->core,VIDIOC_G_TUNER,t);
-#else
-               {
-                       struct video_tuner vt;
-                       memset(&vt,0,sizeof(vt));
-                       cx88_call_i2c_clients(dev,VIDIOCGTUNER,&vt);
-                       t->signal = vt.signal;
-               }
-#endif
                return 0;
        }
        case VIDIOC_ENUMINPUT:
@@ -1775,8 +1753,29 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
                *id = 0;
                return 0;
        }
-       case VIDIOC_S_AUDIO:
+       case VIDIOCSTUNER:
+       {
+               struct video_tuner *v = arg;
+
+               if (v->tuner) /* Only tuner 0 */
+                       return -EINVAL;
+
+               cx88_call_i2c_clients(dev->core,VIDIOCSTUNER,v);
+                return 0;
+       }
        case VIDIOC_S_TUNER:
+       {
+               struct v4l2_tuner *t = arg;
+
+               if (0 != t->index)
+                       return -EINVAL;
+
+               cx88_call_i2c_clients(dev->core,VIDIOC_S_TUNER,t);
+
+               return 0;
+       }
+
+       case VIDIOC_S_AUDIO:
        case VIDIOC_S_INPUT:
        case VIDIOC_S_STD:
                return 0;
index 867e988a5a93cc397685a4095cb861860dbd8e9e..bc5e038bc0feeb56c7d5850a34e94c09b565e503 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88.h,v 1.62 2005/06/12 04:19:19 mchehab Exp $
+ * $Id: cx88.h,v 1.67 2005/07/01 12:10:07 mkrufky Exp $
  *
  * v4l2 device driver for cx2388x based TV cards
  *
@@ -51,8 +51,6 @@
 /* ----------------------------------------------------------- */
 /* defines and enums                                           */
 
-#define V4L2_I2C_CLIENTS 1
-
 #define FORMAT_FLAGS_PACKED       0x01
 #define FORMAT_FLAGS_PLANAR       0x02
 
@@ -159,7 +157,7 @@ extern struct sram_channel cx88_sram_channels[];
 #define CX88_BOARD_KWORLD_DVB_T            14
 #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1 15
 #define CX88_BOARD_KWORLD_LTV883           16
-#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD 17
+#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q  17
 #define CX88_BOARD_HAUPPAUGE_DVB_T1        18
 #define CX88_BOARD_CONEXANT_DVB_T1         19
 #define CX88_BOARD_PROVIDEO_PV259          20
@@ -167,10 +165,12 @@ extern struct sram_channel cx88_sram_channels[];
 #define CX88_BOARD_PCHDTV_HD3000           22
 #define CX88_BOARD_DNTV_LIVE_DVB_T         23
 #define CX88_BOARD_HAUPPAUGE_ROSLYN        24
-#define CX88_BOARD_DIGITALLOGIC_MEC           25
+#define CX88_BOARD_DIGITALLOGIC_MEC        25
 #define CX88_BOARD_IODATA_GVBCTV7E         26
 #define CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO 27
 #define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T  28
+#define CX88_BOARD_ADSTECH_DVB_T_PCI          29
+#define CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1  30
 
 enum cx88_itype {
        CX88_VMUX_COMPOSITE1 = 1,
index 8b623278ccd24f90e9966d13b508d35136923329..ffbe6f4720e161da17c25ee6ecc549ef547be929 100644 (file)
@@ -1363,19 +1363,7 @@ mpt_suspend(struct pci_dev *pdev, pm_message_t state)
        u32 device_state;
        MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
 
-       switch(state)
-       {
-               case 1: /* S1 */
-                       device_state=1; /* D1 */;
-                       break;
-               case 3: /* S3 */
-               case 4: /* S4 */
-                       device_state=3; /* D3 */;
-                       break;
-               default:
-                       return -EAGAIN /*FIXME*/;
-                       break;
-       }
+       device_state=pci_choose_state(pdev, state);
 
        printk(MYIOC_s_INFO_FMT
        "pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
index 5ea89bf0df199862e26c1398f006818b852ea66d..debb8ac5954571a683e26e7e77023b8ec382665d 100644 (file)
@@ -84,7 +84,7 @@
 extern void mptscsih_remove(struct pci_dev *);
 extern void mptscsih_shutdown(struct pci_dev *);
 #ifdef CONFIG_PM
-extern int mptscsih_suspend(struct pci_dev *pdev, u32 state);
+extern int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
 extern int mptscsih_resume(struct pci_dev *pdev);
 #endif
 extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func);
index d0267609a94948c777fdbdafe111823b2984ab8c..fe2e7afc9eae25d0cc52ea46a5d96120e4771958 100644 (file)
@@ -15,7 +15,9 @@
 
 #include <linux/module.h>
 #include <linux/i2o.h>
+#include <linux/dcache.h>
 #include <linux/namei.h>
+#include <linux/fs.h>
 
 #include <asm/uaccess.h>
 
index c2655a817e3d7099e9ced9a44de5710a8449471e..ff7c50d101802333bf7a9b452ab60212a103cf57 100644 (file)
@@ -18,7 +18,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -800,11 +799,6 @@ static dev_link_t *pcmciamtd_attach(void)
 
        /* Register with Card Services */
        client_reg.dev_info = &dev_info;
-       client_reg.EventMask =
-               CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-               CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-               CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-       client_reg.event_handler = &pcmciamtd_event;
        client_reg.Version = 0x0210;
        client_reg.event_callback_args.client_data = link;
        DEBUG(2, "Calling RegisterClient");
@@ -850,6 +844,7 @@ static struct pcmcia_driver pcmciamtd_driver = {
                .name   = "pcmciamtd"
        },
        .attach         = pcmciamtd_attach,
+       .event          = pcmciamtd_event,
        .detach         = pcmciamtd_detach,
        .owner          = THIS_MODULE,
        .id_table       = pcmciamtd_ids,
index ece1b1a1318632da085d4e0a855bf4c2cb7a5e7f..c27e417f32bf5958e322d4277dc7a808c2777284 100644 (file)
@@ -304,7 +304,7 @@ static inline void scc_discard_buffers(struct scc_channel *scc)
                scc->tx_buff = NULL;
        }
        
-       while (skb_queue_len(&scc->tx_queue))
+       while (!skb_queue_empty(&scc->tx_queue))
                dev_kfree_skb(skb_dequeue(&scc->tx_queue));
 
        spin_unlock_irqrestore(&scc->lock, flags);
@@ -1126,8 +1126,7 @@ static void t_dwait(unsigned long channel)
        
        if (scc->stat.tx_state == TXS_WAIT)     /* maxkeyup or idle timeout */
        {
-               if (skb_queue_len(&scc->tx_queue) == 0) /* nothing to send */
-               {
+               if (skb_queue_empty(&scc->tx_queue)) {  /* nothing to send */
                        scc->stat.tx_state = TXS_IDLE;
                        netif_wake_queue(scc->dev);     /* t_maxkeyup locked it. */
                        return;
index f0fc04bd37c4f6404d8458fb16c07c7b7fd293fd..71fd41122c911f785ded502f1dcd41978ec3699c 100644 (file)
@@ -86,7 +86,6 @@ earlier 3Com products.
 #include <linux/ethtool.h>
 #include <linux/bitops.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -312,11 +311,6 @@ static dev_link_t *tc574_attach(void)
        link->next = dev_list;
        dev_list = link;
        client_reg.dev_info = &dev_info;
-       client_reg.EventMask =
-               CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-                       CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-                               CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-       client_reg.event_handler = &tc574_event;
        client_reg.Version = 0x0210;
        client_reg.event_callback_args.client_data = link;
        ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -1299,6 +1293,7 @@ static struct pcmcia_driver tc574_driver = {
                .name   = "3c574_cs",
        },
        .attach         = tc574_attach,
+       .event          = tc574_event,
        .detach         = tc574_detach,
        .id_table       = tc574_ids,
 };
index 8fa1b5f0fb68a5f82e3d235e819d8c44852dbbbf..d83fdd8c1943411d6c7915fbd80221b74878aef4 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/ioport.h>
 #include <linux/bitops.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -226,11 +225,6 @@ static dev_link_t *tc589_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask =
-       CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-       CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-       CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &tc589_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -1074,6 +1068,7 @@ static struct pcmcia_driver tc589_driver = {
                .name   = "3c589_cs",
        },
        .attach         = tc589_attach,
+       .event          = tc589_event,
        .detach         = tc589_detach,
         .id_table       = tc589_ids,
 };
index 23ce77b1d5b013bda9fb9770e4b2f9847714fc8a..8bb4e85689eac19cf81c6cf63390166be0d0963f 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/netdevice.h>
 #include "../8390.h"
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -181,11 +180,6 @@ static dev_link_t *axnet_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask =
-       CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-       CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-       CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &axnet_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -884,6 +878,7 @@ static struct pcmcia_driver axnet_cs_driver = {
                .name   = "axnet_cs",
        },
        .attach         = axnet_attach,
+       .event          = axnet_event,
        .detach         = axnet_detach,
        .id_table       = axnet_ids,
 };
index 68d58cc58d31d8ee9f9d2aaafe6a2e02a76aeebb..b9355d9498a31140f90820022ff0746e41f987b9 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/arcdevice.h>
 #include <linux/com20020.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -200,11 +199,6 @@ static dev_link_t *com20020_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask =
-        CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-        CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-        CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &com20020_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -495,6 +489,7 @@ static struct pcmcia_driver com20020_cs_driver = {
                .name   = "com20020_cs",
        },
        .attach         = com20020_attach,
+       .event          = com20020_event,
        .detach         = com20020_detach,
        .id_table       = com20020_ids,
 };
index 917adbbf0b5b88e80f39df9242ca450727b4c0f8..9d8197bb293ac74b39c315ca42302d2c9d051300 100644 (file)
@@ -49,7 +49,6 @@
 #include <linux/ioport.h>
 #include <linux/crc32.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -288,11 +287,6 @@ static dev_link_t *fmvj18x_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask =
-       CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-       CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-       CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &fmvj18x_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -797,6 +791,7 @@ static struct pcmcia_driver fmvj18x_cs_driver = {
                .name   = "fmvj18x_cs",
        },
        .attach         = fmvj18x_attach,
+       .event          = fmvj18x_event,
        .detach         = fmvj18x_detach,
        .id_table       = fmvj18x_ids,
 };
index cf6d073ea558df00b4149aa8a9ab3b09a7a77284..b6c140eb97999f34da0013593a6cca88f19f0344 100644 (file)
@@ -57,7 +57,6 @@
 #include <linux/trdevice.h>
 #include <linux/ibmtr.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -190,11 +189,6 @@ static dev_link_t *ibmtr_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask =
-        CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-        CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-        CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &ibmtr_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -521,6 +515,7 @@ static struct pcmcia_driver ibmtr_cs_driver = {
                .name   = "ibmtr_cs",
        },
        .attach         = ibmtr_attach,
+       .event          = ibmtr_event,
        .detach         = ibmtr_detach,
        .id_table       = ibmtr_ids,
 };
index b86e7253fbfce721361b2058287e934429ce4e6c..dbb941004ae9e6d3d14eaf8da86e1b32910b5495 100644 (file)
@@ -146,7 +146,6 @@ Include Files
 #include <linux/ioport.h>
 #include <linux/bitops.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cisreg.h>
@@ -502,11 +501,6 @@ static dev_link_t *nmclan_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask =
-       CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-       CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-       CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &nmclan_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -1688,6 +1682,7 @@ static struct pcmcia_driver nmclan_cs_driver = {
                .name   = "nmclan_cs",
        },
        .attach         = nmclan_attach,
+       .event          = nmclan_event,
        .detach         = nmclan_detach,
        .id_table       = nmclan_ids,
 };
index 855a45d062b19ea77260f1822e5d55984bdaff9b..e1664aef3dfdf5f6c32722c32f7a06f16162e7ed 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/netdevice.h>
 #include <../drivers/net/8390.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -276,11 +275,6 @@ static dev_link_t *pcnet_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask =
-       CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-       CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-       CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &pcnet_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -1844,6 +1838,7 @@ static struct pcmcia_driver pcnet_driver = {
                .name   = "pcnet_cs",
        },
        .attach         = pcnet_attach,
+       .event          = pcnet_event,
        .detach         = pcnet_detach,
        .owner          = THIS_MODULE,
        .id_table       = pcnet_ids,
index bc01c88c67093877d8bd9685ab45de1131fa2096..fbc2f58ff6887a869299492345e4afc5afeb6261 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -370,10 +369,6 @@ static dev_link_t *smc91c92_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-       CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-       CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &smc91c92_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -2365,6 +2360,7 @@ static struct pcmcia_driver smc91c92_cs_driver = {
                .name   = "smc91c92_cs",
        },
        .attach         = smc91c92_attach,
+       .event          = smc91c92_event,
        .detach         = smc91c92_detach,
        .id_table       = smc91c92_ids,
 };
index 0cd225e1595c0d6e5d03ea06395e0c19cacce6f8..9f33bad174e9a31d3a49704da4dcb71e52304af8 100644 (file)
@@ -81,7 +81,6 @@
 #include <linux/ioport.h>
 #include <linux/bitops.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -619,11 +618,6 @@ xirc2ps_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask =
-       CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-       CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-       CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &xirc2ps_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     if ((err = pcmcia_register_client(&link->handle, &client_reg))) {
@@ -2016,6 +2010,7 @@ static struct pcmcia_driver xirc2ps_cs_driver = {
                .name   = "xirc2ps_cs",
        },
        .attach         = xirc2ps_attach,
+       .event          = xirc2ps_event,
        .detach         = xirc2ps_detach,
        .id_table       = xirc2ps_ids,
 };
index 5e48b9ab30455ca661f3c03c6bb128910778d22c..59e8183c639e0be7e9a07dc9c8295d5bd78281e6 100644 (file)
@@ -364,7 +364,7 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,
        spin_lock_irqsave(&ap->recv_lock, flags);
        ppp_async_input(ap, buf, cflags, count);
        spin_unlock_irqrestore(&ap->recv_lock, flags);
-       if (skb_queue_len(&ap->rqueue))
+       if (!skb_queue_empty(&ap->rqueue))
                tasklet_schedule(&ap->tsk);
        ap_put(ap);
        if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
index ab726ab43798811bd28d76c293f4fc3564dff75a..a32668e88e09fc2a157e3ac5500c94ae158c9529 100644 (file)
@@ -1237,8 +1237,8 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
                pch = list_entry(list, struct channel, clist);
                navail += pch->avail = (pch->chan != NULL);
                if (pch->avail) {
-                       if (skb_queue_len(&pch->file.xq) == 0
-                           || !pch->had_frag) {
+                       if (skb_queue_empty(&pch->file.xq) ||
+                           !pch->had_frag) {
                                pch->avail = 2;
                                ++nfree;
                        }
@@ -1374,8 +1374,8 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
 
                /* try to send it down the channel */
                chan = pch->chan;
-               if (skb_queue_len(&pch->file.xq)
-                   || !chan->ops->start_xmit(chan, frag))
+               if (!skb_queue_empty(&pch->file.xq) ||
+                   !chan->ops->start_xmit(chan, frag))
                        skb_queue_tail(&pch->file.xq, frag);
                pch->had_frag = 1;
                p += flen;
@@ -1412,7 +1412,7 @@ ppp_channel_push(struct channel *pch)
 
        spin_lock_bh(&pch->downl);
        if (pch->chan != 0) {
-               while (skb_queue_len(&pch->file.xq) > 0) {
+               while (!skb_queue_empty(&pch->file.xq)) {
                        skb = skb_dequeue(&pch->file.xq);
                        if (!pch->chan->ops->start_xmit(pch->chan, skb)) {
                                /* put the packet back and try again later */
@@ -1426,7 +1426,7 @@ ppp_channel_push(struct channel *pch)
        }
        spin_unlock_bh(&pch->downl);
        /* see if there is anything from the attached unit to be sent */
-       if (skb_queue_len(&pch->file.xq) == 0) {
+       if (skb_queue_empty(&pch->file.xq)) {
                read_lock_bh(&pch->upl);
                ppp = pch->ppp;
                if (ppp != 0)
index fd9f50180355b79bef8ae07a7fe44b68621a59f5..4d51c0c8023d160b5d82c3d09e37e440fe0e16bf 100644 (file)
@@ -406,7 +406,7 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
        spin_lock_irqsave(&ap->recv_lock, flags);
        ppp_sync_input(ap, buf, cflags, count);
        spin_unlock_irqrestore(&ap->recv_lock, flags);
-       if (skb_queue_len(&ap->rqueue))
+       if (!skb_queue_empty(&ap->rqueue))
                tasklet_schedule(&ap->tsk);
        sp_put(ap);
        if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
index 3dbb1cb09ed823d99c669a409f17f0b42570059b..5cacc7ad9e79a9f8505b7dbb34a59604293b4601 100644 (file)
@@ -3259,7 +3259,7 @@ static void __devexit skge_remove(struct pci_dev *pdev)
 }
 
 #ifdef CONFIG_PM
-static int skge_suspend(struct pci_dev *pdev, u32 state)
+static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct skge_hw *hw  = pci_get_drvdata(pdev);
        int i, wol = 0;
@@ -3279,7 +3279,7 @@ static int skge_suspend(struct pci_dev *pdev, u32 state)
        }
 
        pci_save_state(pdev);
-       pci_enable_wake(pdev, state, wol);
+       pci_enable_wake(pdev, pci_choose_state(pdev, state), wol);
        pci_disable_device(pdev);
        pci_set_power_state(pdev, pci_choose_state(pdev, state));
 
index 1f5655655c40185091146461789f0a08ab7c5282..2608e7a3d214b280d8d1ec12a265612a477bd14a 100644 (file)
@@ -3079,7 +3079,9 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
        gp->phy_mii.dev = dev;
        gp->phy_mii.mdio_read = _phy_read;
        gp->phy_mii.mdio_write = _phy_write;
-
+#ifdef CONFIG_PPC_PMAC
+       gp->phy_mii.platform_data = gp->of_node;
+#endif
        /* By default, we start with autoneg */
        gp->want_autoneg = 1;
 
index 0fca414d3657f63bbb24fc89de9a8330eb1121d7..d3ddb41d6e5c7c361c7e141034693166619983d0 100644 (file)
 #include <linux/ethtool.h>
 #include <linux/delay.h>
 
+#ifdef CONFIG_PPC_PMAC
+#include <asm/prom.h>
+#endif
+
 #include "sungem_phy.h"
 
 /* Link modes of the BCM5400 PHY */
@@ -281,10 +285,12 @@ static int bcm5411_suspend(struct mii_phy* phy)
 static int bcm5421_init(struct mii_phy* phy)
 {
        u16 data;
-       int rev;
+       unsigned int id;
 
-       rev = phy_read(phy, MII_PHYSID2) & 0x000f;
-       if (rev == 0) {
+       id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
+
+       /* Revision 0 of 5421 needs some fixups */
+       if (id == 0x002060e0) {
                /* This is borrowed from MacOS
                 */
                phy_write(phy, 0x18, 0x1007);
@@ -297,21 +303,28 @@ static int bcm5421_init(struct mii_phy* phy)
                data = phy_read(phy, 0x15);
                phy_write(phy, 0x15, data | 0x0200);
        }
-#if 0
-       /* This has to be verified before I enable it */
-       /* Enable automatic low-power */
-       phy_write(phy, 0x1c, 0x9002);
-       phy_write(phy, 0x1c, 0xa821);
-       phy_write(phy, 0x1c, 0x941d);
-#endif
-       return 0;
-}
 
-static int bcm5421k2_init(struct mii_phy* phy)
-{
-       /* Init code borrowed from OF */
-       phy_write(phy, 4, 0x01e1);
-       phy_write(phy, 9, 0x0300);
+       /* Pick up some init code from OF for K2 version */
+       if ((id & 0xfffffff0) == 0x002062e0) {
+               phy_write(phy, 4, 0x01e1);
+               phy_write(phy, 9, 0x0300);
+       }
+
+       /* Check if we can enable automatic low power */
+#ifdef CONFIG_PPC_PMAC
+       if (phy->platform_data) {
+               struct device_node *np = of_get_parent(phy->platform_data);
+               int can_low_power = 1;
+               if (np == NULL || get_property(np, "no-autolowpower", NULL))
+                       can_low_power = 0;
+               if (can_low_power) {
+                       /* Enable automatic low-power */
+                       phy_write(phy, 0x1c, 0x9002);
+                       phy_write(phy, 0x1c, 0xa821);
+                       phy_write(phy, 0x1c, 0x941d);
+               }
+       }
+#endif /* CONFIG_PPC_PMAC */
 
        return 0;
 }
@@ -762,7 +775,7 @@ static struct mii_phy_def bcm5421_phy_def = {
 
 /* Broadcom BCM 5421 built-in K2 */
 static struct mii_phy_ops bcm5421k2_phy_ops = {
-       .init           = bcm5421k2_init,
+       .init           = bcm5421_init,
        .suspend        = bcm5411_suspend,
        .setup_aneg     = bcm54xx_setup_aneg,
        .setup_forced   = bcm54xx_setup_forced,
@@ -779,6 +792,25 @@ static struct mii_phy_def bcm5421k2_phy_def = {
        .ops            = &bcm5421k2_phy_ops
 };
 
+/* Broadcom BCM 5462 built-in Vesta */
+static struct mii_phy_ops bcm5462V_phy_ops = {
+       .init           = bcm5421_init,
+       .suspend        = bcm5411_suspend,
+       .setup_aneg     = bcm54xx_setup_aneg,
+       .setup_forced   = bcm54xx_setup_forced,
+       .poll_link      = genmii_poll_link,
+       .read_link      = bcm54xx_read_link,
+};
+
+static struct mii_phy_def bcm5462V_phy_def = {
+       .phy_id         = 0x002060d0,
+       .phy_id_mask    = 0xfffffff0,
+       .name           = "BCM5462-Vesta",
+       .features       = MII_GBIT_FEATURES,
+       .magic_aneg     = 1,
+       .ops            = &bcm5462V_phy_ops
+};
+
 /* Marvell 88E1101 (Apple seem to deal with 2 different revs,
  * I masked out the 8 last bits to get both, but some specs
  * would be useful here) --BenH.
@@ -824,6 +856,7 @@ static struct mii_phy_def* mii_phy_table[] = {
        &bcm5411_phy_def,
        &bcm5421_phy_def,
        &bcm5421k2_phy_def,
+       &bcm5462V_phy_def,
        &marvell_phy_def,
        &genmii_phy_def,
        NULL
index 822cb58174ea2235597e7e784a931b2b290e0d32..430544496c52689502f0e1991a1e17d6e11cd797 100644 (file)
@@ -43,9 +43,10 @@ struct mii_phy
        int                     pause;
 
        /* Provided by host chip */
-       struct net_device*      dev;
+       struct net_device       *dev;
        int (*mdio_read) (struct net_device *dev, int mii_id, int reg);
        void (*mdio_write) (struct net_device *dev, int mii_id, int reg, int val);
+       void                    *platform_data;
 };
 
 /* Pass in a struct mii_phy with dev, mdio_read and mdio_write
index 7bfee366297b655dd76c3d3387835775321e87a7..effab0b9adca176b6b6a3b9fd553b256d9f1c850 100644 (file)
@@ -215,7 +215,7 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
 
        poll_wait(file, &tun->read_wait, wait);
  
-       if (skb_queue_len(&tun->readq))
+       if (!skb_queue_empty(&tun->readq))
                mask |= POLLIN | POLLRDNORM;
 
        return mask;
index 0b5ca25379634cc9e49f8ca63c3132151e7a531b..ecfa6f8805ce0ef050448e777e68364b7d50a32e 100644 (file)
@@ -1906,9 +1906,9 @@ typhoon_sleep(struct typhoon *tp, pci_power_t state, u16 events)
         */
        netif_carrier_off(tp->dev);
 
-       pci_enable_wake(tp->pdev, pci_choose_state(pdev, state), 1);
+       pci_enable_wake(tp->pdev, state, 1);
        pci_disable_device(pdev);
-       return pci_set_power_state(pdev, pci_choose_state(pdev, state));
+       return pci_set_power_state(pdev, state);
 }
 
 static int
@@ -2274,7 +2274,7 @@ typhoon_suspend(struct pci_dev *pdev, pm_message_t state)
                goto need_resume;
        }
 
-       if(typhoon_sleep(tp, state, tp->wol_events) < 0) {
+       if(typhoon_sleep(tp, pci_choose_state(pdev, state), tp->wol_events) < 0) {
                printk(KERN_ERR "%s: unable to put card to sleep\n", dev->name);
                goto need_resume;
        }
index c12648d8192b7dd7df2ffbbe7bbb68ccd87a30cb..47f3c5d0203da70e394d82509ab69fdea3c06cfa 100644 (file)
@@ -2374,7 +2374,7 @@ void stop_airo_card( struct net_device *dev, int freeres )
        /*
         * Clean out tx queue
         */
-       if (test_bit(FLAG_MPI, &ai->flags) && skb_queue_len (&ai->txq) > 0) {
+       if (test_bit(FLAG_MPI, &ai->flags) && !skb_queue_empty(&ai->txq)) {
                struct sk_buff *skb = NULL;
                for (;(skb = skb_dequeue(&ai->txq));)
                        dev_kfree_skb(skb);
@@ -3287,7 +3287,7 @@ exitrx:
                                if (status & EV_TXEXC)
                                        get_tx_error(apriv, -1);
                                spin_lock_irqsave(&apriv->aux_lock, flags);
-                               if (skb_queue_len (&apriv->txq)) {
+                               if (!skb_queue_empty(&apriv->txq)) {
                                        spin_unlock_irqrestore(&apriv->aux_lock,flags);
                                        mpi_send_packet (dev);
                                } else {
index f10a9523034a650c9a43c9b2c330e89478db449d..bf25584d68d3d7f9fd00dc5e64b58d77c72e10bb 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/timer.h>
 #include <linux/netdevice.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -210,11 +209,6 @@ static dev_link_t *airo_attach(void)
        link->next = dev_list;
        dev_list = link;
        client_reg.dev_info = &dev_info;
-       client_reg.EventMask =
-               CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-               CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-               CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-       client_reg.event_handler = &airo_event;
        client_reg.Version = 0x0210;
        client_reg.event_callback_args.client_data = link;
        ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -574,6 +568,7 @@ static struct pcmcia_driver airo_driver = {
                .name   = "airo_cs",
        },
        .attach         = airo_attach,
+       .event          = airo_event,
        .detach         = airo_detach,
        .id_table       = airo_ids,
 };
index 86379d4998ac7930d47afe98b7288eb09f938ba8..ff031a3985b32310a82f72bccdd6bcf97776572c 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/moduleparam.h>
 #include <linux/device.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -218,11 +217,6 @@ static dev_link_t *atmel_attach(void)
        link->next = dev_list;
        dev_list = link;
        client_reg.dev_info = &dev_info;
-       client_reg.EventMask =
-               CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-               CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-               CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-       client_reg.event_handler = &atmel_event;
        client_reg.Version = 0x0210;
        client_reg.event_callback_args.client_data = link;
        ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -668,12 +662,13 @@ static struct pcmcia_device_id atmel_ids[] = {
 MODULE_DEVICE_TABLE(pcmcia, atmel_ids);
 
 static struct pcmcia_driver atmel_driver = {
-        .owner          = THIS_MODULE,
-        .drv            = {
-                .name   = "atmel_cs",
+       .owner          = THIS_MODULE,
+       .drv            = {
+               .name   = "atmel_cs",
         },
-        .attach         = atmel_attach,
-        .detach         = atmel_detach,
+       .attach         = atmel_attach,
+       .event          = atmel_event,
+       .detach         = atmel_detach,
        .id_table       = atmel_ids,
 };
 
index e12bd75b269493de8fe19f800202ec42a0d96c1e..5f507c49907b34c80b466374aa42180c6541a101 100644 (file)
@@ -62,7 +62,6 @@
 #endif /* WIRELESS_EXT > 12 */
 #endif
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -491,11 +490,6 @@ static dev_link_t *netwave_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask =
-       CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-       CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-       CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &netwave_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -1680,6 +1674,7 @@ static struct pcmcia_driver netwave_driver = {
                .name   = "netwave_cs",
        },
        .attach         = netwave_attach,
+       .event          = netwave_event,
        .detach         = netwave_detach,
        .id_table       = netwave_ids,
 };
index 597c4586d04931e212eb06cb550928a94a6393ae..368d2f962f670e2ff6f231a44305bcc259d58106 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/etherdevice.h>
 #include <linux/wireless.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -186,11 +185,6 @@ orinoco_cs_attach(void)
        dev_list = link;
 
        client_reg.dev_info = &dev_info;
-       client_reg.EventMask =
-               CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-               CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-               CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-       client_reg.event_handler = &orinoco_cs_event;
        client_reg.Version = 0x0210; /* FIXME: what does this mean? */
        client_reg.event_callback_args.client_data = link;
 
@@ -664,6 +658,7 @@ static struct pcmcia_driver orinoco_driver = {
                .name   = DRIVER_NAME,
        },
        .attach         = orinoco_cs_attach,
+       .event          = orinoco_cs_event,
        .detach         = orinoco_cs_detach,
        .id_table       = orinoco_cs_ids,
 };
index 31652af52eac240dd093d62a3e2be025a4f39453..0e0ba614259af78415767017af7e3e65c5890946 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/skbuff.h>
 #include <linux/ethtool.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -393,11 +392,6 @@ static dev_link_t *ray_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask =
-        CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-        CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-        CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &ray_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
 
@@ -2916,6 +2910,7 @@ static struct pcmcia_driver ray_driver = {
                .name   = "ray_cs",
        },
        .attach         = ray_attach,
+       .event          = ray_event,
        .detach         = ray_detach,
        .id_table       = ray_ids,
 };
index 89532fd929415bd5226b6ffdb2770ff606887f30..f6130a53b7966fe7f9ba5d267b120c9b4f08eff5 100644 (file)
@@ -4684,12 +4684,6 @@ wavelan_attach(void)
 
   /* Register with Card Services */
   client_reg.dev_info = &dev_info;
-  client_reg.EventMask = 
-    CS_EVENT_REGISTRATION_COMPLETE |
-    CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-    CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-    CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-  client_reg.event_handler = &wavelan_event;
   client_reg.Version = 0x0210;
   client_reg.event_callback_args.client_data = link;
 
@@ -4904,6 +4898,7 @@ static struct pcmcia_driver wavelan_driver = {
                .name   = "wavelan_cs",
        },
        .attach         = wavelan_attach,
+       .event          = wavelan_event,
        .detach         = wavelan_detach,
        .id_table       = wavelan_ids,
 };
index ea2ef8dddb9248e98e523821ae84fc38709f4957..677ff71883cb826a1e81eafdc4b8d9e9befabfad 100644 (file)
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
-#include <pcmcia/version.h>
 
 /* Wavelan declarations */
 #include "i82593.h"    /* Definitions for the Intel chip */
index e3a900482d920521db9356fb1251e57d59db0c83..dd902126d0183aec8f5439a834e4d8ba51b3b3cd 100644 (file)
@@ -49,7 +49,6 @@
 
 #include <net/iw_handler.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -2005,13 +2004,6 @@ static dev_link_t *wl3501_attach(void)
        link->next               = wl3501_dev_list;
        wl3501_dev_list          = link;
        client_reg.dev_info      = &wl3501_dev_info;
-       client_reg.EventMask     = CS_EVENT_CARD_INSERTION |
-                                  CS_EVENT_RESET_PHYSICAL |
-                                  CS_EVENT_CARD_RESET |
-                                  CS_EVENT_CARD_REMOVAL |
-                                  CS_EVENT_PM_SUSPEND |
-                                  CS_EVENT_PM_RESUME;
-       client_reg.event_handler = wl3501_event;
        client_reg.Version       = 0x0210;
        client_reg.event_callback_args.client_data = link;
        ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -2246,12 +2238,13 @@ static struct pcmcia_device_id wl3501_ids[] = {
 MODULE_DEVICE_TABLE(pcmcia, wl3501_ids);
 
 static struct pcmcia_driver wl3501_driver = {
-       .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "wl3501_cs",
+       .owner          = THIS_MODULE,
+       .drv            = {
+               .name   = "wl3501_cs",
        },
-       .attach         = wl3501_attach,
-       .detach         = wl3501_detach,
+       .attach         = wl3501_attach,
+       .event          = wl3501_event,
+       .detach         = wl3501_detach,
        .id_table       = wl3501_ids,
 };
 
index ff45662c4f7cb412f430e844de86094328413d14..24e6aacddb74bb0ddaa41fce893c15bb3dd03075 100644 (file)
@@ -48,7 +48,6 @@
 #include <linux/parport.h>
 #include <linux/parport_pc.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -133,11 +132,6 @@ static dev_link_t *parport_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.EventMask =
-       CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-       CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-       CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-    client_reg.event_handler = &parport_event;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -386,6 +380,7 @@ static struct pcmcia_driver parport_cs_driver = {
                .name   = "parport_cs",
        },
        .attach         = parport_attach,
+       .event          = parport_event,
        .detach         = parport_detach,
        .id_table       = parport_ids,
 
index 1a4d4ca2a4dc386d3f63189ecc9cf30f806b947e..9c4a39ee89b57b5065f575b86b2798ed31dc2fc6 100644 (file)
@@ -187,9 +187,10 @@ config HOTPLUG_PCI_RPA_DLPAR
 
 config HOTPLUG_PCI_SGI
        tristate "SGI PCI Hotplug Support"
-       depends on HOTPLUG_PCI && IA64_SGI_SN2
+       depends on HOTPLUG_PCI && (IA64_SGI_SN2 || IA64_GENERIC)
        help
-         Say Y here if you have an SGI IA64 Altix system.
+         Say Y here if you want to use the SGI Altix Hotplug
+         Driver for PCI devices.
 
          When in doubt, say N.
 
index 3e632ff8c717116d0dca075a6ec969e2b1acf31f..31a307004b94404377dd15ab5dab210831d6b63b 100644 (file)
@@ -14,6 +14,7 @@ obj-$(CONFIG_HOTPLUG_PCI_PCIE)                += pciehp.o
 obj-$(CONFIG_HOTPLUG_PCI_SHPC)         += shpchp.o
 obj-$(CONFIG_HOTPLUG_PCI_RPA)          += rpaphp.o
 obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR)    += rpadlpar_io.o
+obj-$(CONFIG_HOTPLUG_PCI_SGI)          += sgi_hotplug.o
 
 pci_hotplug-objs       :=      pci_hotplug_core.o
 
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
new file mode 100644 (file)
index 0000000..323041f
--- /dev/null
@@ -0,0 +1,611 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 Silicon Graphics, Inc. All rights reserved.
+ *
+ * This work was based on the 2.4/2.6 kernel development by Dick Reigner.
+ * Work to add BIOS PROM support was completed by Mike Habeck.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/types.h>
+
+#include <asm/sn/addrs.h>
+#include <asm/sn/l1.h>
+#include <asm/sn/module.h>
+#include <asm/sn/pcibr_provider.h>
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/types.h>
+
+#include "../pci.h"
+#include "pci_hotplug.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)");
+MODULE_DESCRIPTION("SGI Altix Hot Plug PCI Controller Driver");
+
+#define PCIIO_ASIC_TYPE_TIOCA     4
+#define PCI_SLOT_ALREADY_UP       2     /* slot already up */
+#define PCI_SLOT_ALREADY_DOWN     3     /* slot already down */
+#define PCI_L1_ERR                7     /* L1 console command error */
+#define PCI_EMPTY_33MHZ          15     /* empty 33 MHz bus */
+#define PCI_L1_QSIZE            128     /* our L1 message buffer size */
+#define SN_MAX_HP_SLOTS                 32     /* max number of hotplug slots */
+#define SGI_HOTPLUG_PROM_REV   0x0420  /* Min. required PROM version */
+
+/* internal list head */
+static struct list_head sn_hp_list;
+
+/* hotplug_slot struct's private pointer */
+struct slot {
+       int device_num;
+       struct pci_bus *pci_bus;
+       /* this struct for glue internal only */
+       struct hotplug_slot *hotplug_slot;
+       struct list_head hp_list;
+};
+
+struct pcibr_slot_enable_resp {
+       int resp_sub_errno;
+       char resp_l1_msg[PCI_L1_QSIZE + 1];
+};
+
+struct pcibr_slot_disable_resp {
+       int resp_sub_errno;
+       char resp_l1_msg[PCI_L1_QSIZE + 1];
+};
+
+enum sn_pci_req_e {
+       PCI_REQ_SLOT_ELIGIBLE,
+       PCI_REQ_SLOT_DISABLE
+};
+
+static int enable_slot(struct hotplug_slot *slot);
+static int disable_slot(struct hotplug_slot *slot);
+static int get_power_status(struct hotplug_slot *slot, u8 *value);
+
+static struct hotplug_slot_ops sn_hotplug_slot_ops = {
+       .owner                  = THIS_MODULE,
+       .enable_slot            = enable_slot,
+       .disable_slot           = disable_slot,
+       .get_power_status       = get_power_status,
+};
+
+static DECLARE_MUTEX(sn_hotplug_sem);
+
+static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
+{
+       struct pcibus_info *pcibus_info;
+       int bricktype;
+       int bus_num;
+
+       pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
+
+       /* Check to see if this is a valid slot on 'pci_bus' */
+       if (!(pcibus_info->pbi_valid_devices & (1 << device)))
+               return -EPERM;
+
+       bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
+       bus_num = pcibus_info->pbi_buscommon.bs_persist_busnum & 0xf;
+
+       /* Do not allow hotplug operations on base I/O cards */
+       if ((bricktype == L1_BRICKTYPE_IX ||  bricktype == L1_BRICKTYPE_IA) &&
+           (bus_num == 1 && device != 1))
+               return -EPERM;
+
+       return 1;
+}
+
+static int sn_pci_bus_valid(struct pci_bus *pci_bus)
+{
+       struct pcibus_info *pcibus_info;
+       int asic_type;
+       int bricktype;
+
+       pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
+
+       /* Don't register slots hanging off the TIOCA bus */
+       asic_type = pcibus_info->pbi_buscommon.bs_asic_type;
+       if (asic_type == PCIIO_ASIC_TYPE_TIOCA)
+               return -EPERM;
+
+       /* Only register slots in I/O Bricks that support hotplug */
+       bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
+       switch (bricktype) {
+       case L1_BRICKTYPE_IX:
+       case L1_BRICKTYPE_PX:
+       case L1_BRICKTYPE_IA:
+       case L1_BRICKTYPE_PA:
+               return 1;
+               break;
+       default:
+               return -EPERM;
+               break;
+       }
+
+       return -EIO;
+}
+
+static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
+                                   struct pci_bus *pci_bus, int device)
+{
+       struct pcibus_info *pcibus_info;
+       struct slot *slot;
+
+       pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
+
+       bss_hotplug_slot->private = kcalloc(1, sizeof(struct slot),
+                                           GFP_KERNEL);
+       if (!bss_hotplug_slot->private)
+               return -ENOMEM;
+       slot = (struct slot *)bss_hotplug_slot->private;
+
+       bss_hotplug_slot->name = kmalloc(33, GFP_KERNEL);
+       if (!bss_hotplug_slot->name) {
+               kfree(bss_hotplug_slot->private);
+               return -ENOMEM;
+       }
+
+       slot->device_num = device;
+       slot->pci_bus = pci_bus;
+
+       sprintf(bss_hotplug_slot->name, "module_%c%c%c%c%.2d_b_%d_s_%d",
+               '0'+RACK_GET_CLASS(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
+               '0'+RACK_GET_GROUP(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
+               '0'+RACK_GET_NUM(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
+               MODULE_GET_BTCHAR(pcibus_info->pbi_moduleid),
+               MODULE_GET_BPOS(pcibus_info->pbi_moduleid),
+               ((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf,
+               device + 1);
+
+       slot->hotplug_slot = bss_hotplug_slot;
+       list_add(&slot->hp_list, &sn_hp_list);
+
+       return 0;
+}
+
+static struct hotplug_slot * sn_hp_destroy(void)
+{
+       struct slot *slot;
+       struct list_head *list;
+       struct hotplug_slot *bss_hotplug_slot = NULL;
+
+       list_for_each(list, &sn_hp_list) {
+               slot = list_entry(list, struct slot, hp_list);
+               bss_hotplug_slot = slot->hotplug_slot;
+               list_del(&((struct slot *)bss_hotplug_slot->private)->
+                        hp_list);
+               break;
+       }
+       return bss_hotplug_slot;
+}
+
+static void sn_bus_alloc_data(struct pci_dev *dev)
+{
+       struct list_head *node;
+       struct pci_bus *subordinate_bus;
+       struct pci_dev *child;
+
+       sn_pci_fixup_slot(dev);
+
+       /* Recursively sets up the sn_irq_info structs */
+       if (dev->subordinate) {
+               subordinate_bus = dev->subordinate;
+               list_for_each(node, &subordinate_bus->devices) {
+                       child = list_entry(node, struct pci_dev, bus_list);
+                       sn_bus_alloc_data(child);
+               }
+       }
+}
+
+static void sn_bus_free_data(struct pci_dev *dev)
+{
+       struct list_head *node;
+       struct pci_bus *subordinate_bus;
+       struct pci_dev *child;
+
+       /* Recursively clean up sn_irq_info structs */
+       if (dev->subordinate) {
+               subordinate_bus = dev->subordinate;
+               list_for_each(node, &subordinate_bus->devices) {
+                       child = list_entry(node, struct pci_dev, bus_list);
+                       sn_bus_free_data(child);
+               }
+       }
+       sn_pci_unfixup_slot(dev);
+}
+
+static u8 sn_power_status_get(struct hotplug_slot *bss_hotplug_slot)
+{
+       struct slot *slot = (struct slot *)bss_hotplug_slot->private;
+       struct pcibus_info *pcibus_info;
+       u8 retval;
+
+       pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
+       retval = pcibus_info->pbi_enabled_devices & (1 << slot->device_num);
+
+       return retval ? 1 : 0;
+}
+
+static void sn_slot_mark_enable(struct hotplug_slot *bss_hotplug_slot,
+                               int device_num)
+{
+       struct slot *slot = (struct slot *)bss_hotplug_slot->private;
+       struct pcibus_info *pcibus_info;
+
+       pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
+       pcibus_info->pbi_enabled_devices |= (1 << device_num);
+}
+
+static void sn_slot_mark_disable(struct hotplug_slot *bss_hotplug_slot,
+                                int device_num)
+{
+       struct slot *slot = (struct slot *)bss_hotplug_slot->private;
+       struct pcibus_info *pcibus_info;
+
+       pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
+       pcibus_info->pbi_enabled_devices &= ~(1 << device_num);
+}
+
+static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,
+                         int device_num)
+{
+       struct slot *slot = (struct slot *)bss_hotplug_slot->private;
+       struct pcibus_info *pcibus_info;
+       struct pcibr_slot_enable_resp resp;
+       int rc;
+
+       pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
+
+       /*
+        * Power-on and initialize the slot in the SN
+        * PCI infrastructure.
+        */
+       rc = sal_pcibr_slot_enable(pcibus_info, device_num, &resp);
+
+       if (rc == PCI_SLOT_ALREADY_UP) {
+               dev_dbg(slot->pci_bus->self, "is already active\n");
+               return -EPERM;
+       }
+
+       if (rc == PCI_L1_ERR) {
+               dev_dbg(slot->pci_bus->self,
+                       "L1 failure %d with message: %s",
+                       resp.resp_sub_errno, resp.resp_l1_msg);
+               return -EPERM;
+       }
+
+       if (rc) {
+               dev_dbg(slot->pci_bus->self,
+                       "insert failed with error %d sub-error %d\n",
+                       rc, resp.resp_sub_errno);
+               return -EIO;
+       }
+
+       sn_slot_mark_enable(bss_hotplug_slot, device_num);
+
+       return 0;
+}
+
+static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot,
+                          int device_num, int action)
+{
+       struct slot *slot = (struct slot *)bss_hotplug_slot->private;
+       struct pcibus_info *pcibus_info;
+       struct pcibr_slot_disable_resp resp;
+       int rc;
+
+       pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
+
+       rc = sal_pcibr_slot_disable(pcibus_info, device_num, action, &resp);
+
+       if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_SLOT_ALREADY_DOWN) {
+               dev_dbg(slot->pci_bus->self, "Slot %s already inactive\n");
+               return -ENODEV;
+       }
+
+       if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_EMPTY_33MHZ) {
+               dev_dbg(slot->pci_bus->self,
+                       "Cannot remove last 33MHz card\n");
+               return -EPERM;
+       }
+
+       if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_L1_ERR) {
+               dev_dbg(slot->pci_bus->self,
+                       "L1 failure %d with message \n%s\n",
+                       resp.resp_sub_errno, resp.resp_l1_msg);
+               return -EPERM;
+       }
+
+       if (action == PCI_REQ_SLOT_ELIGIBLE && rc) {
+               dev_dbg(slot->pci_bus->self,
+                       "remove failed with error %d sub-error %d\n",
+                       rc, resp.resp_sub_errno);
+               return -EIO;
+       }
+
+       if (action == PCI_REQ_SLOT_ELIGIBLE && !rc)
+               return 0;
+
+       if (action == PCI_REQ_SLOT_DISABLE && !rc) {
+               sn_slot_mark_disable(bss_hotplug_slot, device_num);
+               dev_dbg(slot->pci_bus->self, "remove successful\n");
+               return 0;
+       }
+
+       if (action == PCI_REQ_SLOT_DISABLE && rc) {
+               dev_dbg(slot->pci_bus->self,"remove failed rc = %d\n", rc);
+               return rc;
+       }
+
+       return rc;
+}
+
+static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
+{
+       struct slot *slot = (struct slot *)bss_hotplug_slot->private;
+       struct pci_bus *new_bus = NULL;
+       struct pci_dev *dev;
+       int func, num_funcs;
+       int new_ppb = 0;
+       int rc;
+
+       /* Serialize the Linux PCI infrastructure */
+       down(&sn_hotplug_sem);
+
+       /*
+        * Power-on and initialize the slot in the SN
+        * PCI infrastructure.
+        */
+       rc = sn_slot_enable(bss_hotplug_slot, slot->device_num);
+       if (rc) {
+               up(&sn_hotplug_sem);
+               return rc;
+       }
+
+       num_funcs = pci_scan_slot(slot->pci_bus, PCI_DEVFN(slot->device_num+1,
+                                                          PCI_FUNC(0)));
+       if (!num_funcs) {
+               dev_dbg(slot->pci_bus->self, "no device in slot\n");
+               up(&sn_hotplug_sem);
+               return -ENODEV;
+       }
+
+       sn_pci_controller_fixup(pci_domain_nr(slot->pci_bus),
+                               slot->pci_bus->number,
+                               slot->pci_bus);
+       /*
+        * Map SN resources for all functions on the card
+        * to the Linux PCI interface and tell the drivers
+        * about them.
+        */
+       for (func = 0; func < num_funcs;  func++) {
+               dev = pci_get_slot(slot->pci_bus,
+                                  PCI_DEVFN(slot->device_num + 1,
+                                            PCI_FUNC(func)));
+
+
+               if (dev) {
+                       if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+                               unsigned char sec_bus;
+                               pci_read_config_byte(dev, PCI_SECONDARY_BUS,
+                                                    &sec_bus);
+                               new_bus = pci_add_new_bus(dev->bus, dev,
+                                                         sec_bus);
+                               pci_scan_child_bus(new_bus);
+                               sn_pci_controller_fixup(pci_domain_nr(new_bus),
+                                                       new_bus->number,
+                                                       new_bus);
+                               new_ppb = 1;
+                       }
+                       sn_bus_alloc_data(dev);
+                       pci_dev_put(dev);
+               }
+       }
+
+       /* Call the driver for the new device */
+       pci_bus_add_devices(slot->pci_bus);
+       /* Call the drivers for the new devices subordinate to PPB */
+       if (new_ppb)
+               pci_bus_add_devices(new_bus);
+
+       up(&sn_hotplug_sem);
+
+       if (rc == 0)
+               dev_dbg(slot->pci_bus->self,
+                       "insert operation successful\n");
+       else
+               dev_dbg(slot->pci_bus->self,
+                       "insert operation failed rc = %d\n", rc);
+
+       return rc;
+}
+
+static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
+{
+       struct slot *slot = (struct slot *)bss_hotplug_slot->private;
+       struct pci_dev *dev;
+       int func;
+       int rc;
+
+       /* Acquire update access to the bus */
+       down(&sn_hotplug_sem);
+
+       /* is it okay to bring this slot down? */
+       rc = sn_slot_disable(bss_hotplug_slot, slot->device_num,
+                            PCI_REQ_SLOT_ELIGIBLE);
+       if (rc)
+               goto leaving;
+
+       /* Free the SN resources assigned to the Linux device.*/
+       for (func = 0; func < 8;  func++) {
+               dev = pci_get_slot(slot->pci_bus,
+                                  PCI_DEVFN(slot->device_num+1,
+                                            PCI_FUNC(func)));
+               if (dev) {
+                       /*
+                        * Some drivers may use dma accesses during the
+                        * driver remove function. We release the sysdata
+                        * areas after the driver remove functions have
+                        * been called.
+                        */
+                       sn_bus_store_sysdata(dev);
+                       sn_bus_free_data(dev);
+                       pci_remove_bus_device(dev);
+                       pci_dev_put(dev);
+               }
+       }
+
+       /* free the collected sysdata pointers */
+       sn_bus_free_sysdata();
+
+       /* Deactivate slot */
+       rc = sn_slot_disable(bss_hotplug_slot, slot->device_num,
+                            PCI_REQ_SLOT_DISABLE);
+ leaving:
+       /* Release the bus lock */
+       up(&sn_hotplug_sem);
+
+       return rc;
+}
+
+static int get_power_status(struct hotplug_slot *bss_hotplug_slot, u8 *value)
+{
+       down(&sn_hotplug_sem);
+       *value = sn_power_status_get(bss_hotplug_slot);
+       up(&sn_hotplug_sem);
+       return 0;
+}
+
+static void sn_release_slot(struct hotplug_slot *bss_hotplug_slot)
+{
+       kfree(bss_hotplug_slot->info);
+       kfree(bss_hotplug_slot->name);
+       kfree(bss_hotplug_slot->private);
+       kfree(bss_hotplug_slot);
+}
+
+static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
+{
+       int device;
+       struct hotplug_slot *bss_hotplug_slot;
+       int rc = 0;
+
+       /*
+        * Currently only four devices are supported,
+        * in the future there maybe more -- up to 32.
+        */
+
+       for (device = 0; device < SN_MAX_HP_SLOTS ; device++) {
+               if (sn_pci_slot_valid(pci_bus, device) != 1)
+                       continue;
+
+               bss_hotplug_slot = kcalloc(1,sizeof(struct hotplug_slot),
+                                          GFP_KERNEL);
+               if (!bss_hotplug_slot) {
+                       rc = -ENOMEM;
+                       goto alloc_err;
+               }
+
+               bss_hotplug_slot->info =
+                       kcalloc(1,sizeof(struct hotplug_slot_info),
+                               GFP_KERNEL);
+               if (!bss_hotplug_slot->info) {
+                       rc = -ENOMEM;
+                       goto alloc_err;
+               }
+
+               if (sn_hp_slot_private_alloc(bss_hotplug_slot,
+                                            pci_bus, device)) {
+                       rc = -ENOMEM;
+                       goto alloc_err;
+               }
+
+               bss_hotplug_slot->ops = &sn_hotplug_slot_ops;
+               bss_hotplug_slot->release = &sn_release_slot;
+
+               rc = pci_hp_register(bss_hotplug_slot);
+               if (rc)
+                       goto register_err;
+       }
+       dev_dbg(pci_bus->self, "Registered bus with hotplug\n");
+       return rc;
+
+register_err:
+       dev_dbg(pci_bus->self, "bus failed to register with err = %d\n",
+               rc);
+
+alloc_err:
+       if (rc == -ENOMEM)
+               dev_dbg(pci_bus->self, "Memory allocation error\n");
+
+       /* destroy THIS element */
+       if (bss_hotplug_slot)
+               sn_release_slot(bss_hotplug_slot);
+
+       /* destroy anything else on the list */
+       while ((bss_hotplug_slot = sn_hp_destroy()))
+               pci_hp_deregister(bss_hotplug_slot);
+
+       return rc;
+}
+
+static int sn_pci_hotplug_init(void)
+{
+       struct pci_bus *pci_bus = NULL;
+       int rc;
+       int registered = 0;
+
+       INIT_LIST_HEAD(&sn_hp_list);
+
+       if (sn_sal_rev() < SGI_HOTPLUG_PROM_REV) {
+               printk(KERN_ERR "%s: PROM version must be greater than 4.05\n",
+                      __FUNCTION__);
+               return -EPERM;
+       }
+
+       while ((pci_bus = pci_find_next_bus(pci_bus))) {
+               if (!pci_bus->sysdata)
+                       continue;
+
+               rc = sn_pci_bus_valid(pci_bus);
+               if (rc != 1) {
+                       dev_dbg(pci_bus->self, "not a valid hotplug bus\n");
+                       continue;
+               }
+               dev_dbg(pci_bus->self, "valid hotplug bus\n");
+
+               rc = sn_hotplug_slot_register(pci_bus);
+               if (!rc)
+                       registered = 1;
+               else {
+                       registered = 0;
+                       break;
+               }
+       }
+
+       return registered == 1 ? 0 : -ENODEV;
+}
+
+static void sn_pci_hotplug_exit(void)
+{
+       struct hotplug_slot *bss_hotplug_slot;
+
+       while ((bss_hotplug_slot = sn_hp_destroy())) {
+               pci_hp_deregister(bss_hotplug_slot);
+       }
+
+       if (!list_empty(&sn_hp_list))
+               printk(KERN_ERR "%s: internal list is not empty\n", __FILE__);
+}
+
+module_init(sn_pci_hotplug_init);
+module_exit(sn_pci_hotplug_exit);
index 4db69982876ef6ca6c7c57ca313a941956635442..393e0cee91a93cfb50e518c02909605943ed57c2 100644 (file)
@@ -325,7 +325,7 @@ int pcie_port_device_register(struct pci_dev *dev)
 static int suspend_iter(struct device *dev, void *data)
 {
        struct pcie_port_service_driver *service_driver;
-       u32 state = (u32)data;
+       pm_message_t state = * (pm_message_t *) data;
 
        if ((dev->bus == &pcie_port_bus_type) &&
            (dev->driver)) {
@@ -336,9 +336,9 @@ static int suspend_iter(struct device *dev, void *data)
        return 0;
 }
 
-int pcie_port_device_suspend(struct pci_dev *dev, u32 state)
+int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state)
 {
-       device_for_each_child(&dev->dev, (void *)state, suspend_iter);
+       device_for_each_child(&dev->dev, &state, suspend_iter);
        return 0;
 }
 
index a90a533eba0fc3f8c7b1b892c4d0b2b4fc159730..05fa91a31c620b0dd9de57a59066ed6adae71062 100644 (file)
@@ -379,6 +379,7 @@ exit:
 EXPORT_SYMBOL(pci_dev_present);
 
 EXPORT_SYMBOL(pci_find_bus);
+EXPORT_SYMBOL(pci_find_next_bus);
 EXPORT_SYMBOL(pci_find_device);
 EXPORT_SYMBOL(pci_find_device_reverse);
 EXPORT_SYMBOL(pci_find_slot);
index 52ea34594363e746b5f373fa8542fc460c5ef399..6485f75d2fb3beff9d80880ab354c57a5d3dde42 100644 (file)
@@ -1,8 +1,5 @@
 #
-# PCMCIA bus subsystem configuration
-#
-# Right now the non-CardBus choices are not supported
-# by the integrated kernel driver.
+# PCCARD (PCMCIA/CardBus) bus subsystem configuration
 #
 
 menu "PCCARD (PCMCIA/CardBus) support"
@@ -32,7 +29,7 @@ config PCMCIA_DEBUG
 
          The kernel command line options are:
            pcmcia_core.pc_debug=N
-           ds.pc_debug=N
+           pcmcia.pc_debug=N
            sa11xx_core.pc_debug=N
 
          The module option is called pc_debug=N
@@ -73,7 +70,7 @@ config PCMCIA_LOAD_CIS
          If unsure, say Y.
 
 config PCMCIA_IOCTL
-       bool
+       bool "PCMCIA control ioctl (obsolete)"
        depends on PCMCIA
        default y
        help
@@ -81,9 +78,8 @@ config PCMCIA_IOCTL
          subsystem will be built. It is needed by cardmgr and cardctl
          (pcmcia-cs) to function properly.
 
-         If you do not use the new pcmciautils package, and have a
-         yenta, Cirrus PD6729, i82092, i82365 or tcic compatible bridge,
-         you need to say Y here to be able to use 16-bit PCMCIA cards.
+         You should use the new pcmciautils package instead (see
+         <file:Documentation/Changes> for location and details).
 
          If unsure, say Y.
 
@@ -106,7 +102,8 @@ comment "PC-card bridges"
 
 config YENTA
        tristate "CardBus yenta-compatible bridge support"
-       depends on CARDBUS
+       depends on PCI
+       select CARDBUS if !EMBEDDED
        select PCCARD_NONSTATIC
        ---help---
          This option enables support for CardBus host bridges.  Virtually
index 417bc1500badb70868df9ac7eb9b745c7de8afd3..d5122b1ea94bfd083d6322202a2931bf8045f13e 100644 (file)
@@ -22,7 +22,6 @@
 #define __ASM_AU1000_PCMCIA_H
 
 /* include the world */
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
index df19ce1ea4f34ba0edc9f91b17a2770a1a558e22..d414a3bb50b98814ca4c1be18244e45456915b0d 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/version.h>
 #include <linux/types.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
index 1dfc77653660a7380c0adea53f33da70c94b3253..f113b69d699bf2ddfa8ccdfe8573095f1448d902 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/version.h>
 #include <linux/types.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
index 3ccb5247ec504d726e31e55ef72cc8281e25ae54..1d755e20880cebff5015681c217dd4d672c16c97 100644 (file)
@@ -31,7 +31,6 @@
 #include <asm/io.h>
 
 #define IN_CARD_SERVICES
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cs.h>
index e82859d3227a61e661d159acaf8b3d1c51a7f9fa..e39178fc59d08efb74efe4eaf1e8ba80a6fbdace 100644 (file)
@@ -33,7 +33,6 @@
 #include <asm/irq.h>
 
 #define IN_CARD_SERVICES
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cs.h>
@@ -216,6 +215,13 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
        list_add_tail(&socket->socket_list, &pcmcia_socket_list);
        up_write(&pcmcia_socket_list_rwsem);
 
+#ifndef CONFIG_CARDBUS
+       /*
+        * If we do not support Cardbus, ensure that
+        * the Cardbus socket capability is disabled.
+        */
+       socket->features &= ~SS_CAP_CARDBUS;
+#endif
 
        /* set proper values in socket->dev */
        socket->dev.class_data = socket;
@@ -449,11 +455,11 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
        }
 
        if (status & SS_CARDBUS) {
+               if (!(skt->features & SS_CAP_CARDBUS)) {
+                       cs_err(skt, "cardbus cards are not supported.\n");
+                       return CS_BAD_TYPE;
+               }
                skt->state |= SOCKET_CARDBUS;
-#ifndef CONFIG_CARDBUS
-               cs_err(skt, "cardbus cards are not supported.\n");
-               return CS_BAD_TYPE;
-#endif
        }
 
        /*
index 0b4c18edfa498ef02a21bb56894e91b6a95dc3e4..6bbfbd0e02a5d0f834f5b037f6b5a71815992bc4 100644 (file)
@@ -99,23 +99,11 @@ static inline void cs_socket_put(struct pcmcia_socket *skt)
        }
 }
 
-#define CHECK_HANDLE(h) \
-    (((h) == NULL) || ((h)->client_magic != CLIENT_MAGIC))
-
 #define CHECK_SOCKET(s) \
     (((s) >= sockets) || (socket_table[s]->ops == NULL))
 
-#define SOCKET(h) (h->Socket)
-#define CONFIG(h) (&SOCKET(h)->config[(h)->Function])
-
-#define CHECK_REGION(r) \
-    (((r) == NULL) || ((r)->region_magic != REGION_MAGIC))
-
-#define CHECK_ERASEQ(q) \
-    (((q) == NULL) || ((q)->eraseq_magic != ERASEQ_MAGIC))
-
-#define EVENT(h, e, p) \
-    ((h)->event_handler((e), (p), &(h)->event_callback_args))
+#define SOCKET(h) (h->socket)
+#define CONFIG(h) (&SOCKET(h)->config[(h)->func])
 
 /* In cardbus.c */
 int cb_alloc(struct pcmcia_socket *s);
index d5afd557fe370f8a9b0a92b076cd2f4a37d4e4f3..3e3c6f12bbe6b80bed6b550a55fe7da04ff94ba2 100644 (file)
@@ -158,17 +158,15 @@ static const lookup_t service_table[] = {
 };
 
 
-static int pcmcia_report_error(client_handle_t handle, error_info_t *err)
+static int pcmcia_report_error(struct pcmcia_device *p_dev, error_info_t *err)
 {
        int i;
        char *serv;
 
-       if (CHECK_HANDLE(handle))
+       if (!p_dev)
                printk(KERN_NOTICE);
-       else {
-               struct pcmcia_device *p_dev = handle_to_pdev(handle);
+       else
                printk(KERN_NOTICE "%s: ", p_dev->dev.bus_id);
-       }
 
        for (i = 0; i < ARRAY_SIZE(service_table); i++)
                if (service_table[i].key == err->func)
@@ -193,10 +191,10 @@ static int pcmcia_report_error(client_handle_t handle, error_info_t *err)
 
 /*======================================================================*/
 
-void cs_error(client_handle_t handle, int func, int ret)
+void cs_error(struct pcmcia_device *p_dev, int func, int ret)
 {
        error_info_t err = { func, ret };
-       pcmcia_report_error(handle, &err);
+       pcmcia_report_error(p_dev, &err);
 }
 EXPORT_SYMBOL(cs_error);
 
@@ -207,6 +205,10 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
        unsigned int i;
        u32 hash;
 
+       if (!p_drv->attach || !p_drv->event || !p_drv->detach)
+               printk(KERN_DEBUG "pcmcia: %s does misses a callback function",
+                      p_drv->drv.name);
+
        while (did && did->match_flags) {
                for (i=0; i<4; i++) {
                        if (!did->prod_id[i])
@@ -376,7 +378,7 @@ static int pcmcia_device_probe(struct device * dev)
 
        if (p_drv->attach) {
                p_dev->instance = p_drv->attach();
-               if ((!p_dev->instance) || (p_dev->client.state & CLIENT_UNBOUND)) {
+               if ((!p_dev->instance) || (p_dev->state & CLIENT_UNBOUND)) {
                        printk(KERN_NOTICE "ds: unable to create instance "
                               "of '%s'!\n", p_drv->drv.name);
                        ret = -EINVAL;
@@ -516,10 +518,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
        sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);
 
        /* compat */
-       p_dev->client.client_magic = CLIENT_MAGIC;
-       p_dev->client.Socket = s;
-       p_dev->client.Function = function;
-       p_dev->client.state = CLIENT_UNBOUND;
+       p_dev->state = CLIENT_UNBOUND;
 
        /* Add to the list in pcmcia_bus_socket */
        spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
@@ -573,8 +572,6 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
        else
                no_funcs = 1;
 
-       /* this doesn't handle multifunction devices on one pcmcia function
-        * yet. */
        for (i=0; i < no_funcs; i++)
                pcmcia_device_add(s, i);
 
@@ -914,6 +911,7 @@ struct send_event_data {
 static int send_event_callback(struct device *dev, void * _data)
 {
        struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+       struct pcmcia_driver *p_drv;
        struct send_event_data *data = _data;
 
        /* we get called for all sockets, but may only pass the event
@@ -921,11 +919,16 @@ static int send_event_callback(struct device *dev, void * _data)
        if (p_dev->socket != data->skt)
                return 0;
 
-       if (p_dev->client.state & (CLIENT_UNBOUND|CLIENT_STALE))
+       p_drv = to_pcmcia_drv(p_dev->dev.driver);
+       if (!p_drv)
                return 0;
 
-       if (p_dev->client.EventMask & data->event)
-               return EVENT(&p_dev->client, data->event, data->priority);
+       if (p_dev->state & (CLIENT_UNBOUND|CLIENT_STALE))
+               return 0;
+
+       if (p_drv->event)
+               return p_drv->event(data->event, data->priority,
+                                   &p_dev->event_callback_args);
 
        return 0;
 }
@@ -987,11 +990,11 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
 
 
 
-int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
+int pcmcia_register_client(struct pcmcia_device **handle, client_reg_t *req)
 {
-       client_t *client = NULL;
        struct pcmcia_socket *s = NULL;
        struct pcmcia_device *p_dev = NULL;
+       struct pcmcia_driver *p_drv = NULL;
 
        /* Look for unbound client with matching dev_info */
        down_read(&pcmcia_socket_list_rwsem);
@@ -1006,18 +1009,16 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
                        continue;
                spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
                list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
-                       struct pcmcia_driver *p_drv;
                        p_dev = pcmcia_get_dev(p_dev);
                        if (!p_dev)
                                continue;
-                       if (!(p_dev->client.state & CLIENT_UNBOUND) ||
+                       if (!(p_dev->state & CLIENT_UNBOUND) ||
                            (!p_dev->dev.driver)) {
                                pcmcia_put_dev(p_dev);
                                continue;
                        }
                        p_drv = to_pcmcia_drv(p_dev->dev.driver);
                        if (!strncmp(p_drv->drv.name, (char *)req->dev_info, DEV_NAME_LEN)) {
-                               client = &p_dev->client;
                                spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
                                goto found;
                        }
@@ -1028,26 +1029,20 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
        }
  found:
        up_read(&pcmcia_socket_list_rwsem);
-       if (!p_dev || !client)
+       if (!p_dev)
                return -ENODEV;
 
        pcmcia_put_socket(s); /* safe, as we already hold a reference from bind_device */
 
-       *handle = client;
-       client->state &= ~CLIENT_UNBOUND;
-       client->Socket = s;
-       client->EventMask = req->EventMask;
-       client->event_handler = req->event_handler;
-       client->event_callback_args = req->event_callback_args;
-       client->event_callback_args.client_handle = client;
+       *handle = p_dev;
+       p_dev->state &= ~CLIENT_UNBOUND;
+       p_dev->event_callback_args = req->event_callback_args;
+       p_dev->event_callback_args.client_handle = p_dev;
 
-       if (s->state & SOCKET_CARDBUS)
-               client->state |= CLIENT_CARDBUS;
 
-       if ((!(s->state & SOCKET_CARDBUS)) && (s->functions == 0) &&
-           (client->Function != BIND_FN_ALL)) {
+       if (!s->functions) {
                cistpl_longlink_mfc_t mfc;
-               if (pccard_read_tuple(s, client->Function, CISTPL_LONGLINK_MFC, &mfc)
+               if (pccard_read_tuple(s, p_dev->func, CISTPL_LONGLINK_MFC, &mfc)
                    == CS_SUCCESS)
                        s->functions = mfc.nfn;
                else
@@ -1060,13 +1055,13 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
        }
 
        ds_dbg(1, "register_client(): client 0x%p, dev %s\n",
-              client, p_dev->dev.bus_id);
-       if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE)
-               EVENT(client, CS_EVENT_REGISTRATION_COMPLETE, CS_EVENT_PRI_LOW);
+              p_dev, p_dev->dev.bus_id);
 
        if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT) {
-               if (client->EventMask & CS_EVENT_CARD_INSERTION)
-                       EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
+               if (p_drv->event)
+                       p_drv->event(CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW,
+                                    &p_dev->event_callback_args);
+
        }
 
        return CS_SUCCESS;
@@ -1099,7 +1094,7 @@ static int unbind_request(struct pcmcia_socket *s)
                }
                p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
                list_del(&p_dev->socket_device_list);
-               p_dev->client.state |= CLIENT_STALE;
+               p_dev->state |= CLIENT_STALE;
                spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 
                device_unregister(&p_dev->dev);
@@ -1108,31 +1103,25 @@ static int unbind_request(struct pcmcia_socket *s)
        return 0;
 } /* unbind_request */
 
-int pcmcia_deregister_client(client_handle_t handle)
+int pcmcia_deregister_client(struct pcmcia_device *p_dev)
 {
        struct pcmcia_socket *s;
        int i;
-       struct pcmcia_device *p_dev = handle_to_pdev(handle);
-
-       if (CHECK_HANDLE(handle))
-               return CS_BAD_HANDLE;
 
-       s = SOCKET(handle);
-       ds_dbg(1, "deregister_client(%p)\n", handle);
+       s = p_dev->socket;
+       ds_dbg(1, "deregister_client(%p)\n", p_dev);
 
-       if (handle->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
+       if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
                goto warn_out;
        for (i = 0; i < MAX_WIN; i++)
-               if (handle->state & CLIENT_WIN_REQ(i))
+               if (p_dev->state & CLIENT_WIN_REQ(i))
                        goto warn_out;
 
-       if (handle->state & CLIENT_STALE) {
-               handle->client_magic = 0;
-               handle->state &= ~CLIENT_STALE;
+       if (p_dev->state & CLIENT_STALE) {
+               p_dev->state &= ~CLIENT_STALE;
                pcmcia_put_dev(p_dev);
        } else {
-               handle->state = CLIENT_UNBOUND;
-               handle->event_handler = NULL;
+               p_dev->state = CLIENT_UNBOUND;
        }
 
        return CS_SUCCESS;
index 5ab55ae0ac362dcd078985928ab57d9025e27448..316f8bcc878be674fa22cba22e4781b14fc3ec43 100644 (file)
@@ -43,7 +43,6 @@
 #include <asm/hd64465/hd64465.h>
 #include <asm/hd64465/io.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
index d72f9a35c8bdbf5566293001a153d6a3200749f2..a713015e8228cb48321fa227ceda4db9a1eed7ef 100644 (file)
@@ -53,7 +53,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cs.h>
@@ -698,14 +697,6 @@ static void __init add_pcic(int ns, int type)
     struct i82365_socket *t = &socket[sockets-ns];
 
     base = sockets-ns;
-    if (t->ioaddr > 0) {
-       if (!request_region(t->ioaddr, 2, "i82365")) {
-           printk(KERN_ERR "i82365: IO region conflict at %#lx, not available\n",
-                       t->ioaddr);
-           return;
-       }
-    }
-    
     if (base == 0) printk("\n");
     printk(KERN_INFO "  %s", pcic[type].name);
     printk(" ISA-to-PCMCIA at port %#lx ofs 0x%02x",
index b1111c6bf062a55d726b7be28eb79af41eafe8f5..65f3ee3d4d3c6ea48b76c5b9d052186ad74f8b1c 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cs.h>
index c0997c4714f08a2fe3a36972ad0f6af27df258c7..7b14d7efd68c0632d08ad35b273730bd625bc5d1 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/system.h>
 #include <asm/addrspace.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cs.h>
index 1cc83317e7e34da05607b21070531786a559d0b3..ebb161c4f819fdccb68017836dd16fc64f499d7a 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/init.h>
 
 #define IN_CARD_SERVICES
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/bulkmem.h>
 
 #include "cs_internal.h"
 
-int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple)
+int pcmcia_get_first_tuple(struct pcmcia_device *p_dev, tuple_t *tuple)
 {
-       struct pcmcia_socket *s;
-       if (CHECK_HANDLE(handle))
-               return CS_BAD_HANDLE;
-       s = SOCKET(handle);
-       return pccard_get_first_tuple(s, handle->Function, tuple);
+       return pccard_get_first_tuple(p_dev->socket, p_dev->func, tuple);
 }
 EXPORT_SYMBOL(pcmcia_get_first_tuple);
 
-int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple)
+int pcmcia_get_next_tuple(struct pcmcia_device *p_dev, tuple_t *tuple)
 {
-       struct pcmcia_socket *s;
-       if (CHECK_HANDLE(handle))
-               return CS_BAD_HANDLE;
-       s = SOCKET(handle);
-       return pccard_get_next_tuple(s, handle->Function, tuple);
+       return pccard_get_next_tuple(p_dev->socket, p_dev->func, tuple);
 }
 EXPORT_SYMBOL(pcmcia_get_next_tuple);
 
-int pcmcia_get_tuple_data(client_handle_t handle, tuple_t *tuple)
+int pcmcia_get_tuple_data(struct pcmcia_device *p_dev, tuple_t *tuple)
 {
-       struct pcmcia_socket *s;
-       if (CHECK_HANDLE(handle))
-               return CS_BAD_HANDLE;
-       s = SOCKET(handle);
-       return pccard_get_tuple_data(s, tuple);
+       return pccard_get_tuple_data(p_dev->socket, tuple);
 }
 EXPORT_SYMBOL(pcmcia_get_tuple_data);
 
-int pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+int pcmcia_parse_tuple(struct pcmcia_device *p_dev, tuple_t *tuple, cisparse_t *parse)
 {
        return pccard_parse_tuple(tuple, parse);
 }
 EXPORT_SYMBOL(pcmcia_parse_tuple);
 
-int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info)
+int pcmcia_validate_cis(struct pcmcia_device *p_dev, cisinfo_t *info)
 {
-       struct pcmcia_socket *s;
-       if (CHECK_HANDLE(handle))
-               return CS_BAD_HANDLE;
-       s = SOCKET(handle);
-       return pccard_validate_cis(s, handle->Function, info);
+       return pccard_validate_cis(p_dev->socket, p_dev->func, info);
 }
 EXPORT_SYMBOL(pcmcia_validate_cis);
 
 
-int pcmcia_reset_card(client_handle_t handle, client_req_t *req)
+int pcmcia_reset_card(struct pcmcia_device *p_dev, client_req_t *req)
 {
-       struct pcmcia_socket *skt;
-    
-       if (CHECK_HANDLE(handle))
-               return CS_BAD_HANDLE;
-       skt = SOCKET(handle);
-       if (!skt)
-               return CS_BAD_HANDLE;
-
-       return pccard_reset_card(skt);
+       return pccard_reset_card(p_dev->socket);
 }
 EXPORT_SYMBOL(pcmcia_reset_card);
-
index b883bc151ed00f58b9be03c994974b7e2aaca0cb..39ba6406fd54ef8b9a398eafb3c425a6706837f5 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/workqueue.h>
 
 #define IN_CARD_SERVICES
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -71,29 +70,6 @@ extern int ds_pc_debug;
 #define ds_dbg(lvl, fmt, arg...) do { } while (0)
 #endif
 
-static const char *release = "Linux Kernel Card Services";
-
-/** pcmcia_get_card_services_info
- *
- * Return information about this version of Card Services
- */
-static int pcmcia_get_card_services_info(servinfo_t *info)
-{
-       unsigned int socket_count = 0;
-       struct list_head *tmp;
-       info->Signature[0] = 'C';
-       info->Signature[1] = 'S';
-       down_read(&pcmcia_socket_list_rwsem);
-       list_for_each(tmp, &pcmcia_socket_list)
-               socket_count++;
-       up_read(&pcmcia_socket_list_rwsem);
-       info->Count = socket_count;
-       info->Revision = CS_RELEASE_CODE;
-       info->CSLevel = 0x0210;
-       info->VendorString = (char *)release;
-       return CS_SUCCESS;
-} /* get_card_services_info */
-
 
 /* backwards-compatible accessing of driver --- by name! */
 
@@ -591,9 +567,6 @@ static int ds_ioctl(struct inode * inode, struct file * file,
     case DS_ADJUST_RESOURCE_INFO:
        ret = pcmcia_adjust_resource_info(&buf->adjust);
        break;
-    case DS_GET_CARD_SERVICES_INFO:
-       ret = pcmcia_get_card_services_info(&buf->servinfo);
-       break;
     case DS_GET_CONFIGURATION_INFO:
        if (buf->config.Function &&
           (buf->config.Function >= s->functions))
index c01dc6bf15267fc78ec7e50ad5920012521e83f8..184f4f88b2a0b46c9a406fe962104e94513041d3 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/device.h>
 
 #define IN_CARD_SERVICES
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cs.h>
@@ -202,14 +201,11 @@ int pccard_access_configuration_register(struct pcmcia_socket *s,
        return CS_SUCCESS;
 } /* pccard_access_configuration_register */
 
-int pcmcia_access_configuration_register(client_handle_t handle,
+int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
                                         conf_reg_t *reg)
 {
-       struct pcmcia_socket *s;
-       if (CHECK_HANDLE(handle))
-               return CS_BAD_HANDLE;
-       s = SOCKET(handle);
-       return pccard_access_configuration_register(s, handle->Function, reg);
+       return pccard_access_configuration_register(p_dev->socket,
+                                                   p_dev->func, reg);
 }
 EXPORT_SYMBOL(pcmcia_access_configuration_register);
 
@@ -271,17 +267,11 @@ int pccard_get_configuration_info(struct pcmcia_socket *s,
        return CS_SUCCESS;
 } /* pccard_get_configuration_info */
 
-int pcmcia_get_configuration_info(client_handle_t handle,
+int pcmcia_get_configuration_info(struct pcmcia_device *p_dev,
                                  config_info_t *config)
 {
-       struct pcmcia_socket *s;
-
-       if ((CHECK_HANDLE(handle)) || !config)
-               return CS_BAD_HANDLE;
-       s = SOCKET(handle);
-       if (!s)
-               return CS_BAD_HANDLE;
-       return pccard_get_configuration_info(s, handle->Function, config);
+       return pccard_get_configuration_info(p_dev->socket, p_dev->func,
+                                            config);
 }
 EXPORT_SYMBOL(pcmcia_get_configuration_info);
 
@@ -382,10 +372,8 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function,
 int pcmcia_get_status(client_handle_t handle, cs_status_t *status)
 {
        struct pcmcia_socket *s;
-       if (CHECK_HANDLE(handle))
-               return CS_BAD_HANDLE;
        s = SOCKET(handle);
-       return pccard_get_status(s, handle->Function, status);
+       return pccard_get_status(s, handle->func, status);
 }
 EXPORT_SYMBOL(pcmcia_get_status);
 
@@ -426,16 +414,14 @@ EXPORT_SYMBOL(pcmcia_map_mem_page);
  *
  * Modify a locked socket configuration
  */
-int pcmcia_modify_configuration(client_handle_t handle,
+int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
                                modconf_t *mod)
 {
        struct pcmcia_socket *s;
        config_t *c;
 
-       if (CHECK_HANDLE(handle))
-               return CS_BAD_HANDLE;
-       s = SOCKET(handle);
-       c = CONFIG(handle);
+       s = p_dev->socket;
+       c = CONFIG(p_dev);
        if (!(s->state & SOCKET_PRESENT))
                return CS_NO_CARD;
        if (!(c->state & CONFIG_LOCKED))
@@ -472,25 +458,18 @@ int pcmcia_modify_configuration(client_handle_t handle,
 EXPORT_SYMBOL(pcmcia_modify_configuration);
 
 
-int pcmcia_release_configuration(client_handle_t handle)
+int pcmcia_release_configuration(struct pcmcia_device *p_dev)
 {
        pccard_io_map io = { 0, 0, 0, 0, 1 };
-       struct pcmcia_socket *s;
+       struct pcmcia_socket *s = p_dev->socket;
        int i;
 
-       if (CHECK_HANDLE(handle) ||
-           !(handle->state & CLIENT_CONFIG_LOCKED))
+       if (!(p_dev->state & CLIENT_CONFIG_LOCKED))
                return CS_BAD_HANDLE;
-       handle->state &= ~CLIENT_CONFIG_LOCKED;
-       s = SOCKET(handle);
-
-#ifdef CONFIG_CARDBUS
-       if (handle->state & CLIENT_CARDBUS)
-               return CS_SUCCESS;
-#endif
+       p_dev->state &= ~CLIENT_CONFIG_LOCKED;
 
-       if (!(handle->state & CLIENT_STALE)) {
-               config_t *c = CONFIG(handle);
+       if (!(p_dev->state & CLIENT_STALE)) {
+               config_t *c = CONFIG(p_dev);
                if (--(s->lock_count) == 0) {
                        s->socket.flags = SS_OUTPUT_ENA;   /* Is this correct? */
                        s->socket.Vpp = 0;
@@ -523,22 +502,16 @@ EXPORT_SYMBOL(pcmcia_release_configuration);
  * don't bother checking the port ranges against the current socket
  * values.
  */
-int pcmcia_release_io(client_handle_t handle, io_req_t *req)
+int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
 {
-       struct pcmcia_socket *s;
+       struct pcmcia_socket *s = p_dev->socket;
 
-       if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ))
+       if (!(p_dev->state & CLIENT_IO_REQ))
                return CS_BAD_HANDLE;
-       handle->state &= ~CLIENT_IO_REQ;
-       s = SOCKET(handle);
-
-#ifdef CONFIG_CARDBUS
-       if (handle->state & CLIENT_CARDBUS)
-               return CS_SUCCESS;
-#endif
+       p_dev->state &= ~CLIENT_IO_REQ;
 
-       if (!(handle->state & CLIENT_STALE)) {
-               config_t *c = CONFIG(handle);
+       if (!(p_dev->state & CLIENT_STALE)) {
+               config_t *c = CONFIG(p_dev);
                if (c->state & CONFIG_LOCKED)
                        return CS_CONFIGURATION_LOCKED;
                if ((c->io.BasePort1 != req->BasePort1) ||
@@ -558,16 +531,15 @@ int pcmcia_release_io(client_handle_t handle, io_req_t *req)
 EXPORT_SYMBOL(pcmcia_release_io);
 
 
-int pcmcia_release_irq(client_handle_t handle, irq_req_t *req)
+int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
 {
-       struct pcmcia_socket *s;
-       if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IRQ_REQ))
+       struct pcmcia_socket *s = p_dev->socket;
+       if (!(p_dev->state & CLIENT_IRQ_REQ))
                return CS_BAD_HANDLE;
-       handle->state &= ~CLIENT_IRQ_REQ;
-       s = SOCKET(handle);
+       p_dev->state &= ~CLIENT_IRQ_REQ;
 
-       if (!(handle->state & CLIENT_STALE)) {
-               config_t *c = CONFIG(handle);
+       if (!(p_dev->state & CLIENT_STALE)) {
+               config_t *c = CONFIG(p_dev);
                if (c->state & CONFIG_LOCKED)
                        return CS_CONFIGURATION_LOCKED;
                if (c->irq.Attributes != req->Attributes)
@@ -623,29 +595,21 @@ int pcmcia_release_window(window_handle_t win)
 EXPORT_SYMBOL(pcmcia_release_window);
 
 
-int pcmcia_request_configuration(client_handle_t handle,
+int pcmcia_request_configuration(struct pcmcia_device *p_dev,
                                 config_req_t *req)
 {
        int i;
        u_int base;
-       struct pcmcia_socket *s;
+       struct pcmcia_socket *s = p_dev->socket;
        config_t *c;
        pccard_io_map iomap;
 
-       if (CHECK_HANDLE(handle))
-               return CS_BAD_HANDLE;
-       s = SOCKET(handle);
        if (!(s->state & SOCKET_PRESENT))
                return CS_NO_CARD;
 
-#ifdef CONFIG_CARDBUS
-       if (handle->state & CLIENT_CARDBUS)
-               return CS_UNSUPPORTED_MODE;
-#endif
-
        if (req->IntType & INT_CARDBUS)
                return CS_UNSUPPORTED_MODE;
-       c = CONFIG(handle);
+       c = CONFIG(p_dev);
        if (c->state & CONFIG_LOCKED)
                return CS_CONFIGURATION_LOCKED;
 
@@ -746,7 +710,7 @@ int pcmcia_request_configuration(client_handle_t handle,
        }
 
        c->state |= CONFIG_LOCKED;
-       handle->state |= CLIENT_CONFIG_LOCKED;
+       p_dev->state |= CLIENT_CONFIG_LOCKED;
        return CS_SUCCESS;
 } /* pcmcia_request_configuration */
 EXPORT_SYMBOL(pcmcia_request_configuration);
@@ -757,29 +721,17 @@ EXPORT_SYMBOL(pcmcia_request_configuration);
  * Request_io() reserves ranges of port addresses for a socket.
  * I have not implemented range sharing or alias addressing.
  */
-int pcmcia_request_io(client_handle_t handle, io_req_t *req)
+int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
 {
-       struct pcmcia_socket *s;
+       struct pcmcia_socket *s = p_dev->socket;
        config_t *c;
 
-       if (CHECK_HANDLE(handle))
-               return CS_BAD_HANDLE;
-       s = SOCKET(handle);
        if (!(s->state & SOCKET_PRESENT))
                return CS_NO_CARD;
 
-       if (handle->state & CLIENT_CARDBUS) {
-#ifdef CONFIG_CARDBUS
-               handle->state |= CLIENT_IO_REQ;
-               return CS_SUCCESS;
-#else
-               return CS_UNSUPPORTED_FUNCTION;
-#endif
-       }
-
        if (!req)
                return CS_UNSUPPORTED_MODE;
-       c = CONFIG(handle);
+       c = CONFIG(p_dev);
        if (c->state & CONFIG_LOCKED)
                return CS_CONFIGURATION_LOCKED;
        if (c->state & CONFIG_IO_REQ)
@@ -804,7 +756,7 @@ int pcmcia_request_io(client_handle_t handle, io_req_t *req)
 
        c->io = *req;
        c->state |= CONFIG_IO_REQ;
-       handle->state |= CLIENT_IO_REQ;
+       p_dev->state |= CLIENT_IO_REQ;
        return CS_SUCCESS;
 } /* pcmcia_request_io */
 EXPORT_SYMBOL(pcmcia_request_io);
@@ -827,19 +779,15 @@ static irqreturn_t test_action(int cpl, void *dev_id, struct pt_regs *regs)
 }
 #endif
 
-int pcmcia_request_irq(client_handle_t handle, irq_req_t *req)
+int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
 {
-       struct pcmcia_socket *s;
+       struct pcmcia_socket *s = p_dev->socket;
        config_t *c;
        int ret = CS_IN_USE, irq = 0;
-       struct pcmcia_device *p_dev = handle_to_pdev(handle);
 
-       if (CHECK_HANDLE(handle))
-               return CS_BAD_HANDLE;
-       s = SOCKET(handle);
        if (!(s->state & SOCKET_PRESENT))
                return CS_NO_CARD;
-       c = CONFIG(handle);
+       c = CONFIG(p_dev);
        if (c->state & CONFIG_LOCKED)
                return CS_CONFIGURATION_LOCKED;
        if (c->state & CONFIG_IRQ_REQ)
@@ -903,7 +851,7 @@ int pcmcia_request_irq(client_handle_t handle, irq_req_t *req)
        s->irq.Config++;
 
        c->state |= CONFIG_IRQ_REQ;
-       handle->state |= CLIENT_IRQ_REQ;
+       p_dev->state |= CLIENT_IRQ_REQ;
 
 #ifdef CONFIG_PCMCIA_PROBE
        pcmcia_used_irq[irq]++;
@@ -919,16 +867,13 @@ EXPORT_SYMBOL(pcmcia_request_irq);
  * Request_window() establishes a mapping between card memory space
  * and system memory space.
  */
-int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle_t *wh)
+int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_handle_t *wh)
 {
-       struct pcmcia_socket *s;
+       struct pcmcia_socket *s = (*p_dev)->socket;
        window_t *win;
        u_long align;
        int w;
 
-       if (CHECK_HANDLE(*handle))
-               return CS_BAD_HANDLE;
-       s = (*handle)->Socket;
        if (!(s->state & SOCKET_PRESENT))
                return CS_NO_CARD;
        if (req->Attributes & (WIN_PAGED | WIN_SHARED))
@@ -957,7 +902,7 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle
        win = &s->win[w];
        win->magic = WINDOW_MAGIC;
        win->index = w;
-       win->handle = *handle;
+       win->handle = *p_dev;
        win->sock = s;
 
        if (!(s->features & SS_CAP_STATIC_MAP)) {
@@ -966,7 +911,7 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle
                if (!win->ctl.res)
                        return CS_IN_USE;
        }
-       (*handle)->state |= CLIENT_WIN_REQ(w);
+       (*p_dev)->state |= CLIENT_WIN_REQ(w);
 
        /* Configure the socket controller */
        win->ctl.map = w+1;
index f1bb79153021047c93ab56fbaf645ff260b1cbcb..e98bb3d80e7c30f086f1c7346128cc744793cbf8 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/init.h>
 #include <linux/config.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
index 700a155fbc7810ab6d8c682f8a19d6b199249302..6f14126889b3457e6c8d7055e9994918e594b793 100644 (file)
@@ -11,7 +11,6 @@
 
 /* include the world */
 #include <linux/cpufreq.h>
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
index fcef54c1c2da5c5e17c0113c29a7a36b08c63c5b..1040a6c1a8a44c25eec76006154670bee4d69864 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/irq.h>
 
 #define IN_CARD_SERVICES
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cs.h>
index aacbbb5f055d8c65f6e2c2e38b77343f36edb936..d5a61eae61194a8f3f3cc8f11ff278c3e61ad1da 100644 (file)
@@ -50,7 +50,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
index c7ba99871aca05ef2d51f9e5fdd43144c60bd544..fbe233e19cebb285d620363c42d730b32c5a729b 100644 (file)
 #define ENE_TEST_C9                    0xc9    /* 8bit */
 #define ENE_TEST_C9_TLTENABLE          0x02
 
-#ifdef CONFIG_CARDBUS
-
 /*
  * Texas Instruments CardBus controller overrides.
  */
@@ -843,7 +841,5 @@ static int ti1250_override(struct yenta_socket *socket)
        return ti12xx_override(socket);
 }
 
-#endif /* CONFIG_CARDBUS */
-
 #endif /* _LINUX_TI113X_H */
 
index 02b23abc2df143edfac93a8985b6f1e9dc8084dd..0e7aa8176692f1aa60f5dc874af8a6afde17d740 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/delay.h>
 #include <linux/module.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cs.h>
@@ -869,14 +868,11 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket)
  */
 static void yenta_get_socket_capabilities(struct yenta_socket *socket, u32 isa_irq_mask)
 {
-       socket->socket.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS;
-       socket->socket.map_size = 0x1000;
        socket->socket.pci_irq = socket->cb_irq;
        if (isa_probe)
                socket->socket.irq_mask = yenta_probe_irq(socket, isa_irq_mask);
        else
                socket->socket.irq_mask = 0;
-       socket->socket.cb_dev = socket->dev;
 
        printk(KERN_INFO "Yenta: ISA IRQ mask 0x%04x, PCI irq %d\n",
               socket->socket.irq_mask, socket->cb_irq);
@@ -942,6 +938,9 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
        socket->socket.dev.dev = &dev->dev;
        socket->socket.driver_data = socket;
        socket->socket.owner = THIS_MODULE;
+       socket->socket.features = SS_CAP_PAGE_REGS | SS_CAP_PCCARD;
+       socket->socket.map_size = 0x1000;
+       socket->socket.cb_dev = dev;
 
        /* prepare struct yenta_socket */
        socket->dev = dev;
@@ -1012,6 +1011,10 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
                socket->poll_timer.data = (unsigned long)socket;
                socket->poll_timer.expires = jiffies + HZ;
                add_timer(&socket->poll_timer);
+               printk(KERN_INFO "Yenta: no PCI IRQ, CardBus support disabled for this socket.\n"
+                      KERN_INFO "Yenta: check your BIOS CardBus, BIOS IRQ or ACPI settings.\n");
+       } else {
+               socket->socket.features |= SS_CAP_CARDBUS;
        }
 
        /* Figure out what the dang thing can do for the PCMCIA layer... */
index 60440dbe3a2764168056bf2b48acbaaf4d64cecb..24c0af49c25c8f416615b4a009af21e6045b5043 100644 (file)
@@ -428,7 +428,7 @@ claw_pack_skb(struct claw_privbk *privptr)
        new_skb = NULL;         /* assume no dice */
        pkt_cnt = 0;
        CLAW_DBF_TEXT(4,trace,"PackSKBe");
-       if (skb_queue_len(&p_ch->collect_queue) > 0) {
+       if (!skb_queue_empty(&p_ch->collect_queue)) {
        /* some data */
                held_skb = skb_dequeue(&p_ch->collect_queue);
                if (p_env->packing != DO_PACKED)
@@ -1254,7 +1254,7 @@ claw_write_next ( struct chbk * p_ch )
        privptr = (struct claw_privbk *) dev->priv;
         claw_free_wrt_buf( dev );
        if ((privptr->write_free_count > 0) &&
-           (skb_queue_len(&p_ch->collect_queue) > 0)) {
+           !skb_queue_empty(&p_ch->collect_queue)) {
                pk_skb = claw_pack_skb(privptr);
                while (pk_skb != NULL) {
                        rc = claw_hw_tx( pk_skb, dev,1);
index 3080393e823db43117d22a6bd73adf7cfdcc6013..968f2c113efeefa2bf627f39bc711c32e4dbfff3 100644 (file)
@@ -156,7 +156,7 @@ ctc_tty_readmodem(ctc_tty_info *info)
                                        skb_queue_head(&info->rx_queue, skb);
                                else {
                                        kfree_skb(skb);
-                                       ret = skb_queue_len(&info->rx_queue);
+                                       ret = !skb_queue_empty(&info->rx_queue);
                                }
                        }
                }
@@ -530,7 +530,7 @@ ctc_tty_write(struct tty_struct *tty, const u_char * buf, int count)
                total += c;
                count -= c;
        }
-       if (skb_queue_len(&info->tx_queue)) {
+       if (!skb_queue_empty(&info->tx_queue)) {
                info->lsr &= ~UART_LSR_TEMT;
                tasklet_schedule(&info->tasklet);
        }
@@ -594,7 +594,7 @@ ctc_tty_flush_chars(struct tty_struct *tty)
                return;
        if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_flush_chars"))
                return;
-       if (tty->stopped || tty->hw_stopped || (!skb_queue_len(&info->tx_queue)))
+       if (tty->stopped || tty->hw_stopped || skb_queue_empty(&info->tx_queue))
                return;
        tasklet_schedule(&info->tasklet);
 }
index f1f6bf596dc9f9206521d0b8855863c598ee489f..7c530649983298b09a9b2babc356266b7b10339b 100644 (file)
@@ -50,7 +50,6 @@
 #include <scsi/scsi_host.h>
 #include "aha152x.h"
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -134,11 +133,6 @@ static dev_link_t *aha152x_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.event_handler = &aha152x_event;
-    client_reg.EventMask =
-       CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
-       CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-       CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -334,6 +328,7 @@ static struct pcmcia_driver aha152x_cs_driver = {
                .name   = "aha152x_cs",
        },
        .attach         = aha152x_attach,
+       .event          = aha152x_event,
        .detach         = aha152x_detach,
        .id_table       = aha152x_ids,
 };
index 853e6ee9b71a2e7acec53132ef01cae7ca3f92c0..db8f5cd85ffe9fef772e172e6bf821d514452ca8 100644 (file)
@@ -47,7 +47,6 @@
 #include <scsi/scsi_host.h>
 #include "fdomain.h"
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -120,11 +119,6 @@ static dev_link_t *fdomain_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.event_handler = &fdomain_event;
-    client_reg.EventMask =
-       CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
-       CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-       CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
     client_reg.Version = 0x0210;
     client_reg.event_callback_args.client_data = link;
     ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -314,6 +308,7 @@ static struct pcmcia_driver fdomain_cs_driver = {
                .name   = "fdomain_cs",
        },
        .attach         = fdomain_attach,
+       .event          = fdomain_event,
        .detach         = fdomain_detach,
        .id_table       = fdomain_ids,
 };
index 91b3f28e7a19ddc3dd66942124c7bd5cd2fc786c..3cd3b40b1a4c154ab7df9ca9b6dd86cbbe101fe8 100644 (file)
@@ -51,7 +51,6 @@
 #include <scsi/scsi.h>
 #include <scsi/scsi_ioctl.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -1642,11 +1641,6 @@ static dev_link_t *nsp_cs_attach(void)
        link->next               = dev_list;
        dev_list                 = link;
        client_reg.dev_info      = &dev_info;
-       client_reg.EventMask     =
-               CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-               CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET   |
-               CS_EVENT_PM_SUSPEND     | CS_EVENT_PM_RESUME     ;
-       client_reg.event_handler = &nsp_cs_event;
        client_reg.Version       = 0x0210;
        client_reg.event_callback_args.client_data = link;
        ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -2138,12 +2132,13 @@ static struct pcmcia_device_id nsp_cs_ids[] = {
 MODULE_DEVICE_TABLE(pcmcia, nsp_cs_ids);
 
 static struct pcmcia_driver nsp_driver = {
-       .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "nsp_cs",
+       .owner          = THIS_MODULE,
+       .drv            = {
+               .name   = "nsp_cs",
        },
-       .attach         = nsp_cs_attach,
-       .detach         = nsp_cs_detach,
+       .attach         = nsp_cs_attach,
+       .event          = nsp_cs_event,
+       .detach         = nsp_cs_detach,
        .id_table       = nsp_cs_ids,
 };
 #endif
index 0dcf41102abf0c685fc313e99b5bbdd2bbd09713..7a516f35834ef109c5ff6a0343af06ba6b0028d3 100644 (file)
@@ -49,7 +49,6 @@
 #include <scsi/scsi_host.h>
 #include "../qlogicfas408.h"
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -194,8 +193,6 @@ static dev_link_t *qlogic_attach(void)
        link->next = dev_list;
        dev_list = link;
        client_reg.dev_info = &dev_info;
-       client_reg.event_handler = &qlogic_event;
-       client_reg.EventMask = CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
        client_reg.Version = 0x0210;
        client_reg.event_callback_args.client_data = link;
        ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -423,6 +420,7 @@ static struct pcmcia_driver qlogic_cs_driver = {
        .name           = "qlogic_cs",
        },
        .attach         = qlogic_attach,
+       .event          = qlogic_event,
        .detach         = qlogic_detach,
        .id_table       = qlogic_ids,
 };
index 7d4b16b6797dac2562431a73326b5ad8e4d6ac15..b4b3a1a8a0c7f41aebcf6e1c6939f94c01398caa 100644 (file)
@@ -979,10 +979,6 @@ SYM53C500_attach(void)
        link->next = dev_list;
        dev_list = link;
        client_reg.dev_info = &dev_info;
-       client_reg.event_handler = &SYM53C500_event;
-       client_reg.EventMask = CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
-           CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-           CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
        client_reg.Version = 0x0210;
        client_reg.event_callback_args.client_data = link;
        ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -1013,6 +1009,7 @@ static struct pcmcia_driver sym53c500_cs_driver = {
                .name   = "sym53c500_cs",
        },
        .attach         = SYM53C500_attach,
+       .event          = SYM53C500_event,
        .detach         = SYM53C500_detach,
        .id_table       = sym53c500_ids,
 };
index 73a34b18866f405ee8a5d147a42ce9e46108a83d..de0136cc5938e57fd01daed5fd81f4ca03bd55f9 100644 (file)
@@ -45,7 +45,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -232,11 +231,6 @@ static dev_link_t *serial_attach(void)
        link->next = dev_list;
        dev_list = link;
        client_reg.dev_info = &dev_info;
-       client_reg.EventMask =
-           CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-           CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-           CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-       client_reg.event_handler = &serial_event;
        client_reg.Version = 0x0210;
        client_reg.event_callback_args.client_data = link;
        ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -883,6 +877,7 @@ static struct pcmcia_driver serial_cs_driver = {
                .name   = "serial_cs",
        },
        .attach         = serial_attach,
+       .event          = serial_event,
        .detach         = serial_detach,
        .id_table       = serial_ids,
 };
index ce5ebfe4af2b5e36e3a632aaeade29ecc9811022..57c0c6e3fbedcd3e08ccd3137312c511ec896ded 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/errno.h>       /* error codes */
 #include <linux/slab.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -69,11 +68,6 @@ static dev_link_t *ixj_attach(void)
        link->next = dev_list;
        dev_list = link;
        client_reg.dev_info = &dev_info;
-       client_reg.EventMask =
-           CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-           CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-           CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-       client_reg.event_handler = &ixj_event;
        client_reg.Version = 0x0210;
        client_reg.event_callback_args.client_data = link;
        ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -307,6 +301,7 @@ static struct pcmcia_driver ixj_driver = {
                .name   = "ixj_cs",
        },
        .attach         = ixj_attach,
+       .event          = ixj_event,
        .detach         = ixj_detach,
        .id_table       = ixj_ids,
 };
index 269d8ef01459d7834f699eb6f5c08ebf61ad2ecc..38aebe361ca140cb8e0255a474a0c5c87144dd8c 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/timer.h>
 #include <linux/ioport.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -389,11 +388,6 @@ static dev_link_t *sl811_cs_attach(void)
        dev_list = link;
        client_reg.dev_info = (dev_info_t *) &driver_name;
        client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
-       client_reg.EventMask =
-               CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-               CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-               CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-       client_reg.event_handler = &sl811_cs_event;
        client_reg.Version = 0x0210;
        client_reg.event_callback_args.client_data = link;
        ret = pcmcia_register_client(&link->handle, &client_reg);
@@ -418,6 +412,7 @@ static struct pcmcia_driver sl811_cs_driver = {
                .name   = (char *)driver_name,
        },
        .attach         = sl811_cs_attach,
+       .event          = sl811_cs_event,
        .detach         = sl811_cs_detach,
        .id_table       = sl811_ids,
 };
index 8a945f4f36939d35bc8b5d541b8e9d0b7cb9be06..576f3b852fce39ccfff151704c1447b883e1703f 100644 (file)
@@ -3227,9 +3227,9 @@ static int usbnet_stop (struct net_device *net)
        temp = unlink_urbs (dev, &dev->txq) + unlink_urbs (dev, &dev->rxq);
 
        // maybe wait for deletions to finish.
-       while (skb_queue_len (&dev->rxq)
-                       && skb_queue_len (&dev->txq)
-                       && skb_queue_len (&dev->done)) {
+       while (!skb_queue_empty(&dev->rxq) &&
+              !skb_queue_empty(&dev->txq) &&
+              !skb_queue_empty(&dev->done)) {
                msleep(UNLINK_TIMEOUT_MS);
                if (netif_msg_ifdown (dev))
                        devdbg (dev, "waited for %d urb completions", temp);
index 7dfbf39b4ed3c9c59ea502bd9a507d1a7a224c75..ddc9443254d9dc0bfac823614da46923dfebd354 100644 (file)
@@ -256,7 +256,7 @@ static ssize_t show_cmap(struct class_device *class_device, char *buf)
        unsigned int offset = 0, i;
 
        if (!fb_info->cmap.red || !fb_info->cmap.blue ||
-           fb_info->cmap.green || fb_info->cmap.transp)
+           !fb_info->cmap.green || !fb_info->cmap.transp)
                return -EINVAL;
 
        for (i = 0; i < fb_info->cmap.len; i++) {
index 6ba10e3aceff721457f4e13c7aa38f2a025c114e..3e9ccf370ab222cecdd59a0ceacedbac13b6af66 100644 (file)
@@ -63,5 +63,10 @@ config LOGO_SUPERH_CLUT224
        depends on LOGO && SUPERH
        default y
 
+config LOGO_M32R_CLUT224
+       bool "224-color M32R Linux logo"
+       depends on LOGO && M32R
+       default y
+
 endmenu
 
index b0d995020bd16e25d284c6830d36064cd427816f..d0244c04af5a71b11de61925c55fb9a001442ffd 100644 (file)
@@ -12,6 +12,7 @@ obj-$(CONFIG_LOGO_SUN_CLUT224)                += logo_sun_clut224.o
 obj-$(CONFIG_LOGO_SUPERH_MONO)         += logo_superh_mono.o
 obj-$(CONFIG_LOGO_SUPERH_VGA16)                += logo_superh_vga16.o
 obj-$(CONFIG_LOGO_SUPERH_CLUT224)      += logo_superh_clut224.o
+obj-$(CONFIG_LOGO_M32R_CLUT224)                += logo_m32r_clut224.o
 
 # How to generate logo's
 
index 77b6220750015e5839a8818df64653e6147611a1..788fa812c871a851c457d61834adac900445c5ec 100644 (file)
@@ -33,6 +33,7 @@ extern const struct linux_logo logo_sun_clut224;
 extern const struct linux_logo logo_superh_mono;
 extern const struct linux_logo logo_superh_vga16;
 extern const struct linux_logo logo_superh_clut224;
+extern const struct linux_logo logo_m32r_clut224;
 
 
 const struct linux_logo *fb_find_logo(int depth)
@@ -96,6 +97,10 @@ const struct linux_logo *fb_find_logo(int depth)
 #ifdef CONFIG_LOGO_SUPERH_CLUT224
                /* SuperH Linux logo */
                logo = &logo_superh_clut224;
+#endif
+#ifdef CONFIG_LOGO_M32R_CLUT224
+               /* M32R Linux logo */
+               logo = &logo_m32r_clut224;
 #endif
        }
        return logo;
diff --git a/drivers/video/logo/logo_m32r_clut224.ppm b/drivers/video/logo/logo_m32r_clut224.ppm
new file mode 100644 (file)
index 0000000..8b2983c
--- /dev/null
@@ -0,0 +1,1292 @@
+P3
+# CREATOR: The GIMP's PNM Filter Version 1.0
+#
+# Note: how to convert ppm to pnm(ascii).
+#   $ convert -posterize 224 m32r.ppm - | pnm2asc -f5 >logo_m32r_clut224.ppm
+#
+# convert - imagemagick: /usr/bin/convert
+# pnm2asc - pnm to ascii-pnm format converter
+#   http://www.is.aist.go.jp/etlcdb/util/p2a.htm#English
+
+80 80
+255
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  43 43 43  75 75 75  27 27 27  2 2 3
+  2 2 3  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  59 59 59  123 123 123  67 67 67  27 27 27
+  2 2 3  2 2 3  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  10 6 3  59 59 59  80 80 80  43 43 43  27 27 27
+  2 2 3  2 2 3  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  19 19 19  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  2 2 3  2 2 3  10 6 3  10 6 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  10 6 3  11 11 11  11 11 11  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  2 2 3  2 2 3  2 2 3  27 27 27  10 6 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  19 19 19  2 2 3  2 2 3  51 51 51  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  2 2 3  123 123 123  196 196 196  115 115 115  2 2 3
+  2 2 3  2 2 3  2 2 3  75 75 75  141 141 140
+  172 172 172  196 196 196  190 189 188  2 2 3  11 11 11
+  2 2 3  2 2 3  2 2 3  2 2 3  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  27 27 27  164 164 164  228 228 228  221 221 220  10 6 3
+  2 2 3  2 2 3  2 2 3  172 172 172  245 245 245
+  254 254 252  254 254 252  221 221 220  35 35 35  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  164 164 164  228 228 228  35 35 35  236 236 236  236 236 236
+  2 2 3  11 11 11  2 2 3  254 254 252  245 245 245
+  2 2 3  75 75 75  245 245 245  245 245 245  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  212 212 212  2 2 3  51 51 51  11 11 11  245 245 245
+  27 27 27  80 80 80  10 6 3  254 254 252  2 2 3
+  2 2 3  91 91 91  19 19 19  254 254 252  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  196 196 196  10 6 3  2 2 3  11 11 11  107 107 107
+  49 35 5  57 42 11  31 22 3  236 236 236  2 2 3
+  2 2 3  2 2 3  2 2 3  254 254 252  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  107 107 107  221 221 220  2 2 3  64 43 7  194 148 10
+  236 188 10  225 180 10  170 126 10  236 188 10  94 86 67
+  2 2 3  2 2 3  204 204 204  236 236 236  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  2 2 3  228 228 228  182 126 10  218 164 9  236 188 10
+  236 188 10  237 204 14  236 205 40  246 214 48  246 214 48
+  245 189 11  209 156 9  196 196 196  11 11 11  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  2 2 3  165 114 10  207 148 7  229 172 9  236 180 10
+  236 196 11  237 204 14  242 218 43  246 218 75  246 218 19
+  246 213 13  246 218 19  244 205 11  218 164 9  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  164 109 5  192 133 7  224 165 9  236 180 10  236 188 10
+  236 196 11  241 212 42  246 218 75  246 218 19  246 218 19
+  246 218 19  236 196 11  150 114 10  229 172 9  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  165 114 10  201 142 7  229 172 9  242 182 11  236 188 10
+  237 204 14  245 213 67  246 218 19  246 213 13  246 213 13
+  154 119 10  207 148 7  218 164 9  216 156 8  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  2 2 3  120 78 3  225 180 10  245 189 11  236 205 40
+  241 212 42  241 212 17  237 204 14  148 107 9  182 126 10
+  216 156 8  218 164 9  207 148 7  82 70 43  2 2 3
+  2 2 3  123 123 123  35 35 35  2 2 3  2 2 3
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  10 6 3  180 180 180  156 102 5  135 88 5  142 106 7
+  126 98 11  165 114 10  185 132 9  207 148 7  215 150 13
+  199 140 8  188 148 71  196 196 196  190 189 188  2 2 3
+  2 2 3  11 11 11  132 132 132  75 75 75  2 2 3
+  2 2 3  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  10 6 3  190 189 188  190 189 188  151 97 5  192 133 7
+  207 148 7  206 142 8  199 140 8  180 121 7  180 132 31
+  190 189 188  190 189 188  212 212 212  212 212 212  107 107 107
+  2 2 3  2 2 3  99 99 99  51 51 51  2 2 3
+  2 2 3  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  2 2 3  190 189 188  190 189 188  190 189 188  136 95 7
+  151 97 5  151 97 5  151 97 5  183 156 91  190 189 188
+  190 189 188  228 228 228  254 254 252  254 254 252  221 221 220
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  10 6 3  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  2 2 3  2 2 3
+  75 75 75  245 245 245  196 196 196  190 189 188  190 189 188
+  190 189 188  196 196 196  190 189 188  190 189 188  204 204 204
+  236 236 236  254 254 252  254 254 252  254 254 252  254 254 252
+  35 35 35  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  2 2 3  27 27 27  2 2 3
+  245 245 245  254 254 252  245 245 245  190 189 188  190 189 188
+  190 189 188  190 189 188  190 189 188  212 212 212  245 245 245
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  10 6 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  2 2 3  2 2 3  132 132 132
+  254 254 252  254 254 252  254 254 252  236 236 236  196 196 196
+  190 189 188  204 204 204  245 245 245  245 245 245  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  80 80 80  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  2 2 3  2 2 3  2 2 3  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  245 245 245
+  245 245 245  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  2 2 3  2 2 3  2 2 3  212 212 212  245 245 245
+  254 254 252  254 254 252  254 254 252  254 254 252  245 245 245
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  2 2 3  2 2 3  2 2 3  204 204 204  245 245 245
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  245 245 245  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  245 245 245  236 236 236  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  2 2 3  2 2 3
+  2 2 3  2 2 3  11 11 11  164 164 164  212 212 212
+  236 236 236  245 245 245  254 254 252  236 236 236  221 221 220
+  221 221 220  228 228 228  245 245 245  245 245 245  245 245 245
+  236 236 236  221 221 220  212 212 212  204 204 204  204 204 204
+  196 196 196  204 204 204  59 59 59  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  2 2 3  2 2 3
+  2 2 3  2 2 3  27 27 27  172 172 172  212 212 212
+  236 236 236  254 254 252  254 254 252  254 254 252  228 228 228
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  245 245 245  221 221 220  204 204 204  196 196 196
+  196 196 196  196 196 196  228 228 228  19 19 19  2 2 3
+  80 80 80  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  2 2 3  2 2 3  2 2 3
+  11 11 11  2 2 3  164 164 164  236 236 236  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  245 245 245
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  236 236 236  212 212 212  196 196 196  245 245 245  2 2 3
+  2 2 3  11 11 11  51 51 51  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  2 2 3  2 2 3  86 86 83
+  2 2 3  27 27 27  236 236 236  254 254 252  254 254 252
+  245 245 245  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  212 212 212  196 196 196  91 91 91
+  2 2 3  2 2 3  2 2 3  11 11 11  2 2 3
+  2 2 3  2 2 3  2 2 3  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  2 2 3  2 2 3  2 2 3
+  2 2 3  245 245 245  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  245 245 245
+  254 254 252  245 245 245  254 254 252  254 254 252  254 254 252
+  254 254 252  245 245 245  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  221 221 220  245 245 245
+  2 2 3  11 11 11  43 43 43  19 19 19  10 6 3
+  2 2 3  2 2 3  2 2 3  2 2 3  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  2 2 3  80 80 80  2 2 3
+  2 2 3  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  245 245 245  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  43 43 43  27 27 27  80 80 80  19 19 19  80 80 80
+  2 2 3  2 2 3  2 2 3  2 2 3  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  2 2 3  2 2 3  2 2 3  2 2 3
+  245 245 245  254 254 252  254 254 252  17 11 233  254 254 252
+  254 254 252  254 254 252  254 254 252  236 236 236  17 11 233
+  17 11 233  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  245 245 245
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  11 11 11  11 11 11  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  2 2 3  67 67 67  2 2 3  19 19 19
+  254 254 252  254 254 252  245 245 245  17 11 233  245 245 245
+  254 254 252  254 254 252  17 11 233  228 228 228  17 11 233
+  17 11 233  17 11 233  17 11 233  254 254 252  17 11 233
+  17 11 233  254 254 252  254 254 252  17 11 233  17 11 233
+  17 11 233  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  2 2 3  2 2 3  2 2 3  2 2 3
+  11 11 11  2 2 3  2 2 3  2 2 3  2 2 3
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  2 2 3  10 6 3  11 11 11  2 2 3  228 228 228
+  254 254 252  254 254 252  254 254 252  17 11 233  254 254 252
+  254 254 252  17 11 233  17 11 233  17 11 233  245 245 245
+  254 254 252  254 254 252  17 11 233  17 11 233  17 11 233
+  17 11 233  17 11 233  254 254 252  17 11 233  17 11 233
+  17 11 233  17 11 233  254 254 252  254 254 252  254 254 252
+  254 254 252  2 2 3  2 2 3  2 2 3  2 2 3
+  27 27 27  2 2 3  2 2 3  2 2 3  2 2 3
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  2 2 3  2 2 3  2 2 3  2 2 3  254 254 252
+  254 254 252  254 254 252  254 254 252  17 11 233  17 11 233
+  17 11 233  17 11 233  17 11 233  17 11 233  254 254 252
+  17 11 233  17 11 233  17 11 233  254 254 252  254 254 252
+  17 11 233  17 11 233  254 254 252  17 11 233  17 11 233
+  254 254 252  17 11 233  254 254 252  254 254 252  254 254 252
+  254 254 252  2 2 3  2 2 3  2 2 3  2 2 3
+  11 11 11  2 2 3  2 2 3  2 2 3  2 2 3
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  2 2 3  19 19 19  2 2 3  2 2 3  254 254 252
+  254 254 252  254 254 252  17 11 233  245 245 245  17 11 233
+  17 11 233  245 245 245  254 254 252  17 11 233  254 254 252
+  17 11 233  17 11 233  17 11 233  254 254 252  254 254 252
+  17 11 233  17 11 233  254 254 252  17 11 233  17 11 233
+  17 11 233  17 11 233  254 254 252  254 254 252  254 254 252
+  254 254 252  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  2 2 3
+  2 2 3  19 19 19  2 2 3  19 19 19  254 254 252
+  254 254 252  245 245 245  17 11 233  254 254 252  17 11 233
+  17 11 233  254 254 252  254 254 252  17 11 233  254 254 252
+  254 254 252  254 254 252  17 11 233  17 11 233  254 254 252
+  17 11 233  17 11 233  254 254 252  17 11 233  17 11 233
+  17 11 233  17 11 233  17 11 233  254 254 252  254 254 252
+  254 254 252  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  2 2 3  2 2 3
+  2 2 3  43 43 43  2 2 3  43 43 43  254 254 252
+  245 245 245  254 254 252  17 11 233  254 254 252  17 11 233
+  254 254 252  254 254 252  254 254 252  17 11 233  17 11 233
+  17 11 233  17 11 233  17 11 233  254 254 252  17 11 233
+  17 11 233  17 11 233  17 11 233  17 11 233  17 11 233
+  245 245 245  254 254 252  17 11 233  254 254 252  254 254 252
+  245 245 245  2 2 3  2 2 3  2 2 3  11 11 11
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  2 2 3  2 2 3
+  2 2 3  75 75 75  2 2 3  99 99 99  254 254 252
+  254 254 252  254 254 252  17 11 233  254 254 252  254 254 252
+  254 254 252  254 254 252  245 245 245  228 228 228  254 254 252
+  254 254 252  17 11 233  245 245 245  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  17 11 233  17 11 233
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  2 2 3  2 2 3  2 2 3  75 75 75
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  2 2 3  2 2 3
+  2 2 3  2 2 3  11 11 11  107 107 107  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  245 245 245  254 254 252  245 245 245  236 236 236  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  245 245 245
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  2 2 3  2 2 3  11 11 11  19 19 19
+  11 11 11  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  2 2 3  11 11 11
+  140 102 3  11 11 11  10 6 3  67 67 67  254 254 252
+  245 245 245  245 245 245  254 254 252  254 254 252  245 245 245
+  254 254 252  254 254 252  245 245 245  228 228 228  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  245 245 245  254 254 252  254 254 252  245 245 245
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  2 2 3  43 43 43  2 2 3  2 2 3
+  2 2 3  11 11 11  67 67 67  11 11 11  2 2 3
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  185 132 9  242 182 11
+  245 189 11  245 189 11  49 35 5  2 2 3  228 228 228
+  254 254 252  254 254 252  254 254 252  245 245 245  254 254 252
+  254 254 252  254 254 252  254 254 252  228 228 228  245 245 245
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  245 238 222  232 189 94
+  226 186 99  43 43 43  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  59 59 59  2 2 3
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  216 156 8  236 180 22
+  245 189 11  245 189 11  245 189 11  49 35 5  11 11 11
+  212 212 212  245 245 245  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  245 245 245  228 228 228  254 254 252
+  245 245 245  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  245 245 245  254 254 252  254 254 252  229 172 9  246 218 19
+  246 218 19  41 27 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  19 19 19  27 27 27  196 154 14
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  199 140 8  229 172 9  242 182 11
+  245 189 11  245 189 11  245 189 11  244 196 10  2 2 3
+  2 2 3  115 115 115  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  245 245 245  228 228 228  254 254 252
+  254 254 252  245 245 245  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  224 165 9  245 189 11
+  236 196 11  19 19 19  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  11 11 11  236 196 11
+  244 205 11  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  182 126 10  209 156 9  215 150 13
+  193 140 10  207 148 24  216 156 8  242 182 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  209 156 9
+  2 2 3  2 2 3  43 43 43  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  245 245 245
+  254 254 252  254 254 252  254 254 252  254 254 252  245 245 245
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  236 236 236  216 156 8  245 189 11
+  229 172 9  64 43 7  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  207 148 7  236 188 10
+  245 189 11  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  180 121 7  216 156 8  242 182 11  236 180 10
+  229 172 9  242 182 11  242 182 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  237 204 14
+  170 126 10  2 2 3  2 2 3  11 11 11  236 236 236
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  204 204 204  196 196 196  216 156 8  236 180 10
+  224 165 9  182 126 10  73 48 6  2 2 3  2 2 3
+  2 2 3  41 27 3  199 140 8  229 172 9  236 180 10
+  245 189 11  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  185 132 9  229 172 9  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  226 188 11  2 2 3  2 2 3  2 2 3  11 11 11
+  245 245 245  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  245 245 245  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  196 196 196  196 196 196  215 150 13  236 180 10
+  229 172 9  201 142 7  185 132 9  180 121 7  173 120 10
+  180 121 7  192 133 7  229 172 9  242 182 11  245 189 11
+  245 189 11  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  180 126 47  224 165 9  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  236 188 10  193 140 10  2 2 3  2 2 3  2 2 3
+  2 2 3  212 212 212  254 254 252  245 245 245  245 245 245
+  254 254 252  254 254 252  254 254 252  245 245 245  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  204 204 204  196 196 196  199 140 8  229 172 9
+  236 180 10  218 164 9  215 150 13  207 148 7  207 148 7
+  216 156 8  229 172 9  245 189 11  245 189 11  245 189 11
+  245 189 11  242 182 11  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  185 132 9  216 156 8  242 182 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  236 196 11  19 19 19  2 2 3  2 2 3
+  2 2 3  11 11 11  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  245 245 245  254 254 252  254 254 252
+  245 245 245  221 221 220  196 196 196  185 132 9  229 172 9
+  242 182 11  229 172 9  224 165 9  218 164 9  224 165 9
+  229 172 9  236 180 10  245 189 11  245 189 11  245 189 11
+  245 189 11  236 180 22  242 182 11  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  236 180 22  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  236 188 10  225 180 10  2 2 3  2 2 3
+  2 2 3  11 11 11  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  221 221 220  19 19 19  185 132 9  224 165 9
+  245 189 11  245 189 11  242 182 11  236 180 10  236 180 10
+  242 182 11  242 182 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  196 154 14
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  207 148 7  236 180 22  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  242 182 11
+  245 189 11  245 189 11  237 204 14  135 88 5  2 2 3
+  27 27 27  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  245 245 245  254 254 252  254 254 252  245 245 245
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  67 67 67  19 13 3  185 132 9  229 172 9
+  242 182 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  236 180 22  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  245 189 11  242 182 11
+  242 182 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  236 188 10  226 188 11  104 83 48
+  254 254 252  254 254 252  254 254 252  254 254 252  245 245 245
+  254 254 252  254 254 252  245 245 245  254 254 252  245 245 245
+  254 254 252  245 245 245  254 254 252  254 254 252  254 254 252
+  2 2 3  2 2 3  56 38 5  185 132 9  229 172 9
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  242 182 11
+  229 172 9  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  182 126 10  215 150 13  242 182 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  242 182 11  245 189 11  236 196 11  216 156 8
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  245 245 245  2 2 3
+  2 2 3  2 2 3  75 54 3  182 126 10  229 172 9
+  242 182 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  229 172 9
+  207 148 24  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  192 133 7  229 172 9  242 182 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  242 182 11  225 180 10  224 165 9
+  107 69 5  245 245 245  254 254 252  254 254 252  254 254 252
+  254 254 252  254 254 252  254 254 252  254 254 252  254 254 252
+  254 254 252  236 236 236  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  91 67 9  182 126 10  229 172 9
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  242 182 11  242 182 11  216 156 8  180 126 47
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  206 142 8  224 165 9  245 189 11  242 182 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  242 182 11
+  245 189 11  245 189 11  242 182 11  242 182 11  216 156 8
+  156 102 5  19 13 3  43 43 43  196 196 196  254 254 252
+  245 245 245  254 254 252  254 254 252  204 204 204  51 51 51
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  95 62 5  185 132 9  229 172 9
+  242 182 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  242 182 11  245 189 11  245 189 11
+  236 180 22  216 156 8  206 142 8  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  192 133 7  215 150 13  229 172 9  229 172 9
+  236 180 10  236 180 22  242 182 11  242 182 11  245 189 11
+  245 189 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  245 189 11  245 189 11  229 172 9  216 156 8
+  156 102 5  83 54 6  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  115 73 3  185 132 9  229 172 9
+  242 182 11  245 189 11  245 189 11  245 189 11  245 189 11
+  245 189 11  242 182 11  229 172 9  229 172 9  216 156 8
+  180 121 7  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  180 121 7  182 126 10  192 133 7  199 140 8
+  207 148 7  215 150 13  216 156 8  224 165 9  229 172 9
+  236 180 22  245 189 11  242 182 11  245 189 11  242 182 11
+  245 189 11  245 189 11  242 182 11  229 172 9  199 140 8
+  151 97 5  101 67 7  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  115 73 3  180 121 7  216 156 8
+  236 180 22  242 182 11  245 189 11  245 189 11  242 182 11
+  236 180 10  224 165 9  215 150 13  206 142 8  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  156 102 5  164 109 5  172 114 5  180 121 7  180 121 7
+  192 133 7  201 142 7  216 156 8  224 165 9  236 180 22
+  245 189 11  242 182 11  229 172 9  201 142 7  172 114 5
+  125 83 5  83 54 6  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  2 2 3  2 2 3  2 2 3
+  2 2 3  2 2 3  91 58 5  156 102 5  192 133 7
+  216 156 8  229 172 9  236 180 10  236 180 10  229 172 9
+  215 150 13  199 140 8  164 109 5  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  120 78 3  132 82 3
+  151 97 5  157 106 7  180 121 7  185 132 9  193 140 10
+  207 148 7  207 148 7  192 133 7  172 114 5  132 82 3
+  101 67 7  41 27 3  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  73 48 6  143 90 3  180 121 7
+  192 133 7  207 148 7  207 148 7  201 142 7  185 132 9
+  173 120 10  136 95 7  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  91 58 5  125 83 5  135 88 5
+  144 95 7  151 97 5  132 82 3  115 73 3  95 62 5
+  64 43 7  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  64 43 7  91 58 5  151 97 5
+  157 106 7  172 114 5  172 114 5  164 109 5  151 97 5
+  85 59 6  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  73 48 6
+  91 58 5  95 62 5  95 62 5  91 58 5  56 38 5
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  83 54 6
+  107 69 5  132 82 3  125 83 5  101 67 7  71 47 31
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
+  215 150 13  215 150 13  215 150 13  215 150 13  215 150 13
index 789de13f461f689280e2b94c78b50c18387bfe0f..3848be2b9d2d6e9a30194dd693f368c70d1d1dfa 100644 (file)
@@ -67,12 +67,18 @@ static struct fb_fix_screeninfo __devinitdata s1d13xxxfb_fix = {
 static inline u8
 s1d13xxxfb_readreg(struct s1d13xxxfb_par *par, u16 regno)
 {
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI3)
+       regno=((regno & 1) ? (regno & ~1L) : (regno + 1));
+#endif
        return readb(par->regs + regno);
 }
 
 static inline void
 s1d13xxxfb_writereg(struct s1d13xxxfb_par *par, u16 regno, u8 value)
 {
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI3)
+       regno=((regno & 1) ? (regno & ~1L) : (regno + 1));
+#endif
        writeb(value, par->regs + regno);
 }
 
@@ -259,7 +265,11 @@ s1d13xxxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                        dbg("s1d13xxxfb_setcolreg: pseudo %d, val %08x\n",
                                    regno, pseudo_val);
 
+#if defined(CONFIG_PLAT_MAPPI)
+                       ((u32 *)info->pseudo_palette)[regno] = cpu_to_le16(pseudo_val);
+#else
                        ((u32 *)info->pseudo_palette)[regno] = pseudo_val;
+#endif
 
                        break;
                case FB_VISUAL_PSEUDOCOLOR:
index 8fadcdae6f426216200ed6659dd3cfbca031e57f..f4633d1891f121070b68ae5c4cb4f53cf0d76ddc 100644 (file)
@@ -2113,7 +2113,7 @@ static int savagefb_suspend (struct pci_dev* dev, pm_message_t state)
        printk(KERN_DEBUG "state: %u\n", state);
 
        acquire_console_sem();
-       fb_set_suspend(info, state);
+       fb_set_suspend(info, pci_choose_state(dev, state));
        savage_disable_mmio(par);
        release_console_sem();
 
index 062177956239b1c25c6199579e9f72faecc21212..aae0686a15fbbf456b00c4c71b5422bb082e74c1 100644 (file)
@@ -29,6 +29,7 @@ config EXT2_FS_XATTR
 config EXT2_FS_POSIX_ACL
        bool "Ext2 POSIX Access Control Lists"
        depends on EXT2_FS_XATTR
+       select FS_POSIX_ACL
        help
          Posix Access Control Lists (ACLs) support permissions for users and
          groups beyond the owner/group/world scheme.
@@ -114,6 +115,7 @@ config EXT3_FS_XATTR
 config EXT3_FS_POSIX_ACL
        bool "Ext3 POSIX Access Control Lists"
        depends on EXT3_FS_XATTR
+       select FS_POSIX_ACL
        help
          Posix Access Control Lists (ACLs) support permissions for users and
          groups beyond the owner/group/world scheme.
@@ -241,6 +243,7 @@ config REISERFS_FS_XATTR
 config REISERFS_FS_POSIX_ACL
        bool "ReiserFS POSIX Access Control Lists"
        depends on REISERFS_FS_XATTR
+       select FS_POSIX_ACL
        help
          Posix Access Control Lists (ACLs) support permissions for users and
          groups beyond the owner/group/world scheme.
@@ -274,6 +277,7 @@ config JFS_FS
 config JFS_POSIX_ACL
        bool "JFS POSIX Access Control Lists"
        depends on JFS_FS
+       select FS_POSIX_ACL
        help
          Posix Access Control Lists (ACLs) support permissions for users and
          groups beyond the owner/group/world scheme.
@@ -318,8 +322,7 @@ config FS_POSIX_ACL
 #      Never use this symbol for ifdefs.
 #
        bool
-       depends on EXT2_FS_POSIX_ACL || EXT3_FS_POSIX_ACL || JFS_POSIX_ACL || REISERFS_FS_POSIX_ACL || NFSD_V4
-       default y
+       default n
 
 source "fs/xfs/Kconfig"
 
@@ -1438,6 +1441,7 @@ config NFSD_V4
        select NFSD_TCP
        select CRYPTO_MD5
        select CRYPTO
+       select FS_POSIX_ACL
        help
          If you would like to include the NFSv4 server as well as the NFSv2
          and NFSv3 servers, say Y here.  This feature is experimental, and
index fa2348dcd6718732c3f8bfb4ad2ecfe52c323aad..3df86285a1c7e981e054d145fb134b89673336ab 100644 (file)
@@ -231,8 +231,8 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
                int type = (notify == NFY_MOUNT ?
                        autofs_ptype_missing : autofs_ptype_expire_multi);
 
-               DPRINTK(("new wait id = 0x%08lx, name = %.*s, nfy=%d\n",
-                       (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify));
+               DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d\n",
+                       (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
 
                /* autofs4_notify_daemon() may block */
                autofs4_notify_daemon(sbi, wq, type);
index 3a1472acc361ef0e95f03843cac07f5b92f23e61..ca8f7a850fe30aa27cb6e3b524464197bd76f3c8 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -52,7 +52,7 @@ struct biovec_slab {
  */
 
 #define BV(x) { .nr_vecs = x, .name = "biovec-"__stringify(x) }
-static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] = {
+static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = {
        BV(1), BV(4), BV(16), BV(64), BV(128), BV(BIO_MAX_PAGES),
 };
 #undef BV
index 561e63a149667abafef2c92aabe287e0eae2f27d..6a25d7df89b176db6bb7163517538476398a9af4 100644 (file)
@@ -513,8 +513,8 @@ static void free_more_memory(void)
  */
 static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
 {
-       static DEFINE_SPINLOCK(page_uptodate_lock);
        unsigned long flags;
+       struct buffer_head *first;
        struct buffer_head *tmp;
        struct page *page;
        int page_uptodate = 1;
@@ -536,7 +536,9 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
         * two buffer heads end IO at almost the same time and both
         * decide that the page is now completely done.
         */
-       spin_lock_irqsave(&page_uptodate_lock, flags);
+       first = page_buffers(page);
+       local_irq_save(flags);
+       bit_spin_lock(BH_Uptodate_Lock, &first->b_state);
        clear_buffer_async_read(bh);
        unlock_buffer(bh);
        tmp = bh;
@@ -549,7 +551,8 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
                }
                tmp = tmp->b_this_page;
        } while (tmp != bh);
-       spin_unlock_irqrestore(&page_uptodate_lock, flags);
+       bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
+       local_irq_restore(flags);
 
        /*
         * If none of the buffers had errors and they are all
@@ -561,7 +564,8 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
        return;
 
 still_busy:
-       spin_unlock_irqrestore(&page_uptodate_lock, flags);
+       bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
+       local_irq_restore(flags);
        return;
 }
 
@@ -572,8 +576,8 @@ still_busy:
 void end_buffer_async_write(struct buffer_head *bh, int uptodate)
 {
        char b[BDEVNAME_SIZE];
-       static DEFINE_SPINLOCK(page_uptodate_lock);
        unsigned long flags;
+       struct buffer_head *first;
        struct buffer_head *tmp;
        struct page *page;
 
@@ -594,7 +598,10 @@ void end_buffer_async_write(struct buffer_head *bh, int uptodate)
                SetPageError(page);
        }
 
-       spin_lock_irqsave(&page_uptodate_lock, flags);
+       first = page_buffers(page);
+       local_irq_save(flags);
+       bit_spin_lock(BH_Uptodate_Lock, &first->b_state);
+
        clear_buffer_async_write(bh);
        unlock_buffer(bh);
        tmp = bh->b_this_page;
@@ -605,12 +612,14 @@ void end_buffer_async_write(struct buffer_head *bh, int uptodate)
                }
                tmp = tmp->b_this_page;
        }
-       spin_unlock_irqrestore(&page_uptodate_lock, flags);
+       bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
+       local_irq_restore(flags);
        end_page_writeback(page);
        return;
 
 still_busy:
-       spin_unlock_irqrestore(&page_uptodate_lock, flags);
+       bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
+       local_irq_restore(flags);
        return;
 }
 
index 581aac959cd3a71f8f675909432fb5defdbe4ed9..02aa0ddc582a6a169fe855883cf069923e63bb74 100644 (file)
@@ -94,12 +94,10 @@ static struct dcookie_struct * alloc_dcookie(struct dentry * dentry,
        if (!dcs)
                return NULL;
 
-       atomic_inc(&dentry->d_count);
-       atomic_inc(&vfsmnt->mnt_count);
        dentry->d_cookie = dcs;
 
-       dcs->dentry = dentry;
-       dcs->vfsmnt = vfsmnt;
+       dcs->dentry = dget(dentry);
+       dcs->vfsmnt = mntget(vfsmnt);
        hash_dcookie(dcs);
 
        return dcs;
index 0b2db4f618cbec499832a0969b14f827a839245c..9989fdcf4d5aba4c00e07bd7826e9ccb639624f3 100644 (file)
@@ -2663,7 +2663,7 @@ static int ext3_do_update_inode(handle_t *handle,
        } else for (block = 0; block < EXT3_N_BLOCKS; block++)
                raw_inode->i_block[block] = ei->i_data[block];
 
-       if (EXT3_INODE_SIZE(inode->i_sb) > EXT3_GOOD_OLD_INODE_SIZE)
+       if (ei->i_extra_isize)
                raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize);
 
        BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
index f8e0cbd0cb60b1c6fddf14a791448292347ff1e4..6f553e17c3758bc18a4fa70633a22dbaf1a4f007 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/file.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -491,7 +492,7 @@ static int hppfs_open(struct inode *inode, struct file *file)
                fd = open_host_sock(host_file, &filter);
                if(fd > 0){
                        data->contents = hppfs_get_data(fd, filter,
-                                                       &data->proc_file,
+                                                       data->proc_file,
                                                        file, &data->len);
                        if(!IS_ERR(data->contents))
                                data->host_fd = fd;
@@ -543,7 +544,7 @@ static int hppfs_dir_open(struct inode *inode, struct file *file)
 static loff_t hppfs_llseek(struct file *file, loff_t off, int where)
 {
        struct hppfs_private *data = file->private_data;
-       struct file *proc_file = &data->proc_file;
+       struct file *proc_file = data->proc_file;
        loff_t (*llseek)(struct file *, loff_t, int);
        loff_t ret;
 
@@ -586,7 +587,7 @@ static int hppfs_filldir(void *d, const char *name, int size,
 static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir)
 {
        struct hppfs_private *data = file->private_data;
-       struct file *proc_file = &data->proc_file;
+       struct file *proc_file = data->proc_file;
        int (*readdir)(struct file *, void *, filldir_t);
        struct hppfs_dirent dirent = ((struct hppfs_dirent)
                                      { .vfs_dirent     = ent,
index 1f9a3a2b89bc67add68e90faa78612ebf6e884cf..6d695037a0a3df62f6f977091881ae7a596705c9 100644 (file)
@@ -1052,7 +1052,7 @@ static void generic_forget_inode(struct inode *inode)
  * inode when the usage count drops to zero, and
  * i_nlink is zero.
  */
-static void generic_drop_inode(struct inode *inode)
+void generic_drop_inode(struct inode *inode)
 {
        if (!inode->i_nlink)
                generic_delete_inode(inode);
@@ -1060,6 +1060,8 @@ static void generic_drop_inode(struct inode *inode)
                generic_forget_inode(inode);
 }
 
+EXPORT_SYMBOL_GPL(generic_drop_inode);
+
 /*
  * Called when we're dropping the last reference
  * to an inode. 
index 663e420636d6b76e147d1b1e3984acc5aefd115a..97e1f088ba00b3b63f7f9ea594b756781fcf6596 100644 (file)
@@ -43,7 +43,7 @@ static int set_task_ioprio(struct task_struct *task, int ioprio)
        return 0;
 }
 
-asmlinkage int sys_ioprio_set(int which, int who, int ioprio)
+asmlinkage long sys_ioprio_set(int which, int who, int ioprio)
 {
        int class = IOPRIO_PRIO_CLASS(ioprio);
        int data = IOPRIO_PRIO_DATA(ioprio);
@@ -115,7 +115,7 @@ asmlinkage int sys_ioprio_set(int which, int who, int ioprio)
        return ret;
 }
 
-asmlinkage int sys_ioprio_get(int which, int who)
+asmlinkage long sys_ioprio_get(int which, int who)
 {
        struct task_struct *g, *p;
        struct user_struct *user;
index a0bc03495bd44e23bfa89deb6c492ee2a9ccfcb8..29fa5da6c1170cab553b17b85eab000a2056793d 100644 (file)
@@ -1276,7 +1276,7 @@ int fcntl_getlease(struct file *filp)
  */
 static int __setlease(struct file *filp, long arg, struct file_lock **flp)
 {
-       struct file_lock *fl, **before, **my_before = NULL, *lease = *flp;
+       struct file_lock *fl, **before, **my_before = NULL, *lease;
        struct dentry *dentry = filp->f_dentry;
        struct inode *inode = dentry->d_inode;
        int error, rdlease_count = 0, wrlease_count = 0;
@@ -1287,6 +1287,8 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
        if (!flp || !(*flp) || !(*flp)->fl_lmops || !(*flp)->fl_lmops->fl_break)
                goto out;
 
+       lease = *flp;
+
        error = -EAGAIN;
        if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
                goto out;
index fa8df81ce8cadd841e7f73aff5a40aa59dfcf73b..1d93cb4f7c5fdef37ff0ce60daeb6edbad8d12aa 100644 (file)
@@ -314,7 +314,7 @@ void path_release(struct nameidata *nd)
 void path_release_on_umount(struct nameidata *nd)
 {
        dput(nd->dentry);
-       _mntput(nd->mnt);
+       mntput_no_expire(nd->mnt);
 }
 
 /*
index 208c079e9fdbf240ce848e27903b237c9c9d764f..587eb0d707ee8d7fd4119aee67c5e4791f4d9d9e 100644 (file)
@@ -61,7 +61,7 @@ struct vfsmount *alloc_vfsmnt(const char *name)
                INIT_LIST_HEAD(&mnt->mnt_child);
                INIT_LIST_HEAD(&mnt->mnt_mounts);
                INIT_LIST_HEAD(&mnt->mnt_list);
-               INIT_LIST_HEAD(&mnt->mnt_fslink);
+               INIT_LIST_HEAD(&mnt->mnt_expire);
                if (name) {
                        int size = strlen(name)+1;
                        char *newname = kmalloc(size, GFP_KERNEL);
@@ -165,8 +165,8 @@ clone_mnt(struct vfsmount *old, struct dentry *root)
                /* stick the duplicate mount on the same expiry list
                 * as the original if that was on one */
                spin_lock(&vfsmount_lock);
-               if (!list_empty(&old->mnt_fslink))
-                       list_add(&mnt->mnt_fslink, &old->mnt_fslink);
+               if (!list_empty(&old->mnt_expire))
+                       list_add(&mnt->mnt_expire, &old->mnt_expire);
                spin_unlock(&vfsmount_lock);
        }
        return mnt;
@@ -345,12 +345,13 @@ static void umount_tree(struct vfsmount *mnt)
        for (p = mnt; p; p = next_mnt(p, mnt)) {
                list_del(&p->mnt_list);
                list_add(&p->mnt_list, &kill);
+               p->mnt_namespace = NULL;
        }
 
        while (!list_empty(&kill)) {
                mnt = list_entry(kill.next, struct vfsmount, mnt_list);
                list_del_init(&mnt->mnt_list);
-               list_del_init(&mnt->mnt_fslink);
+               list_del_init(&mnt->mnt_expire);
                if (mnt->mnt_parent == mnt) {
                        spin_unlock(&vfsmount_lock);
                } else {
@@ -644,7 +645,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse)
        if (mnt) {
                /* stop bind mounts from expiring */
                spin_lock(&vfsmount_lock);
-               list_del_init(&mnt->mnt_fslink);
+               list_del_init(&mnt->mnt_expire);
                spin_unlock(&vfsmount_lock);
 
                err = graft_tree(mnt, nd);
@@ -743,7 +744,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name)
 
        /* if the mount is moved, it should no longer be expire
         * automatically */
-       list_del_init(&old_nd.mnt->mnt_fslink);
+       list_del_init(&old_nd.mnt->mnt_expire);
 out2:
        spin_unlock(&vfsmount_lock);
 out1:
@@ -807,12 +808,13 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd,
                goto unlock;
 
        newmnt->mnt_flags = mnt_flags;
+       newmnt->mnt_namespace = current->namespace;
        err = graft_tree(newmnt, nd);
 
        if (err == 0 && fslist) {
                /* add to the specified expiration list */
                spin_lock(&vfsmount_lock);
-               list_add_tail(&newmnt->mnt_fslink, fslist);
+               list_add_tail(&newmnt->mnt_expire, fslist);
                spin_unlock(&vfsmount_lock);
        }
 
@@ -824,6 +826,54 @@ unlock:
 
 EXPORT_SYMBOL_GPL(do_add_mount);
 
+static void expire_mount(struct vfsmount *mnt, struct list_head *mounts)
+{
+       spin_lock(&vfsmount_lock);
+
+       /*
+        * Check if mount is still attached, if not, let whoever holds it deal
+        * with the sucker
+        */
+       if (mnt->mnt_parent == mnt) {
+               spin_unlock(&vfsmount_lock);
+               return;
+       }
+
+       /*
+        * Check that it is still dead: the count should now be 2 - as
+        * contributed by the vfsmount parent and the mntget above
+        */
+       if (atomic_read(&mnt->mnt_count) == 2) {
+               struct nameidata old_nd;
+
+               /* delete from the namespace */
+               list_del_init(&mnt->mnt_list);
+               mnt->mnt_namespace = NULL;
+               detach_mnt(mnt, &old_nd);
+               spin_unlock(&vfsmount_lock);
+               path_release(&old_nd);
+
+               /*
+                * Now lay it to rest if this was the last ref on the superblock
+                */
+               if (atomic_read(&mnt->mnt_sb->s_active) == 1) {
+                       /* last instance - try to be smart */
+                       lock_kernel();
+                       DQUOT_OFF(mnt->mnt_sb);
+                       acct_auto_close(mnt->mnt_sb);
+                       unlock_kernel();
+               }
+               mntput(mnt);
+       } else {
+               /*
+                * Someone brought it back to life whilst we didn't have any
+                * locks held so return it to the expiration list
+                */
+               list_add_tail(&mnt->mnt_expire, mounts);
+               spin_unlock(&vfsmount_lock);
+       }
+}
+
 /*
  * process a list of expirable mountpoints with the intent of discarding any
  * mountpoints that aren't in use and haven't been touched since last we came
@@ -846,13 +896,13 @@ void mark_mounts_for_expiry(struct list_head *mounts)
         * - still marked for expiry (marked on the last call here; marks are
         *   cleared by mntput())
         */
-       list_for_each_entry_safe(mnt, next, mounts, mnt_fslink) {
+       list_for_each_entry_safe(mnt, next, mounts, mnt_expire) {
                if (!xchg(&mnt->mnt_expiry_mark, 1) ||
                    atomic_read(&mnt->mnt_count) != 1)
                        continue;
 
                mntget(mnt);
-               list_move(&mnt->mnt_fslink, &graveyard);
+               list_move(&mnt->mnt_expire, &graveyard);
        }
 
        /*
@@ -862,61 +912,19 @@ void mark_mounts_for_expiry(struct list_head *mounts)
         * - dispose of the corpse
         */
        while (!list_empty(&graveyard)) {
-               mnt = list_entry(graveyard.next, struct vfsmount, mnt_fslink);
-               list_del_init(&mnt->mnt_fslink);
+               mnt = list_entry(graveyard.next, struct vfsmount, mnt_expire);
+               list_del_init(&mnt->mnt_expire);
 
                /* don't do anything if the namespace is dead - all the
                 * vfsmounts from it are going away anyway */
                namespace = mnt->mnt_namespace;
-               if (!namespace || atomic_read(&namespace->count) <= 0)
+               if (!namespace || !namespace->root)
                        continue;
                get_namespace(namespace);
 
                spin_unlock(&vfsmount_lock);
                down_write(&namespace->sem);
-               spin_lock(&vfsmount_lock);
-
-               /* check that it is still dead: the count should now be 2 - as
-                * contributed by the vfsmount parent and the mntget above */
-               if (atomic_read(&mnt->mnt_count) == 2) {
-                       struct vfsmount *xdmnt;
-                       struct dentry *xdentry;
-
-                       /* delete from the namespace */
-                       list_del_init(&mnt->mnt_list);
-                       list_del_init(&mnt->mnt_child);
-                       list_del_init(&mnt->mnt_hash);
-                       mnt->mnt_mountpoint->d_mounted--;
-
-                       xdentry = mnt->mnt_mountpoint;
-                       mnt->mnt_mountpoint = mnt->mnt_root;
-                       xdmnt = mnt->mnt_parent;
-                       mnt->mnt_parent = mnt;
-
-                       spin_unlock(&vfsmount_lock);
-
-                       mntput(xdmnt);
-                       dput(xdentry);
-
-                       /* now lay it to rest if this was the last ref on the
-                        * superblock */
-                       if (atomic_read(&mnt->mnt_sb->s_active) == 1) {
-                               /* last instance - try to be smart */
-                               lock_kernel();
-                               DQUOT_OFF(mnt->mnt_sb);
-                               acct_auto_close(mnt->mnt_sb);
-                               unlock_kernel();
-                       }
-
-                       mntput(mnt);
-               } else {
-                       /* someone brought it back to life whilst we didn't
-                        * have any locks held so return it to the expiration
-                        * list */
-                       list_add_tail(&mnt->mnt_fslink, mounts);
-                       spin_unlock(&vfsmount_lock);
-               }
-
+               expire_mount(mnt, mounts);
                up_write(&namespace->sem);
 
                mntput(mnt);
@@ -1449,16 +1457,12 @@ void __init mnt_init(unsigned long mempages)
 
 void __put_namespace(struct namespace *namespace)
 {
-       struct vfsmount *mnt;
-
+       struct vfsmount *root = namespace->root;
+       namespace->root = NULL;
+       spin_unlock(&vfsmount_lock);
        down_write(&namespace->sem);
        spin_lock(&vfsmount_lock);
-
-       list_for_each_entry(mnt, &namespace->list, mnt_list) {
-               mnt->mnt_namespace = NULL;
-       }
-
-       umount_tree(namespace->root);
+       umount_tree(root);
        spin_unlock(&vfsmount_lock);
        up_write(&namespace->sem);
        kfree(namespace);
index d71f14517b9c09fc7cae2209b8c62a9777a427d7..e08edc17c6a038d7f78791c2f7d175e729ec903b 100644 (file)
@@ -169,12 +169,6 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
                (int)open->op_fname.len, open->op_fname.data,
                open->op_stateowner);
 
-       if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
-               return nfserr_grace;
-
-       if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
-               return nfserr_no_grace;
-
        /* This check required by spec. */
        if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
                return nfserr_inval;
index 095f1740f3aeeb2b98939006f8e408d79311a5dc..57ed50fe7f8568be7f4408b292ee36a3d1a8ab4e 100644 (file)
@@ -119,25 +119,12 @@ out:
        return status;
 }
 
-static int
-nfsd4_rec_fsync(struct dentry *dentry)
+static void
+nfsd4_sync_rec_dir(void)
 {
-       struct file *filp;
-       int status = nfs_ok;
-
-       dprintk("NFSD: nfs4_fsync_rec_dir\n");
-       filp = dentry_open(dget(dentry), mntget(rec_dir.mnt), O_RDWR);
-       if (IS_ERR(filp)) {
-               status = PTR_ERR(filp);
-               goto out;
-       }
-       if (filp->f_op && filp->f_op->fsync)
-               status = filp->f_op->fsync(filp, filp->f_dentry, 0);
-       fput(filp);
-out:
-       if (status)
-               printk("nfsd4: unable to sync recovery directory\n");
-       return status;
+       down(&rec_dir.dentry->d_inode->i_sem);
+       nfsd_sync_dir(rec_dir.dentry);
+       up(&rec_dir.dentry->d_inode->i_sem);
 }
 
 int
@@ -176,7 +163,7 @@ out_unlock:
        up(&rec_dir.dentry->d_inode->i_sem);
        if (status == 0) {
                clp->cl_firststate = 1;
-               status = nfsd4_rec_fsync(rec_dir.dentry);
+               nfsd4_sync_rec_dir();
        }
        nfs4_reset_user(uid, gid);
        dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status);
@@ -302,7 +289,9 @@ nfsd4_unlink_clid_dir(char *name, int namlen)
 
        dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
 
+       down(&rec_dir.dentry->d_inode->i_sem);
        dentry = lookup_one_len(name, rec_dir.dentry, namlen);
+       up(&rec_dir.dentry->d_inode->i_sem);
        if (IS_ERR(dentry)) {
                status = PTR_ERR(dentry);
                return status;
@@ -327,11 +316,12 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
        if (!rec_dir_init || !clp->cl_firststate)
                return;
 
+       clp->cl_firststate = 0;
        nfs4_save_user(&uid, &gid);
        status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
        nfs4_reset_user(uid, gid);
        if (status == 0)
-               status = nfsd4_rec_fsync(rec_dir.dentry);
+               nfsd4_sync_rec_dir();
        if (status)
                printk("NFSD: Failed to remove expired client state directory"
                                " %.*s\n", HEXDIR_LEN, clp->cl_recdir);
@@ -362,7 +352,7 @@ nfsd4_recdir_purge_old(void) {
                return;
        status = nfsd4_list_rec_dir(rec_dir.dentry, purge_old);
        if (status == 0)
-               status = nfsd4_rec_fsync(rec_dir.dentry);
+               nfsd4_sync_rec_dir();
        if (status)
                printk("nfsd4: failed to purge old clients from recovery"
                        " directory %s\n", rec_dir.dentry->d_name.name);
index 89e36526d7f289f32873fe856bd9421d89288311..b83f8fb441e15328ed9cff30099a7f637151124d 100644 (file)
@@ -874,6 +874,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
                          * change request correctly. */
                        atomic_set(&conf->cl_callback.cb_set, 0);
                        gen_confirm(conf);
+                       nfsd4_remove_clid_dir(unconf);
                        expire_client(unconf);
                        status = nfs_ok;
 
@@ -1159,6 +1160,7 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *
        stp->st_deny_bmap = 0;
        __set_bit(open->op_share_access, &stp->st_access_bmap);
        __set_bit(open->op_share_deny, &stp->st_deny_bmap);
+       stp->st_openstp = NULL;
 }
 
 static void
@@ -1294,7 +1296,7 @@ nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
        fp = find_file(ino);
        if (!fp)
                return nfs_ok;
-       ret = nfserr_share_denied;
+       ret = nfserr_locked;
        /* Search for conflicting share reservations */
        list_for_each_entry(stp, &fp->fi_stateids, st_perfile) {
                if (test_bit(deny_type, &stp->st_deny_bmap) ||
@@ -1482,7 +1484,7 @@ nfsd4_process_open1(struct nfsd4_open *open)
        if (sop) {
                open->op_stateowner = sop;
                /* check for replay */
-               if (open->op_seqid == sop->so_seqid){
+               if (open->op_seqid == sop->so_seqid - 1){
                        if (sop->so_replay.rp_buflen)
                                return NFSERR_REPLAY_ME;
                        else {
@@ -1497,7 +1499,7 @@ nfsd4_process_open1(struct nfsd4_open *open)
                                goto renew;
                        }
                } else if (sop->so_confirmed) {
-                       if (open->op_seqid == sop->so_seqid + 1)
+                       if (open->op_seqid == sop->so_seqid)
                                goto renew;
                        status = nfserr_bad_seqid;
                        goto out;
@@ -1530,8 +1532,6 @@ renew:
        status = nfs_ok;
        renew_client(sop->so_client);
 out:
-       if (status && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
-               status = nfserr_reclaim_bad;
        return status;
 }
 
@@ -1685,19 +1685,11 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta
 }
 
 
-/* decrement seqid on successful reclaim, it will be bumped in encode_open */
 static void
-nfs4_set_claim_prev(struct nfsd4_open *open, int *status)
+nfs4_set_claim_prev(struct nfsd4_open *open)
 {
-       if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) {
-               if (*status)
-                       *status = nfserr_reclaim_bad;
-               else {
-                       open->op_stateowner->so_confirmed = 1;
-                       open->op_stateowner->so_client->cl_firststate = 1;
-                       open->op_stateowner->so_seqid--;
-               }
-       }
+       open->op_stateowner->so_confirmed = 1;
+       open->op_stateowner->so_client->cl_firststate = 1;
 }
 
 /*
@@ -1789,6 +1781,12 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
        struct nfs4_delegation *dp = NULL;
        int status;
 
+       if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
+               return nfserr_grace;
+
+       if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
+               return nfserr_no_grace;
+
        status = nfserr_inval;
        if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny))
                goto out;
@@ -1823,6 +1821,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
                status = nfs4_upgrade_open(rqstp, current_fh, stp, open);
                if (status)
                        goto out;
+               update_stateid(&stp->st_stateid);
        } else {
                /* Stateid was not found, this is a new OPEN */
                int flags = 0;
@@ -1856,8 +1855,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
 out:
        if (fp)
                put_nfs4_file(fp);
-       /* CLAIM_PREVIOUS has different error returns */
-       nfs4_set_claim_prev(open, &status);
+       if (status == 0 && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
+               nfs4_set_claim_prev(open);
        /*
        * To finish the open response, we just need to set the rflags.
        */
@@ -1990,14 +1989,11 @@ laundromat_main(void *not_used)
        queue_delayed_work(laundry_wq, &laundromat_work, t*HZ);
 }
 
-/* search ownerid_hashtbl[] and close_lru for stateid owner
- * (stateid->si_stateownerid)
- */
 static struct nfs4_stateowner *
-find_openstateowner_id(u32 st_id, int flags) {
+search_close_lru(u32 st_id, int flags)
+{
        struct nfs4_stateowner *local = NULL;
 
-       dprintk("NFSD: find_openstateowner_id %d\n", st_id);
        if (flags & CLOSE_STATE) {
                list_for_each_entry(local, &close_lru, so_close_lru) {
                        if (local->so_id == st_id)
@@ -2163,14 +2159,19 @@ out:
        return status;
 }
 
+static inline int
+setlkflg (int type)
+{
+       return (type == NFS4_READW_LT || type == NFS4_READ_LT) ?
+               RD_STATE : WR_STATE;
+}
 
 /* 
  * Checks for sequence id mutating operations. 
  */
 static int
-nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid)
+nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, struct nfsd4_lock *lock)
 {
-       int status;
        struct nfs4_stateid *stp;
        struct nfs4_stateowner *sop;
 
@@ -2178,53 +2179,65 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
                        "stateid = (%08x/%08x/%08x/%08x)\n", seqid,
                stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
                stateid->si_generation);
-                               
+
        *stpp = NULL;
        *sopp = NULL;
 
-       status = nfserr_bad_stateid;
        if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {
                printk("NFSD: preprocess_seqid_op: magic stateid!\n");
-               goto out;
+               return nfserr_bad_stateid;
        }
 
-       status = nfserr_stale_stateid;
        if (STALE_STATEID(stateid))
-               goto out;
+               return nfserr_stale_stateid;
        /*
        * We return BAD_STATEID if filehandle doesn't match stateid, 
        * the confirmed flag is incorrecly set, or the generation 
        * number is incorrect.  
-       * If there is no entry in the openfile table for this id, 
-       * we can't always return BAD_STATEID;
-       * this might be a retransmitted CLOSE which has arrived after 
-       * the openfile has been released.
        */
-       if (!(stp = find_stateid(stateid, flags)))
-               goto no_nfs4_stateid;
-
-       status = nfserr_bad_stateid;
+       stp = find_stateid(stateid, flags);
+       if (stp == NULL) {
+               /*
+                * Also, we should make sure this isn't just the result of
+                * a replayed close:
+                */
+               sop = search_close_lru(stateid->si_stateownerid, flags);
+               if (sop == NULL)
+                       return nfserr_bad_stateid;
+               *sopp = sop;
+               goto check_replay;
+       }
 
-       /* for new lock stateowners:
-        * check that the lock->v.new.open_stateid
-        * refers to an open stateowner
-        *
-        * check that the lockclid (nfs4_lock->v.new.clientid) is the same
-        * as the open_stateid->st_stateowner->so_client->clientid
-        */
-       if (lockclid) {
+       if (lock) {
                struct nfs4_stateowner *sop = stp->st_stateowner;
+               clientid_t *lockclid = &lock->v.new.clientid;
                struct nfs4_client *clp = sop->so_client;
+               int lkflg = 0;
+               int status;
+
+               lkflg = setlkflg(lock->lk_type);
+
+               if (lock->lk_is_new) {
+                       if (!sop->so_is_open_owner)
+                              return nfserr_bad_stateid;
+                       if (!cmp_clid(&clp->cl_clientid, lockclid))
+                              return nfserr_bad_stateid;
+                       /* stp is the open stateid */
+                       status = nfs4_check_openmode(stp, lkflg);
+                       if (status)
+                              return status;
+               } else {
+                       /* stp is the lock stateid */
+                       status = nfs4_check_openmode(stp->st_openstp, lkflg);
+                       if (status)
+                              return status;
+               }
 
-               if (!sop->so_is_open_owner)
-                       goto out;
-               if (!cmp_clid(&clp->cl_clientid, lockclid))
-                       goto out;
        }
 
        if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
                printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
-               goto out;
+               return nfserr_bad_stateid;
        }
 
        *stpp = stp;
@@ -2235,63 +2248,41 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
        *  For the moment, we ignore the possibility of 
        *  generation number wraparound.
        */
-       if (seqid != sop->so_seqid + 1)
+       if (seqid != sop->so_seqid)
                goto check_replay;
 
-       if (sop->so_confirmed) {
-               if (flags & CONFIRM) {
-                       printk("NFSD: preprocess_seqid_op: expected unconfirmed stateowner!\n");
-                       goto out;
-               }
+       if (sop->so_confirmed && flags & CONFIRM) {
+               printk("NFSD: preprocess_seqid_op: expected"
+                               " unconfirmed stateowner!\n");
+               return nfserr_bad_stateid;
        }
-       else {
-               if (!(flags & CONFIRM)) {
-                       printk("NFSD: preprocess_seqid_op: stateowner not confirmed yet!\n");
-                       goto out;
-               }
+       if (!sop->so_confirmed && !(flags & CONFIRM)) {
+               printk("NFSD: preprocess_seqid_op: stateowner not"
+                               " confirmed yet!\n");
+               return nfserr_bad_stateid;
        }
        if (stateid->si_generation > stp->st_stateid.si_generation) {
                printk("NFSD: preprocess_seqid_op: future stateid?!\n");
-               goto out;
+               return nfserr_bad_stateid;
        }
 
-       status = nfserr_old_stateid;
        if (stateid->si_generation < stp->st_stateid.si_generation) {
                printk("NFSD: preprocess_seqid_op: old stateid!\n");
-               goto out;
+               return nfserr_old_stateid;
        }
-       /* XXX renew the client lease here */
-       status = nfs_ok;
-
-out:
-       return status;
-
-no_nfs4_stateid:
-
-       /*
-       * We determine whether this is a bad stateid or a replay, 
-       * starting by trying to look up the stateowner.
-       * If stateowner is not found - stateid is bad.
-       */
-       if (!(sop = find_openstateowner_id(stateid->si_stateownerid, flags))) {
-               printk("NFSD: preprocess_seqid_op: no stateowner or nfs4_stateid!\n");
-               status = nfserr_bad_stateid;
-               goto out;
-       }
-       *sopp = sop;
+       renew_client(sop->so_client);
+       return nfs_ok;
 
 check_replay:
-       if (seqid == sop->so_seqid) {
+       if (seqid == sop->so_seqid - 1) {
                printk("NFSD: preprocess_seqid_op: retransmission?\n");
                /* indicate replay to calling function */
-               status = NFSERR_REPLAY_ME;
-       } else  {
-               printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d\n", sop->so_seqid +1, seqid);
-
-               *sopp = NULL;
-               status = nfserr_bad_seqid;
+               return NFSERR_REPLAY_ME;
        }
-       goto out;
+       printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d)\n",
+                       sop->so_seqid, seqid);
+       *sopp = NULL;
+       return nfserr_bad_seqid;
 }
 
 int
@@ -2609,7 +2600,6 @@ find_lockstateowner_str(struct inode *inode, clientid_t *clid,
  * occured. 
  *
  * strhashval = lock_ownerstr_hashval 
- * so_seqid = lock->lk_new_lock_seqid - 1: it gets bumped in encode 
  */
 
 static struct nfs4_stateowner *
@@ -2634,7 +2624,7 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
        sop->so_is_open_owner = 0;
        sop->so_id = current_ownerid++;
        sop->so_client = clp;
-       sop->so_seqid = lock->lk_new_lock_seqid - 1;
+       sop->so_seqid = lock->lk_new_lock_seqid;
        sop->so_confirmed = 1;
        rp = &sop->so_replay;
        rp->rp_status = NFSERR_SERVERFAULT;
@@ -2669,6 +2659,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
        stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */
        stp->st_access_bmap = open_stp->st_access_bmap;
        stp->st_deny_bmap = open_stp->st_deny_bmap;
+       stp->st_openstp = open_stp;
 
 out:
        return stp;
@@ -2699,22 +2690,17 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
                (long long) lock->lk_offset,
                (long long) lock->lk_length);
 
-       if (nfs4_in_grace() && !lock->lk_reclaim)
-               return nfserr_grace;
-       if (!nfs4_in_grace() && lock->lk_reclaim)
-               return nfserr_no_grace;
-
        if (check_lock_length(lock->lk_offset, lock->lk_length))
                 return nfserr_inval;
 
        nfs4_lock_state();
 
        if (lock->lk_is_new) {
-       /*
-        * Client indicates that this is a new lockowner.
-        * Use open owner and open stateid to create lock owner and lock 
-        * stateid.
-        */
+               /*
+                * Client indicates that this is a new lockowner.
+                * Use open owner and open stateid to create lock owner and
+                * lock stateid.
+                */
                struct nfs4_stateid *open_stp = NULL;
                struct nfs4_file *fp;
                
@@ -2724,23 +2710,14 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
                        goto out;
                }
 
-               /* is the new lock seqid presented by the client zero? */
-               status = nfserr_bad_seqid;
-               if (lock->v.new.lock_seqid != 0)
-                       goto out;
-
                /* validate and update open stateid and open seqid */
                status = nfs4_preprocess_seqid_op(current_fh, 
                                        lock->lk_new_open_seqid,
                                        &lock->lk_new_open_stateid,
                                        CHECK_FH | OPEN_STATE,
-                                       &open_sop, &open_stp,
-                                       &lock->v.new.clientid);
-               if (status) {
-                       if (lock->lk_reclaim)
-                               status = nfserr_reclaim_bad;
+                                       &open_sop, &open_stp, lock);
+               if (status)
                        goto out;
-               }
                /* create lockowner and lock stateid */
                fp = open_stp->st_file;
                strhashval = lock_ownerstr_hashval(fp->fi_inode, 
@@ -2766,7 +2743,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
                                       lock->lk_old_lock_seqid, 
                                       &lock->lk_old_lock_stateid, 
                                       CHECK_FH | LOCK_STATE, 
-                                      &lock->lk_stateowner, &lock_stp, NULL);
+                                      &lock->lk_stateowner, &lock_stp, lock);
                if (status)
                        goto out;
        }
@@ -2778,6 +2755,13 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
                goto out;
        }
 
+       status = nfserr_grace;
+       if (nfs4_in_grace() && !lock->lk_reclaim)
+               goto out;
+       status = nfserr_no_grace;
+       if (!nfs4_in_grace() && lock->lk_reclaim)
+               goto out;
+
        locks_init_lock(&file_lock);
        switch (lock->lk_type) {
                case NFS4_READ_LT:
@@ -2844,10 +2828,10 @@ conflicting_lock:
 out_destroy_new_stateid:
        if (lock->lk_is_new) {
                dprintk("NFSD: nfsd4_lock: destroy new stateid!\n");
-       /*
-       * An error encountered after instantiation of the new
-       * stateid has forced us to destroy it.
-       */
+               /*
+                * An error encountered after instantiation of the new
+                * stateid has forced us to destroy it.
+                */
                if (!seqid_mutating_err(status))
                        open_sop->so_seqid--;
 
@@ -3083,7 +3067,12 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *
         * of the lockowner state released; so don't release any until all
         * have been checked. */
        status = nfs_ok;
-       list_for_each_entry(sop, &matches, so_perclient) {
+       while (!list_empty(&matches)) {
+               sop = list_entry(matches.next, struct nfs4_stateowner,
+                                                               so_perclient);
+               /* unhash_stateowner deletes so_perclient only
+                * for openowners. */
+               list_del(&sop->so_perclient);
                release_stateowner(sop);
        }
 out:
index 91fb171d2aceee025712bc4783f2a04e2773255c..4c4146350236be796c83072bd01e3913e344db71 100644 (file)
@@ -1210,16 +1210,15 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
        save = resp->p;
 
 /*
- * Routine for encoding the result of a
- * "seqid-mutating" NFSv4 operation.  This is
- * where seqids are incremented, and the
- * replay cache is filled.
+ * Routine for encoding the result of a "seqid-mutating" NFSv4 operation.  This
+ * is where sequence id's are incremented, and the replay cache is filled.
+ * Note that we increment sequence id's here, at the last moment, so we're sure
+ * we know whether the error to be returned is a sequence id mutating error.
  */
 
 #define ENCODE_SEQID_OP_TAIL(stateowner) do {                  \
        if (seqid_mutating_err(nfserr) && stateowner) {         \
-               if (stateowner->so_confirmed)                   \
-                       stateowner->so_seqid++;                 \
+               stateowner->so_seqid++;                         \
                stateowner->so_replay.rp_status = nfserr;       \
                stateowner->so_replay.rp_buflen =               \
                          (((char *)(resp)->p - (char *)save)); \
@@ -1367,9 +1366,9 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
                if ((buflen -= 4) < 0)
                        goto out_resource;
                if (exp->ex_flags & NFSEXP_NOSUBTREECHECK)
-                       WRITE32(NFS4_FH_VOLATILE_ANY);
+                       WRITE32(NFS4_FH_PERSISTENT);
                else
-                       WRITE32(NFS4_FH_VOLATILE_ANY|NFS4_FH_VOL_RENAME);
+                       WRITE32(NFS4_FH_PERSISTENT|NFS4_FH_VOL_RENAME);
        }
        if (bmval0 & FATTR4_WORD0_CHANGE) {
                /*
index be24ead89d94935298af52020262978136887d1f..5e0bf3917607f036eb7e0bb077822b016c8fb64a 100644 (file)
@@ -733,7 +733,7 @@ nfsd_sync(struct file *filp)
        up(&inode->i_sem);
 }
 
-static void
+void
 nfsd_sync_dir(struct dentry *dp)
 {
        nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
index 25bc1ec6bc5dfd0e8348b4c12d6c82acd25246fb..6e57ee252e14e1cd2982bb865fdebbbe24fb6ef7 100644 (file)
@@ -840,7 +840,6 @@ do_kern_mount(const char *fstype, int flags, const char *name, void *data)
        mnt->mnt_root = dget(sb->s_root);
        mnt->mnt_mountpoint = sb->s_root;
        mnt->mnt_parent = mnt;
-       mnt->mnt_namespace = current->namespace;
        up_write(&sb->s_umount);
        free_secdata(secdata);
        put_filesystem(type);
index 408aea55e0ccbc6f246c2910c6b0407a48dbcaea..e139463d9a0e158e1f88e8fff8b4876445810c44 100644 (file)
 #define __S110 _PAGE_S(0)
 #define __S111 _PAGE_S(0)
 
+#define pgprot_noncached(prot) (prot)
+
 /*
  * BAD_PAGETABLE is used when we need a bogus page-table, while
  * BAD_PAGE is used for a bogus page.
index 33ce5d37e8948cae3c3eede690e4e9c8d67f9c88..516421300ea2d2346cfb084eefb276bd00b9ec18 100644 (file)
@@ -8,20 +8,15 @@
 
 #include <asm/smp.h>
 
-#if CONFIG_NUMA
+#ifdef CONFIG_NUMA
 extern struct pglist_data *node_data[];
 #define NODE_DATA(nid) (node_data[nid])
 
-#ifdef CONFIG_NUMA
-       #ifdef CONFIG_X86_NUMAQ
-               #include <asm/numaq.h>
-       #else   /* summit or generic arch */
-               #include <asm/srat.h>
-       #endif
-#else /* !CONFIG_NUMA */
-       #define get_memcfg_numa get_memcfg_numa_flat
-       #define get_zholes_size(n) (0)
-#endif /* CONFIG_NUMA */
+#ifdef CONFIG_X86_NUMAQ
+       #include <asm/numaq.h>
+#else  /* summit or generic arch */
+       #include <asm/srat.h>
+#endif
 
 extern int get_memcfg_numa_flat(void );
 /*
@@ -42,6 +37,11 @@ static inline void get_memcfg_numa(void)
        get_memcfg_numa_flat();
 }
 
+extern int early_pfn_to_nid(unsigned long pfn);
+
+#else /* !CONFIG_NUMA */
+#define get_memcfg_numa get_memcfg_numa_flat
+#define get_zholes_size(n) (0)
 #endif /* CONFIG_NUMA */
 
 #ifdef CONFIG_DISCONTIGMEM
@@ -151,6 +151,4 @@ static inline int pfn_valid(int pfn)
 
 #endif /* CONFIG_NEED_MULTIPLE_NODES */
 
-extern int early_pfn_to_nid(unsigned long pfn);
-
 #endif /* _ASM_MMZONE_H_ */
index 6f0f93d0d41741ea7f094a3975f7cae5843aa44f..5d06e6bd6ba0bff037197c5ff047d66f47faa9fd 100644 (file)
@@ -694,4 +694,12 @@ extern unsigned long boot_option_idle_override;
 extern void enable_sep_cpu(void);
 extern int sysenter_setup(void);
 
+#ifdef CONFIG_MTRR
+extern void mtrr_ap_init(void);
+extern void mtrr_bp_init(void);
+#else
+#define mtrr_ap_init() do {} while (0)
+#define mtrr_bp_init() do {} while (0)
+#endif
+
 #endif /* __ASM_I386_PROCESSOR_H */
index 635fdce854a84b89129a9b292ac3b43392ced642..ab827d29856987ea758b6aaefb29f3fcea6f0790 100644 (file)
@@ -11,6 +11,7 @@
 #ifndef _ASM_IA64_SN_ARCH_H
 #define _ASM_IA64_SN_ARCH_H
 
+#include <linux/numa.h>
 #include <asm/types.h>
 #include <asm/percpu.h>
 #include <asm/sn/types.h>
index e51471fb0867e0226eccf85c2000639b6a3c5884..e190dd4213d56233938104e66cd1b93958abd99e 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef _ASM_IA64_SN_INTR_H
 #define _ASM_IA64_SN_INTR_H
 
+#include <linux/rcupdate.h>
+
 #define SGI_UART_VECTOR                (0xe9)
 #define SGI_PCIBR_ERROR                (0x33)
 
@@ -33,7 +35,7 @@
 
 // The SN PROM irq struct
 struct sn_irq_info {
-       struct sn_irq_info *irq_next;   /* sharing irq list          */
+       struct sn_irq_info *irq_next;   /* deprecated DO NOT USE     */
        short           irq_nasid;      /* Nasid IRQ is assigned to  */
        int             irq_slice;      /* slice IRQ is assigned to  */
        int             irq_cpuid;      /* kernel logical cpuid      */
@@ -47,6 +49,8 @@ struct sn_irq_info {
        int             irq_cookie;     /* unique cookie             */
        int             irq_flags;      /* flags */
        int             irq_share_cnt;  /* num devices sharing IRQ   */
+       struct list_head        list;   /* list of sn_irq_info structs */
+       struct rcu_head         rcu;    /* rcu callback list */
 };
 
 extern void sn_send_IPI_phys(int, long, int, int);
diff --git a/include/asm-ia64/sn/pcibr_provider.h b/include/asm-ia64/sn/pcibr_provider.h
new file mode 100644 (file)
index 0000000..f9b8d21
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992-1997,2000-2004 Silicon Graphics, Inc. All rights reserved.
+ */
+#ifndef _ASM_IA64_SN_PCI_PCIBR_PROVIDER_H
+#define _ASM_IA64_SN_PCI_PCIBR_PROVIDER_H
+
+#include <asm/sn/intr.h>
+#include <asm/sn/pcibus_provider_defs.h>
+
+/* Workarounds */
+#define PV907516 (1 << 1) /* TIOCP: Don't write the write buffer flush reg */
+
+#define BUSTYPE_MASK                    0x1
+
+/* Macros given a pcibus structure */
+#define IS_PCIX(ps)     ((ps)->pbi_bridge_mode & BUSTYPE_MASK)
+#define IS_PCI_BRIDGE_ASIC(asic) (asic == PCIIO_ASIC_TYPE_PIC || \
+                asic == PCIIO_ASIC_TYPE_TIOCP)
+#define IS_PIC_SOFT(ps)     (ps->pbi_bridge_type == PCIBR_BRIDGETYPE_PIC)
+
+
+/*
+ * The different PCI Bridge types supported on the SGI Altix platforms
+ */
+#define PCIBR_BRIDGETYPE_UNKNOWN       -1
+#define PCIBR_BRIDGETYPE_PIC            2
+#define PCIBR_BRIDGETYPE_TIOCP          3
+
+/*
+ * Bridge 64bit Direct Map Attributes
+ */
+#define PCI64_ATTR_PREF                 (1ull << 59)
+#define PCI64_ATTR_PREC                 (1ull << 58)
+#define PCI64_ATTR_VIRTUAL              (1ull << 57)
+#define PCI64_ATTR_BAR                  (1ull << 56)
+#define PCI64_ATTR_SWAP                 (1ull << 55)
+#define PCI64_ATTR_VIRTUAL1             (1ull << 54)
+
+#define PCI32_LOCAL_BASE                0
+#define PCI32_MAPPED_BASE               0x40000000
+#define PCI32_DIRECT_BASE               0x80000000
+
+#define IS_PCI32_MAPPED(x)              ((uint64_t)(x) < PCI32_DIRECT_BASE && \
+                                         (uint64_t)(x) >= PCI32_MAPPED_BASE)
+#define IS_PCI32_DIRECT(x)              ((uint64_t)(x) >= PCI32_MAPPED_BASE)
+
+
+/*
+ * Bridge PMU Address Transaltion Entry Attibutes
+ */
+#define PCI32_ATE_V                     (0x1 << 0)
+#define PCI32_ATE_CO                    (0x1 << 1)
+#define PCI32_ATE_PREC                  (0x1 << 2)
+#define PCI32_ATE_PREF                  (0x1 << 3)
+#define PCI32_ATE_BAR                   (0x1 << 4)
+#define PCI32_ATE_ADDR_SHFT             12
+
+#define MINIMAL_ATES_REQUIRED(addr, size) \
+       (IOPG(IOPGOFF(addr) + (size) - 1) == IOPG((size) - 1))
+
+#define MINIMAL_ATE_FLAG(addr, size) \
+       (MINIMAL_ATES_REQUIRED((uint64_t)addr, size) ? 1 : 0)
+
+/* bit 29 of the pci address is the SWAP bit */
+#define ATE_SWAPSHIFT                   29
+#define ATE_SWAP_ON(x)                  ((x) |= (1 << ATE_SWAPSHIFT))
+#define ATE_SWAP_OFF(x)                 ((x) &= ~(1 << ATE_SWAPSHIFT))
+
+/*
+ * I/O page size
+ */
+#if PAGE_SIZE < 16384
+#define IOPFNSHIFT                      12      /* 4K per mapped page */
+#else
+#define IOPFNSHIFT                      14      /* 16K per mapped page */
+#endif
+
+#define IOPGSIZE                        (1 << IOPFNSHIFT)
+#define IOPG(x)                         ((x) >> IOPFNSHIFT)
+#define IOPGOFF(x)                      ((x) & (IOPGSIZE-1))
+
+#define PCIBR_DEV_SWAP_DIR              (1ull << 19)
+#define PCIBR_CTRL_PAGE_SIZE            (0x1 << 21)
+
+/*
+ * PMU resources.
+ */
+struct ate_resource{
+       uint64_t *ate;
+       uint64_t num_ate;
+       uint64_t lowest_free_index;
+};
+
+struct pcibus_info {
+       struct pcibus_bussoft   pbi_buscommon;   /* common header */
+       uint32_t                pbi_moduleid;
+       short                   pbi_bridge_type;
+       short                   pbi_bridge_mode;
+
+       struct ate_resource     pbi_int_ate_resource;
+       uint64_t                pbi_int_ate_size;
+
+       uint64_t                pbi_dir_xbase;
+       char                    pbi_hub_xid;
+
+       uint64_t                pbi_devreg[8];
+
+       uint32_t                pbi_valid_devices;
+       uint32_t                pbi_enabled_devices;
+
+       spinlock_t              pbi_lock;
+};
+
+/*
+ * pcibus_info structure locking macros
+ */
+inline static unsigned long
+pcibr_lock(struct pcibus_info *pcibus_info)
+{
+       unsigned long flag;
+       spin_lock_irqsave(&pcibus_info->pbi_lock, flag);
+       return(flag);
+}
+#define pcibr_unlock(pcibus_info, flag)  spin_unlock_irqrestore(&pcibus_info->pbi_lock, flag)
+
+extern int  pcibr_init_provider(void);
+extern void *pcibr_bus_fixup(struct pcibus_bussoft *);
+extern dma_addr_t pcibr_dma_map(struct pci_dev *, unsigned long, size_t);
+extern dma_addr_t pcibr_dma_map_consistent(struct pci_dev *, unsigned long, size_t);
+extern void pcibr_dma_unmap(struct pci_dev *, dma_addr_t, int);
+
+/*
+ * prototypes for the bridge asic register access routines in pcibr_reg.c
+ */
+extern void             pcireg_control_bit_clr(struct pcibus_info *, uint64_t);
+extern void             pcireg_control_bit_set(struct pcibus_info *, uint64_t);
+extern uint64_t         pcireg_tflush_get(struct pcibus_info *);
+extern uint64_t         pcireg_intr_status_get(struct pcibus_info *);
+extern void             pcireg_intr_enable_bit_clr(struct pcibus_info *, uint64_t);
+extern void             pcireg_intr_enable_bit_set(struct pcibus_info *, uint64_t);
+extern void             pcireg_intr_addr_addr_set(struct pcibus_info *, int, uint64_t);
+extern void             pcireg_force_intr_set(struct pcibus_info *, int);
+extern uint64_t         pcireg_wrb_flush_get(struct pcibus_info *, int);
+extern void             pcireg_int_ate_set(struct pcibus_info *, int, uint64_t);
+extern uint64_t *      pcireg_int_ate_addr(struct pcibus_info *, int);
+extern void            pcibr_force_interrupt(struct sn_irq_info *sn_irq_info);
+extern void            pcibr_change_devices_irq(struct sn_irq_info *sn_irq_info);
+extern int             pcibr_ate_alloc(struct pcibus_info *, int);
+extern void            pcibr_ate_free(struct pcibus_info *, int);
+extern void            ate_write(struct pcibus_info *, int, int, uint64_t);
+extern int sal_pcibr_slot_enable(struct pcibus_info *soft, int device,
+                                void *resp);
+extern int sal_pcibr_slot_disable(struct pcibus_info *soft, int device,
+                                 int action, void *resp);
+#endif
index ed4031d808113c17029477f2308b42e065d4d5eb..49711d00ad04f77d90467daf33bfd13d549e2109 100644 (file)
 
 #include <linux/pci.h>
 
-extern struct sn_irq_info **sn_irq;
-
 #define SN_PCIDEV_INFO(pci_dev) \
         ((struct pcidev_info *)(pci_dev)->sysdata)
 
+#define SN_PCIBUS_BUSSOFT_INFO(pci_bus) \
+       (struct pcibus_info *)((struct pcibus_bussoft *)(PCI_CONTROLLER((pci_bus))->platform_data))
 /*
  * Given a pci_bus, return the sn pcibus_bussoft struct.  Note that
  * this only works for root busses, not for busses represented by PPB's.
@@ -23,6 +23,8 @@ extern struct sn_irq_info **sn_irq;
 #define SN_PCIBUS_BUSSOFT(pci_bus) \
         ((struct pcibus_bussoft *)(PCI_CONTROLLER((pci_bus))->platform_data))
 
+#define SN_PCIBUS_BUSSOFT_INFO(pci_bus) \
+       (struct pcibus_info *)((struct pcibus_bussoft *)(PCI_CONTROLLER((pci_bus))->platform_data))
 /*
  * Given a struct pci_dev, return the sn pcibus_bussoft struct.  Note
  * that this is not equivalent to SN_PCIBUS_BUSSOFT(pci_dev->bus) due
@@ -50,9 +52,17 @@ struct pcidev_info {
 
        struct sn_irq_info      *pdi_sn_irq_info;
        struct sn_pcibus_provider *pdi_provider;        /* sn pci ops */
+       struct pci_dev          *host_pci_dev;          /* host bus link */
 };
 
 extern void sn_irq_fixup(struct pci_dev *pci_dev,
                         struct sn_irq_info *sn_irq_info);
-
+extern void sn_irq_unfixup(struct pci_dev *pci_dev);
+extern void sn_pci_controller_fixup(int segment, int busnum,
+                                   struct pci_bus *bus);
+extern void sn_bus_store_sysdata(struct pci_dev *dev);
+extern void sn_bus_free_sysdata(void);
+extern void sn_pci_fixup_slot(struct pci_dev *dev);
+extern void sn_pci_unfixup_slot(struct pci_dev *dev);
+extern void sn_irq_lh_init(void);
 #endif                         /* _ASM_IA64_SN_PCI_PCIDEV_H */
diff --git a/include/asm-ia64/sn/pic.h b/include/asm-ia64/sn/pic.h
new file mode 100644 (file)
index 0000000..0de82e6
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+#ifndef _ASM_IA64_SN_PCI_PIC_H
+#define _ASM_IA64_SN_PCI_PIC_H
+
+/*
+ * PIC AS DEVICE ZERO
+ * ------------------
+ *
+ * PIC handles PCI/X busses.  PCI/X requires that the 'bridge' (i.e. PIC)
+ * be designated as 'device 0'.   That is a departure from earlier SGI
+ * PCI bridges.  Because of that we use config space 1 to access the
+ * config space of the first actual PCI device on the bus.
+ * Here's what the PIC manual says:
+ *
+ *     The current PCI-X bus specification now defines that the parent
+ *     hosts bus bridge (PIC for example) must be device 0 on bus 0. PIC
+ *     reduced the total number of devices from 8 to 4 and removed the
+ *     device registers and windows, now only supporting devices 0,1,2, and
+ *     3. PIC did leave all 8 configuration space windows. The reason was
+ *     there was nothing to gain by removing them. Here in lies the problem.
+ *     The device numbering we do using 0 through 3 is unrelated to the device
+ *     numbering which PCI-X requires in configuration space. In the past we
+ *     correlated Configs pace and our device space 0 <-> 0, 1 <-> 1, etc.
+ *     PCI-X requires we start a 1, not 0 and currently the PX brick
+ *     does associate our:
+ *
+ *         device 0 with configuration space window 1,
+ *         device 1 with configuration space window 2,
+ *         device 2 with configuration space window 3,
+ *         device 3 with configuration space window 4.
+ *
+ * The net effect is that all config space access are off-by-one with
+ * relation to other per-slot accesses on the PIC.
+ * Here is a table that shows some of that:
+ *
+ *                               Internal Slot#
+ *           |
+ *           |     0         1        2         3
+ * ----------|---------------------------------------
+ * config    |  0x21000   0x22000  0x23000   0x24000
+ *           |
+ * even rrb  |  0[0]      n/a      1[0]      n/a       [] == implied even/odd
+ *           |
+ * odd rrb   |  n/a       0[1]     n/a       1[1]
+ *           |
+ * int dev   |  00       01        10        11
+ *           |
+ * ext slot# |  1        2         3         4
+ * ----------|---------------------------------------
+ */
+
+#define PIC_ATE_TARGETID_SHFT           8
+#define PIC_HOST_INTR_ADDR              0x0000FFFFFFFFFFFFUL
+#define PIC_PCI64_ATTR_TARG_SHFT        60
+
+
+/*****************************************************************************
+ *********************** PIC MMR structure mapping ***************************
+ *****************************************************************************/
+
+/* NOTE: PIC WAR. PV#854697.  PIC does not allow writes just to [31:0]
+ * of a 64-bit register.  When writing PIC registers, always write the
+ * entire 64 bits.
+ */
+
+struct pic {
+
+    /* 0x000000-0x00FFFF -- Local Registers */
+
+    /* 0x000000-0x000057 -- Standard Widget Configuration */
+    uint64_t           p_wid_id;                       /* 0x000000 */
+    uint64_t           p_wid_stat;                     /* 0x000008 */
+    uint64_t           p_wid_err_upper;                /* 0x000010 */
+    uint64_t           p_wid_err_lower;                /* 0x000018 */
+    #define p_wid_err p_wid_err_lower
+    uint64_t           p_wid_control;                  /* 0x000020 */
+    uint64_t           p_wid_req_timeout;              /* 0x000028 */
+    uint64_t           p_wid_int_upper;                /* 0x000030 */
+    uint64_t           p_wid_int_lower;                /* 0x000038 */
+    #define p_wid_int p_wid_int_lower
+    uint64_t           p_wid_err_cmdword;              /* 0x000040 */
+    uint64_t           p_wid_llp;                      /* 0x000048 */
+    uint64_t           p_wid_tflush;                   /* 0x000050 */
+
+    /* 0x000058-0x00007F -- Bridge-specific Widget Configuration */
+    uint64_t           p_wid_aux_err;                  /* 0x000058 */
+    uint64_t           p_wid_resp_upper;               /* 0x000060 */
+    uint64_t           p_wid_resp_lower;               /* 0x000068 */
+    #define p_wid_resp p_wid_resp_lower
+    uint64_t           p_wid_tst_pin_ctrl;             /* 0x000070 */
+    uint64_t           p_wid_addr_lkerr;               /* 0x000078 */
+
+    /* 0x000080-0x00008F -- PMU & MAP */
+    uint64_t           p_dir_map;                      /* 0x000080 */
+    uint64_t           _pad_000088;                    /* 0x000088 */
+
+    /* 0x000090-0x00009F -- SSRAM */
+    uint64_t           p_map_fault;                    /* 0x000090 */
+    uint64_t           _pad_000098;                    /* 0x000098 */
+
+    /* 0x0000A0-0x0000AF -- Arbitration */
+    uint64_t           p_arb;                          /* 0x0000A0 */
+    uint64_t           _pad_0000A8;                    /* 0x0000A8 */
+
+    /* 0x0000B0-0x0000BF -- Number In A Can or ATE Parity Error */
+    uint64_t           p_ate_parity_err;               /* 0x0000B0 */
+    uint64_t           _pad_0000B8;                    /* 0x0000B8 */
+
+    /* 0x0000C0-0x0000FF -- PCI/GIO */
+    uint64_t           p_bus_timeout;                  /* 0x0000C0 */
+    uint64_t           p_pci_cfg;                      /* 0x0000C8 */
+    uint64_t           p_pci_err_upper;                /* 0x0000D0 */
+    uint64_t           p_pci_err_lower;                /* 0x0000D8 */
+    #define p_pci_err p_pci_err_lower
+    uint64_t           _pad_0000E0[4];                 /* 0x0000{E0..F8} */
+
+    /* 0x000100-0x0001FF -- Interrupt */
+    uint64_t           p_int_status;                   /* 0x000100 */
+    uint64_t           p_int_enable;                   /* 0x000108 */
+    uint64_t           p_int_rst_stat;                 /* 0x000110 */
+    uint64_t           p_int_mode;                     /* 0x000118 */
+    uint64_t           p_int_device;                   /* 0x000120 */
+    uint64_t           p_int_host_err;                 /* 0x000128 */
+    uint64_t           p_int_addr[8];                  /* 0x0001{30,,,68} */
+    uint64_t           p_err_int_view;                 /* 0x000170 */
+    uint64_t           p_mult_int;                     /* 0x000178 */
+    uint64_t           p_force_always[8];              /* 0x0001{80,,,B8} */
+    uint64_t           p_force_pin[8];                 /* 0x0001{C0,,,F8} */
+
+    /* 0x000200-0x000298 -- Device */
+    uint64_t           p_device[4];                    /* 0x0002{00,,,18} */
+    uint64_t           _pad_000220[4];                 /* 0x0002{20,,,38} */
+    uint64_t           p_wr_req_buf[4];                /* 0x0002{40,,,58} */
+    uint64_t           _pad_000260[4];                 /* 0x0002{60,,,78} */
+    uint64_t           p_rrb_map[2];                   /* 0x0002{80,,,88} */
+    #define p_even_resp p_rrb_map[0]                   /* 0x000280 */
+    #define p_odd_resp  p_rrb_map[1]                   /* 0x000288 */
+    uint64_t           p_resp_status;                  /* 0x000290 */
+    uint64_t           p_resp_clear;                   /* 0x000298 */
+
+    uint64_t           _pad_0002A0[12];                /* 0x0002{A0..F8} */
+
+    /* 0x000300-0x0003F8 -- Buffer Address Match Registers */
+    struct {
+       uint64_t        upper;                          /* 0x0003{00,,,F0} */
+       uint64_t        lower;                          /* 0x0003{08,,,F8} */
+    } p_buf_addr_match[16];
+
+    /* 0x000400-0x0005FF -- Performance Monitor Registers (even only) */
+    struct {
+       uint64_t        flush_w_touch;                  /* 0x000{400,,,5C0} */
+       uint64_t        flush_wo_touch;                 /* 0x000{408,,,5C8} */
+       uint64_t        inflight;                       /* 0x000{410,,,5D0} */
+       uint64_t        prefetch;                       /* 0x000{418,,,5D8} */
+       uint64_t        total_pci_retry;                /* 0x000{420,,,5E0} */
+       uint64_t        max_pci_retry;                  /* 0x000{428,,,5E8} */
+       uint64_t        max_latency;                    /* 0x000{430,,,5F0} */
+       uint64_t        clear_all;                      /* 0x000{438,,,5F8} */
+    } p_buf_count[8];
+
+
+    /* 0x000600-0x0009FF -- PCI/X registers */
+    uint64_t           p_pcix_bus_err_addr;            /* 0x000600 */
+    uint64_t           p_pcix_bus_err_attr;            /* 0x000608 */
+    uint64_t           p_pcix_bus_err_data;            /* 0x000610 */
+    uint64_t           p_pcix_pio_split_addr;          /* 0x000618 */
+    uint64_t           p_pcix_pio_split_attr;          /* 0x000620 */
+    uint64_t           p_pcix_dma_req_err_attr;        /* 0x000628 */
+    uint64_t           p_pcix_dma_req_err_addr;        /* 0x000630 */
+    uint64_t           p_pcix_timeout;                 /* 0x000638 */
+
+    uint64_t           _pad_000640[120];               /* 0x000{640,,,9F8} */
+
+    /* 0x000A00-0x000BFF -- PCI/X Read&Write Buffer */
+    struct {
+       uint64_t        p_buf_addr;                     /* 0x000{A00,,,AF0} */
+       uint64_t        p_buf_attr;                     /* 0X000{A08,,,AF8} */
+    } p_pcix_read_buf_64[16];
+
+    struct {
+       uint64_t        p_buf_addr;                     /* 0x000{B00,,,BE0} */
+       uint64_t        p_buf_attr;                     /* 0x000{B08,,,BE8} */
+       uint64_t        p_buf_valid;                    /* 0x000{B10,,,BF0} */
+       uint64_t        __pad1;                         /* 0x000{B18,,,BF8} */
+    } p_pcix_write_buf_64[8];
+
+    /* End of Local Registers -- Start of Address Map space */
+
+    char               _pad_000c00[0x010000 - 0x000c00];
+
+    /* 0x010000-0x011fff -- Internal ATE RAM (Auto Parity Generation) */
+    uint64_t           p_int_ate_ram[1024];            /* 0x010000-0x011fff */
+
+    /* 0x012000-0x013fff -- Internal ATE RAM (Manual Parity Generation) */
+    uint64_t           p_int_ate_ram_mp[1024];         /* 0x012000-0x013fff */
+
+    char               _pad_014000[0x18000 - 0x014000];
+
+    /* 0x18000-0x197F8 -- PIC Write Request Ram */
+    uint64_t           p_wr_req_lower[256];            /* 0x18000 - 0x187F8 */
+    uint64_t           p_wr_req_upper[256];            /* 0x18800 - 0x18FF8 */
+    uint64_t           p_wr_req_parity[256];           /* 0x19000 - 0x197F8 */
+
+    char               _pad_019800[0x20000 - 0x019800];
+
+    /* 0x020000-0x027FFF -- PCI Device Configuration Spaces */
+    union {
+       uint8_t         c[0x1000 / 1];                  /* 0x02{0000,,,7FFF} */
+       uint16_t        s[0x1000 / 2];                  /* 0x02{0000,,,7FFF} */
+       uint32_t        l[0x1000 / 4];                  /* 0x02{0000,,,7FFF} */
+       uint64_t        d[0x1000 / 8];                  /* 0x02{0000,,,7FFF} */
+       union {
+           uint8_t     c[0x100 / 1];
+           uint16_t    s[0x100 / 2];
+           uint32_t    l[0x100 / 4];
+           uint64_t    d[0x100 / 8];
+       } f[8];
+    } p_type0_cfg_dev[8];                              /* 0x02{0000,,,7FFF} */
+
+    /* 0x028000-0x028FFF -- PCI Type 1 Configuration Space */
+    union {
+       uint8_t         c[0x1000 / 1];                  /* 0x028000-0x029000 */
+       uint16_t        s[0x1000 / 2];                  /* 0x028000-0x029000 */
+       uint32_t        l[0x1000 / 4];                  /* 0x028000-0x029000 */
+       uint64_t        d[0x1000 / 8];                  /* 0x028000-0x029000 */
+       union {
+           uint8_t     c[0x100 / 1];
+           uint16_t    s[0x100 / 2];
+           uint32_t    l[0x100 / 4];
+           uint64_t    d[0x100 / 8];
+       } f[8];
+    } p_type1_cfg;                                     /* 0x028000-0x029000 */
+
+    char               _pad_029000[0x030000-0x029000];
+
+    /* 0x030000-0x030007 -- PCI Interrupt Acknowledge Cycle */
+    union {
+       uint8_t         c[8 / 1];
+       uint16_t        s[8 / 2];
+       uint32_t        l[8 / 4];
+       uint64_t        d[8 / 8];
+    } p_pci_iack;                                      /* 0x030000-0x030007 */
+
+    char               _pad_030007[0x040000-0x030008];
+
+    /* 0x040000-0x030007 -- PCIX Special Cycle */
+    union {
+       uint8_t         c[8 / 1];
+       uint16_t        s[8 / 2];
+       uint32_t        l[8 / 4];
+       uint64_t        d[8 / 8];
+    } p_pcix_cycle;                                    /* 0x040000-0x040007 */
+};
+
+#endif                          /* _ASM_IA64_SN_PCI_PIC_H */
index 20b3001876698992860772fcef3edfc6f62040d3..d2c1d34dcce4e062229eb9cc11c636f215e0e2a7 100644 (file)
  *
  */
 
-#ifndef CONFIG_SMP
-#define cpu_physical_id(cpuid)                 ((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff)
-#endif
-
-
 #define get_node_number(addr)                  NASID_GET(addr)
 
 /*
index 1455375d2ce4e8429fd78fc565ffe30151b0fb2e..27976d22318657e56fcdc48833cf993a887309b1 100644 (file)
 
 #define SN_SAL_FAKE_PROM                          0x02009999
 
-
 /**
- * sn_sal_rev_major - get the major SGI SAL revision number
- *
- * The SGI PROM stores its version in sal_[ab]_rev_(major|minor).
- * This routine simply extracts the major value from the
- * @ia64_sal_systab structure constructed by ia64_sal_init().
- */
-static inline int
-sn_sal_rev_major(void)
+  * sn_sal_revision - get the SGI SAL revision number
+  *
+  * The SGI PROM stores its version in the sal_[ab]_rev_(major|minor).
+  * This routine simply extracts the major and minor values and
+  * presents them in a u32 format.
+  *
+  * For example, version 4.05 would be represented at 0x0405.
+  */
+static inline u32
+sn_sal_rev(void)
 {
        struct ia64_sal_systab *systab = efi.sal_systab;
 
-       return (int)systab->sal_b_rev_major;
-}
-
-/**
- * sn_sal_rev_minor - get the minor SGI SAL revision number
- *
- * The SGI PROM stores its version in sal_[ab]_rev_(major|minor).
- * This routine simply extracts the minor value from the
- * @ia64_sal_systab structure constructed by ia64_sal_init().
- */
-static inline int
-sn_sal_rev_minor(void)
-{
-       struct ia64_sal_systab *systab = efi.sal_systab;
-       
-       return (int)systab->sal_b_rev_minor;
+       return (u32)(systab->sal_b_rev_major << 8 | systab->sal_b_rev_minor);
 }
 
 /*
  * Specify the minimum PROM revsion required for this kernel.
  * Note that they're stored in hex format...
  */
-#define SN_SAL_MIN_MAJOR       0x4  /* SN2 kernels need at least PROM 4.0 */
-#define SN_SAL_MIN_MINOR       0x0
+#define SN_SAL_MIN_VERSION     0x0404
 
 /*
  * Returns the master console nasid, if the call fails, return an illegal
diff --git a/include/asm-ia64/sn/tiocp.h b/include/asm-ia64/sn/tiocp.h
new file mode 100644 (file)
index 0000000..5f2489c
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003-2004 Silicon Graphics, Inc. All rights reserved.
+ */
+#ifndef _ASM_IA64_SN_PCI_TIOCP_H
+#define _ASM_IA64_SN_PCI_TIOCP_H
+
+#define TIOCP_HOST_INTR_ADDR            0x003FFFFFFFFFFFFFUL
+#define TIOCP_PCI64_CMDTYPE_MEM         (0x1ull << 60)
+
+
+/*****************************************************************************
+ *********************** TIOCP MMR structure mapping ***************************
+ *****************************************************************************/
+
+struct tiocp{
+
+    /* 0x000000-0x00FFFF -- Local Registers */
+
+    /* 0x000000-0x000057 -- (Legacy Widget Space) Configuration */
+    uint64_t           cp_id;                          /* 0x000000 */
+    uint64_t           cp_stat;                        /* 0x000008 */
+    uint64_t           cp_err_upper;                   /* 0x000010 */
+    uint64_t           cp_err_lower;                   /* 0x000018 */
+    #define cp_err cp_err_lower
+    uint64_t           cp_control;                     /* 0x000020 */
+    uint64_t           cp_req_timeout;                 /* 0x000028 */
+    uint64_t           cp_intr_upper;                  /* 0x000030 */
+    uint64_t           cp_intr_lower;                  /* 0x000038 */
+    #define cp_intr cp_intr_lower
+    uint64_t           cp_err_cmdword;                 /* 0x000040 */
+    uint64_t           _pad_000048;                    /* 0x000048 */
+    uint64_t           cp_tflush;                      /* 0x000050 */
+
+    /* 0x000058-0x00007F -- Bridge-specific Configuration */
+    uint64_t           cp_aux_err;                     /* 0x000058 */
+    uint64_t           cp_resp_upper;                  /* 0x000060 */
+    uint64_t           cp_resp_lower;                  /* 0x000068 */
+    #define cp_resp cp_resp_lower
+    uint64_t           cp_tst_pin_ctrl;                /* 0x000070 */
+    uint64_t           cp_addr_lkerr;                  /* 0x000078 */
+
+    /* 0x000080-0x00008F -- PMU & MAP */
+    uint64_t           cp_dir_map;                     /* 0x000080 */
+    uint64_t           _pad_000088;                    /* 0x000088 */
+
+    /* 0x000090-0x00009F -- SSRAM */
+    uint64_t           cp_map_fault;                   /* 0x000090 */
+    uint64_t           _pad_000098;                    /* 0x000098 */
+
+    /* 0x0000A0-0x0000AF -- Arbitration */
+    uint64_t           cp_arb;                         /* 0x0000A0 */
+    uint64_t           _pad_0000A8;                    /* 0x0000A8 */
+
+    /* 0x0000B0-0x0000BF -- Number In A Can or ATE Parity Error */
+    uint64_t           cp_ate_parity_err;              /* 0x0000B0 */
+    uint64_t           _pad_0000B8;                    /* 0x0000B8 */
+
+    /* 0x0000C0-0x0000FF -- PCI/GIO */
+    uint64_t           cp_bus_timeout;                 /* 0x0000C0 */
+    uint64_t           cp_pci_cfg;                     /* 0x0000C8 */
+    uint64_t           cp_pci_err_upper;               /* 0x0000D0 */
+    uint64_t           cp_pci_err_lower;               /* 0x0000D8 */
+    #define cp_pci_err cp_pci_err_lower
+    uint64_t           _pad_0000E0[4];                 /* 0x0000{E0..F8} */
+
+    /* 0x000100-0x0001FF -- Interrupt */
+    uint64_t           cp_int_status;                  /* 0x000100 */
+    uint64_t           cp_int_enable;                  /* 0x000108 */
+    uint64_t           cp_int_rst_stat;                /* 0x000110 */
+    uint64_t           cp_int_mode;                    /* 0x000118 */
+    uint64_t           cp_int_device;                  /* 0x000120 */
+    uint64_t           cp_int_host_err;                /* 0x000128 */
+    uint64_t           cp_int_addr[8];                 /* 0x0001{30,,,68} */
+    uint64_t           cp_err_int_view;                /* 0x000170 */
+    uint64_t           cp_mult_int;                    /* 0x000178 */
+    uint64_t           cp_force_always[8];             /* 0x0001{80,,,B8} */
+    uint64_t           cp_force_pin[8];                /* 0x0001{C0,,,F8} */
+
+    /* 0x000200-0x000298 -- Device */
+    uint64_t           cp_device[4];                   /* 0x0002{00,,,18} */
+    uint64_t           _pad_000220[4];                 /* 0x0002{20,,,38} */
+    uint64_t           cp_wr_req_buf[4];               /* 0x0002{40,,,58} */
+    uint64_t           _pad_000260[4];                 /* 0x0002{60,,,78} */
+    uint64_t           cp_rrb_map[2];                  /* 0x0002{80,,,88} */
+    #define cp_even_resp cp_rrb_map[0]                 /* 0x000280 */
+    #define cp_odd_resp  cp_rrb_map[1]                 /* 0x000288 */
+    uint64_t           cp_resp_status;                 /* 0x000290 */
+    uint64_t           cp_resp_clear;                  /* 0x000298 */
+
+    uint64_t           _pad_0002A0[12];                /* 0x0002{A0..F8} */
+
+    /* 0x000300-0x0003F8 -- Buffer Address Match Registers */
+    struct {
+       uint64_t        upper;                          /* 0x0003{00,,,F0} */
+       uint64_t        lower;                          /* 0x0003{08,,,F8} */
+    } cp_buf_addr_match[16];
+
+    /* 0x000400-0x0005FF -- Performance Monitor Registers (even only) */
+    struct {
+       uint64_t        flush_w_touch;                  /* 0x000{400,,,5C0} */
+       uint64_t        flush_wo_touch;                 /* 0x000{408,,,5C8} */
+       uint64_t        inflight;                       /* 0x000{410,,,5D0} */
+       uint64_t        prefetch;                       /* 0x000{418,,,5D8} */
+       uint64_t        total_pci_retry;                /* 0x000{420,,,5E0} */
+       uint64_t        max_pci_retry;                  /* 0x000{428,,,5E8} */
+       uint64_t        max_latency;                    /* 0x000{430,,,5F0} */
+       uint64_t        clear_all;                      /* 0x000{438,,,5F8} */
+    } cp_buf_count[8];
+
+
+    /* 0x000600-0x0009FF -- PCI/X registers */
+    uint64_t           cp_pcix_bus_err_addr;           /* 0x000600 */
+    uint64_t           cp_pcix_bus_err_attr;           /* 0x000608 */
+    uint64_t           cp_pcix_bus_err_data;           /* 0x000610 */
+    uint64_t           cp_pcix_pio_split_addr;         /* 0x000618 */
+    uint64_t           cp_pcix_pio_split_attr;         /* 0x000620 */
+    uint64_t           cp_pcix_dma_req_err_attr;       /* 0x000628 */
+    uint64_t           cp_pcix_dma_req_err_addr;       /* 0x000630 */
+    uint64_t           cp_pcix_timeout;                /* 0x000638 */
+
+    uint64_t           _pad_000640[24];                /* 0x000{640,,,6F8} */
+
+    /* 0x000700-0x000737 -- Debug Registers */
+    uint64_t           cp_ct_debug_ctl;                /* 0x000700 */
+    uint64_t           cp_br_debug_ctl;                /* 0x000708 */
+    uint64_t           cp_mux3_debug_ctl;              /* 0x000710 */
+    uint64_t           cp_mux4_debug_ctl;              /* 0x000718 */
+    uint64_t           cp_mux5_debug_ctl;              /* 0x000720 */
+    uint64_t           cp_mux6_debug_ctl;              /* 0x000728 */
+    uint64_t           cp_mux7_debug_ctl;              /* 0x000730 */
+
+    uint64_t           _pad_000738[89];                /* 0x000{738,,,9F8} */
+
+    /* 0x000A00-0x000BFF -- PCI/X Read&Write Buffer */
+    struct {
+       uint64_t        cp_buf_addr;                    /* 0x000{A00,,,AF0} */
+       uint64_t        cp_buf_attr;                    /* 0X000{A08,,,AF8} */
+    } cp_pcix_read_buf_64[16];
+
+    struct {
+       uint64_t        cp_buf_addr;                    /* 0x000{B00,,,BE0} */
+       uint64_t        cp_buf_attr;                    /* 0x000{B08,,,BE8} */
+       uint64_t        cp_buf_valid;                   /* 0x000{B10,,,BF0} */
+       uint64_t        __pad1;                         /* 0x000{B18,,,BF8} */
+    } cp_pcix_write_buf_64[8];
+
+    /* End of Local Registers -- Start of Address Map space */
+
+    char               _pad_000c00[0x010000 - 0x000c00];
+
+    /* 0x010000-0x011FF8 -- Internal ATE RAM (Auto Parity Generation) */
+    uint64_t           cp_int_ate_ram[1024];           /* 0x010000-0x011FF8 */
+
+    char               _pad_012000[0x14000 - 0x012000];
+
+    /* 0x014000-0x015FF8 -- Internal ATE RAM (Manual Parity Generation) */
+    uint64_t           cp_int_ate_ram_mp[1024];        /* 0x014000-0x015FF8 */
+
+    char               _pad_016000[0x18000 - 0x016000];
+
+    /* 0x18000-0x197F8 -- TIOCP Write Request Ram */
+    uint64_t           cp_wr_req_lower[256];           /* 0x18000 - 0x187F8 */
+    uint64_t           cp_wr_req_upper[256];           /* 0x18800 - 0x18FF8 */
+    uint64_t           cp_wr_req_parity[256];          /* 0x19000 - 0x197F8 */
+
+    char               _pad_019800[0x1C000 - 0x019800];
+
+    /* 0x1C000-0x1EFF8 -- TIOCP Read Response Ram */
+    uint64_t           cp_rd_resp_lower[512];          /* 0x1C000 - 0x1CFF8 */
+    uint64_t           cp_rd_resp_upper[512];          /* 0x1D000 - 0x1DFF8 */
+    uint64_t           cp_rd_resp_parity[512];         /* 0x1E000 - 0x1EFF8 */
+
+    char               _pad_01F000[0x20000 - 0x01F000];
+
+    /* 0x020000-0x021FFF -- Host Device (CP) Configuration Space (not used)  */
+    char               _pad_020000[0x021000 - 0x20000];
+
+    /* 0x021000-0x027FFF -- PCI Device Configuration Spaces */
+    union {
+       uint8_t         c[0x1000 / 1];                  /* 0x02{0000,,,7FFF} */
+       uint16_t        s[0x1000 / 2];                  /* 0x02{0000,,,7FFF} */
+       uint32_t        l[0x1000 / 4];                  /* 0x02{0000,,,7FFF} */
+       uint64_t        d[0x1000 / 8];                  /* 0x02{0000,,,7FFF} */
+       union {
+           uint8_t     c[0x100 / 1];
+           uint16_t    s[0x100 / 2];
+           uint32_t    l[0x100 / 4];
+           uint64_t    d[0x100 / 8];
+       } f[8];
+    } cp_type0_cfg_dev[7];                             /* 0x02{1000,,,7FFF} */
+
+    /* 0x028000-0x028FFF -- PCI Type 1 Configuration Space */
+    union {
+       uint8_t         c[0x1000 / 1];                  /* 0x028000-0x029000 */
+       uint16_t        s[0x1000 / 2];                  /* 0x028000-0x029000 */
+       uint32_t        l[0x1000 / 4];                  /* 0x028000-0x029000 */
+       uint64_t        d[0x1000 / 8];                  /* 0x028000-0x029000 */
+       union {
+           uint8_t     c[0x100 / 1];
+           uint16_t    s[0x100 / 2];
+           uint32_t    l[0x100 / 4];
+           uint64_t    d[0x100 / 8];
+       } f[8];
+    } cp_type1_cfg;                                    /* 0x028000-0x029000 */
+
+    char               _pad_029000[0x030000-0x029000];
+
+    /* 0x030000-0x030007 -- PCI Interrupt Acknowledge Cycle */
+    union {
+       uint8_t         c[8 / 1];
+       uint16_t        s[8 / 2];
+       uint32_t        l[8 / 4];
+       uint64_t        d[8 / 8];
+    } cp_pci_iack;                                     /* 0x030000-0x030007 */
+
+    char               _pad_030007[0x040000-0x030008];
+
+    /* 0x040000-0x040007 -- PCIX Special Cycle */
+    union {
+       uint8_t         c[8 / 1];
+       uint16_t        s[8 / 2];
+       uint32_t        l[8 / 4];
+       uint64_t        d[8 / 8];
+    } cp_pcix_cycle;                                   /* 0x040000-0x040007 */
+
+    char               _pad_040007[0x200000-0x040008];
+
+    /* 0x200000-0x7FFFFF -- PCI/GIO Device Spaces */
+    union {
+       uint8_t         c[0x100000 / 1];
+       uint16_t        s[0x100000 / 2];
+       uint32_t        l[0x100000 / 4];
+       uint64_t        d[0x100000 / 8];
+    } cp_devio_raw[6];                                 /* 0x200000-0x7FFFFF */
+
+    #define cp_devio(n)  cp_devio_raw[((n)<2)?(n*2):(n+2)]
+
+    char               _pad_800000[0xA00000-0x800000];
+
+    /* 0xA00000-0xBFFFFF -- PCI/GIO Device Spaces w/flush  */
+    union {
+       uint8_t         c[0x100000 / 1];
+       uint16_t        s[0x100000 / 2];
+       uint32_t        l[0x100000 / 4];
+       uint64_t        d[0x100000 / 8];
+    } cp_devio_raw_flush[6];                           /* 0xA00000-0xBFFFFF */
+
+    #define cp_devio_flush(n)  cp_devio_raw_flush[((n)<2)?(n*2):(n+2)]
+
+};
+
+#endif         /* _ASM_IA64_SN_PCI_TIOCP_H */
diff --git a/include/asm-m32r/s1d13806.h b/include/asm-m32r/s1d13806.h
new file mode 100644 (file)
index 0000000..248d36a
--- /dev/null
@@ -0,0 +1,199 @@
+//----------------------------------------------------------------------------
+//
+//  File generated by S1D13806CFG.EXE
+//
+//  Copyright (c) 2000,2001 Epson Research and Development, Inc.
+//  All rights reserved.
+//
+//----------------------------------------------------------------------------
+
+// Panel:  (active)  640x480 77Hz STN Single 8-bit (PCLK=CLKI=25.175MHz)
+// Memory: Embedded SDRAM (MCLK=CLKI3=50.000MHz) (BUSCLK=33.333MHz)
+
+#define SWIVEL_VIEW            0       /* 0:none, 1:90 not completed */
+
+static struct s1d13xxxfb_regval s1d13xxxfb_initregs[] = {
+
+    {0x0001,0x00},   // Miscellaneous Register
+    {0x01FC,0x00},   // Display Mode Register
+#if defined(CONFIG_PLAT_MAPPI)
+    {0x0004,0x00},   // General IO Pins Configuration Register 0
+    {0x0005,0x00},   // General IO Pins Configuration Register 1
+    {0x0008,0x00},   // General IO Pins Control Register 0
+    {0x0009,0x00},   // General IO Pins Control Register 1
+    {0x0010,0x00},   // Memory Clock Configuration Register
+    {0x0014,0x00},   // LCD Pixel Clock Configuration Register
+    {0x0018,0x00},   // CRT/TV Pixel Clock Configuration Register
+    {0x001C,0x00},   // MediaPlug Clock Configuration Register
+/*
+ * .. 10MHz: 0x00
+ * .. 30MHz: 0x01
+ * 30MHz ..: 0x02
+ */
+    {0x001E,0x02},   // CPU To Memory Wait State Select Register
+    {0x0021,0x02},   // DRAM Refresh Rate Register
+    {0x002A,0x11},   // DRAM Timings Control Register 0
+    {0x002B,0x13},   // DRAM Timings Control Register 1
+    {0x0020,0x80},   // Memory Configuration Register
+    {0x0030,0x25},   // Panel Type Register
+    {0x0031,0x00},   // MOD Rate Register
+    {0x0032,0x4F},   // LCD Horizontal Display Width Register
+    {0x0034,0x12},   // LCD Horizontal Non-Display Period Register
+    {0x0035,0x01},   // TFT FPLINE Start Position Register
+    {0x0036,0x0B},   // TFT FPLINE Pulse Width Register
+    {0x0038,0xDF},   // LCD Vertical Display Height Register 0
+    {0x0039,0x01},   // LCD Vertical Display Height Register 1
+    {0x003A,0x2C},   // LCD Vertical Non-Display Period Register
+    {0x003B,0x0A},   // TFT FPFRAME Start Position Register
+    {0x003C,0x01},   // TFT FPFRAME Pulse Width Register
+
+    {0x0041,0x00},   // LCD Miscellaneous Register
+    {0x0042,0x00},   // LCD Display Start Address Register 0
+    {0x0043,0x00},   // LCD Display Start Address Register 1
+    {0x0044,0x00},   // LCD Display Start Address Register 2
+
+#elif defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI3)
+    {0x0004,0x07},   // GPIO[0:7] direction
+    {0x0005,0x00},   // GPIO[8:12] direction
+    {0x0008,0x00},   // GPIO[0:7] data
+    {0x0009,0x00},   // GPIO[8:12] data
+    {0x0008,0x04},   // LCD panel Vcc on
+    {0x0008,0x05},   // LCD panel reset
+    {0x0010,0x01},   // Memory Clock Configuration Register
+    {0x0014,0x30},   // LCD Pixel Clock Configuration Register (CLKI 22MHz/4)
+    {0x0018,0x00},   // CRT/TV Pixel Clock Configuration Register
+    {0x001C,0x00},   // MediaPlug Clock Configuration Register(10MHz)
+    {0x001E,0x00},   // CPU To Memory Wait State Select Register
+    {0x0020,0x80},   // Memory Configuration Register
+    {0x0021,0x03},   // DRAM Refresh Rate Register
+    {0x002A,0x00},   // DRAM Timings Control Register 0
+    {0x002B,0x01},   // DRAM Timings Control Register 1
+    {0x0030,0x25},   // Panel Type Register
+    {0x0031,0x00},   // MOD Rate Register
+    {0x0032,0x1d},   // LCD Horizontal Display Width Register
+    {0x0034,0x05},   // LCD Horizontal Non-Display Period Register
+    {0x0035,0x01},   // TFT FPLINE Start Position Register
+    {0x0036,0x01},   // TFT FPLINE Pulse Width Register
+    {0x0038,0x3F},   // LCD Vertical Display Height Register 0
+    {0x0039,0x01},   // LCD Vertical Display Height Register 1
+    {0x003A,0x0b},   // LCD Vertical Non-Display Period Register
+    {0x003B,0x07},   // TFT FPFRAME Start Position Register
+    {0x003C,0x02},   // TFT FPFRAME Pulse Width Register
+
+    {0x0041,0x00},   // LCD Miscellaneous Register
+#if (SWIVEL_VIEW == 0)
+    {0x0042,0x00},   // LCD Display Start Address Register 0
+    {0x0043,0x00},   // LCD Display Start Address Register 1
+    {0x0044,0x00},   // LCD Display Start Address Register 2
+
+#elif (SWIVEL_VIEW == 1)
+    // 1024 - W(320) = 0x2C0
+    {0x0042,0xC0},   // LCD Display Start Address Register 0
+    {0x0043,0x02},   // LCD Display Start Address Register 1
+    {0x0044,0x00},   // LCD Display Start Address Register 2
+    // 1024
+    {0x0046,0x00},   // LCD Memory Address Offset Register 0
+    {0x0047,0x02},   // LCD Memory Address Offset Register 1
+#else
+#error unsupported SWIVEL_VIEW mode
+#endif
+#else
+#error no platform configuration
+#endif  /* CONFIG_PLAT_XXX */
+
+    {0x0048,0x00},   // LCD Pixel Panning Register
+    {0x004A,0x00},   // LCD Display FIFO High Threshold Control Register
+    {0x004B,0x00},   // LCD Display FIFO Low Threshold Control Register
+    {0x0050,0x4F},   // CRT/TV Horizontal Display Width Register
+    {0x0052,0x13},   // CRT/TV Horizontal Non-Display Period Register
+    {0x0053,0x01},   // CRT/TV HRTC Start Position Register
+    {0x0054,0x0B},   // CRT/TV HRTC Pulse Width Register
+    {0x0056,0xDF},   // CRT/TV Vertical Display Height Register 0
+    {0x0057,0x01},   // CRT/TV Vertical Display Height Register 1
+    {0x0058,0x2B},   // CRT/TV Vertical Non-Display Period Register
+    {0x0059,0x09},   // CRT/TV VRTC Start Position Register
+    {0x005A,0x01},   // CRT/TV VRTC Pulse Width Register
+    {0x005B,0x10},   // TV Output Control Register
+
+    {0x0062,0x00},   // CRT/TV Display Start Address Register 0
+    {0x0063,0x00},   // CRT/TV Display Start Address Register 1
+    {0x0064,0x00},   // CRT/TV Display Start Address Register 2
+
+    {0x0068,0x00},   // CRT/TV Pixel Panning Register
+    {0x006A,0x00},   // CRT/TV Display FIFO High Threshold Control Register
+    {0x006B,0x00},   // CRT/TV Display FIFO Low Threshold Control Register
+    {0x0070,0x00},   // LCD Ink/Cursor Control Register
+    {0x0071,0x01},   // LCD Ink/Cursor Start Address Register
+    {0x0072,0x00},   // LCD Cursor X Position Register 0
+    {0x0073,0x00},   // LCD Cursor X Position Register 1
+    {0x0074,0x00},   // LCD Cursor Y Position Register 0
+    {0x0075,0x00},   // LCD Cursor Y Position Register 1
+    {0x0076,0x00},   // LCD Ink/Cursor Blue Color 0 Register
+    {0x0077,0x00},   // LCD Ink/Cursor Green Color 0 Register
+    {0x0078,0x00},   // LCD Ink/Cursor Red Color 0 Register
+    {0x007A,0x1F},   // LCD Ink/Cursor Blue Color 1 Register
+    {0x007B,0x3F},   // LCD Ink/Cursor Green Color 1 Register
+    {0x007C,0x1F},   // LCD Ink/Cursor Red Color 1 Register
+    {0x007E,0x00},   // LCD Ink/Cursor FIFO Threshold Register
+    {0x0080,0x00},   // CRT/TV Ink/Cursor Control Register
+    {0x0081,0x01},   // CRT/TV Ink/Cursor Start Address Register
+    {0x0082,0x00},   // CRT/TV Cursor X Position Register 0
+    {0x0083,0x00},   // CRT/TV Cursor X Position Register 1
+    {0x0084,0x00},   // CRT/TV Cursor Y Position Register 0
+    {0x0085,0x00},   // CRT/TV Cursor Y Position Register 1
+    {0x0086,0x00},   // CRT/TV Ink/Cursor Blue Color 0 Register
+    {0x0087,0x00},   // CRT/TV Ink/Cursor Green Color 0 Register
+    {0x0088,0x00},   // CRT/TV Ink/Cursor Red Color 0 Register
+    {0x008A,0x1F},   // CRT/TV Ink/Cursor Blue Color 1 Register
+    {0x008B,0x3F},   // CRT/TV Ink/Cursor Green Color 1 Register
+    {0x008C,0x1F},   // CRT/TV Ink/Cursor Red Color 1 Register
+    {0x008E,0x00},   // CRT/TV Ink/Cursor FIFO Threshold Register
+    {0x0100,0x00},   // BitBlt Control Register 0
+    {0x0101,0x00},   // BitBlt Control Register 1
+    {0x0102,0x00},   // BitBlt ROP Code/Color Expansion Register
+    {0x0103,0x00},   // BitBlt Operation Register
+    {0x0104,0x00},   // BitBlt Source Start Address Register 0
+    {0x0105,0x00},   // BitBlt Source Start Address Register 1
+    {0x0106,0x00},   // BitBlt Source Start Address Register 2
+    {0x0108,0x00},   // BitBlt Destination Start Address Register 0
+    {0x0109,0x00},   // BitBlt Destination Start Address Register 1
+    {0x010A,0x00},   // BitBlt Destination Start Address Register 2
+    {0x010C,0x00},   // BitBlt Memory Address Offset Register 0
+    {0x010D,0x00},   // BitBlt Memory Address Offset Register 1
+    {0x0110,0x00},   // BitBlt Width Register 0
+    {0x0111,0x00},   // BitBlt Width Register 1
+    {0x0112,0x00},   // BitBlt Height Register 0
+    {0x0113,0x00},   // BitBlt Height Register 1
+    {0x0114,0x00},   // BitBlt Background Color Register 0
+    {0x0115,0x00},   // BitBlt Background Color Register 1
+    {0x0118,0x00},   // BitBlt Foreground Color Register 0
+    {0x0119,0x00},   // BitBlt Foreground Color Register 1
+    {0x01E0,0x00},   // Look-Up Table Mode Register
+    {0x01E2,0x00},   // Look-Up Table Address Register
+    {0x01F0,0x10},   // Power Save Configuration Register
+    {0x01F1,0x00},   // Power Save Status Register
+    {0x01F4,0x00},   // CPU-to-Memory Access Watchdog Timer Register
+#if (SWIVEL_VIEW == 0)
+    {0x01FC,0x01},   // Display Mode Register(0x01:LCD, 0x02:CRT, 0x03:LCD&CRT)
+#elif (SWIVEL_VIEW == 1)
+    {0x01FC,0x41},   // Display Mode Register(0x01:LCD, 0x02:CRT, 0x03:LCD&CRT)
+#else
+#error unsupported SWIVEL_VIEW mode
+#endif  /* SWIVEL_VIEW */
+
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI3)
+    {0x0008,0x07},   // LCD panel Vdd & Vg on
+#endif
+
+    {0x0040,0x05},   // LCD Display Mode Register (2:4bpp,3:8bpp,5:16bpp)
+#if defined(CONFIG_PLAT_MAPPI)
+    {0x0046,0x80},   // LCD Memory Address Offset Register 0
+    {0x0047,0x02},   // LCD Memory Address Offset Register 1
+#elif defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI3)
+    {0x0046,0xf0},   // LCD Memory Address Offset Register 0
+    {0x0047,0x00},   // LCD Memory Address Offset Register 1
+#endif
+    {0x0060,0x05},   // CRT/TV Display Mode Register (2:4bpp,3:8bpp,5:16bpp)
+    {0x0066,0x80},   // CRT/TV Memory Address Offset Register 0        // takeo
+    {0x0067,0x02},   // CRT/TV Memory Address Offset Register 1
+};
index e8b79220b29c1687abb28a324ffc0ee010626cfd..a7894e0fbbb1a8d1e7f7719a2b7d4fda940ef263 100644 (file)
 #define __NR_rtas              255
 #define __NR_sys_debug_setcontext 256
 /* Number 257 is reserved for vserver */
-/* Number 258 is reserved for new sys_remap_file_pages */
+/* 258 currently unused */
 /* Number 259 is reserved for new sys_mbind */
 /* Number 260 is reserved for new sys_get_mempolicy */
 /* Number 261 is reserved for new sys_set_mempolicy */
index cbbfbec78b6bde7ec6eb9d6a05dcb56bd3d3b030..d67fa9e2607908477b8517df6a5ffe8bb9934337 100644 (file)
@@ -138,6 +138,7 @@ extern firmware_feature_t firmware_features_table[];
 #define CPU_FTR_COHERENT_ICACHE        ASM_CONST(0x0000020000000000)
 #define CPU_FTR_LOCKLESS_TLBIE         ASM_CONST(0x0000040000000000)
 #define CPU_FTR_MMCRA_SIHV             ASM_CONST(0x0000080000000000)
+#define CPU_FTR_CTRL                   ASM_CONST(0x0000100000000000)
 
 /* Platform firmware features */
 #define FW_FTR_                                ASM_CONST(0x0000000000000001)
@@ -148,7 +149,7 @@ extern firmware_feature_t firmware_features_table[];
 
 #define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \
                                  CPU_FTR_TLBIEL | CPU_FTR_NOEXECUTE | \
-                                 CPU_FTR_NODSISRALIGN)
+                                 CPU_FTR_NODSISRALIGN | CPU_FTR_CTRL)
 
 /* iSeries doesn't support large pages */
 #ifdef CONFIG_PPC_ISERIES
index d89d94c918158095e8e98bfb685ca0e995257072..6da93ce74dc06353faca972eb0d0fdce16138b34 100644 (file)
  */
 #define MAX_NR_HVC_CONSOLES    16
 
+/* implemented by a low level driver */
+struct hv_ops {
+       int (*get_chars)(uint32_t vtermno, char *buf, int count);
+       int (*put_chars)(uint32_t vtermno, const char *buf, int count);
+};
 extern int hvc_get_chars(uint32_t vtermno, char *buf, int count);
 extern int hvc_put_chars(uint32_t vtermno, const char *buf, int count);
 
-/* Early discovery of console adapters. */
-extern int hvc_find_vtys(void);
+struct hvc_struct;
 
-/* Implemented by a console driver */
-extern int hvc_instantiate(uint32_t vtermno, int index);
+/* Register a vterm and a slot index for use as a console (console_init) */
+extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops);
+/* register a vterm for hvc tty operation (module_init or hotplug add) */
+extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq,
+                                                struct hv_ops *ops);
+/* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */
+extern int __devexit hvc_remove(struct hvc_struct *hp);
 #endif /* _PPC64_HVCONSOLE_H */
index 9cdad3ed1526c2a6a74dff7f9c7d0d2ca8ec85b4..1e6ad4824132020c3a621bfba43144321016021f 100644 (file)
@@ -140,8 +140,13 @@ struct machdep_calls {
                                                unsigned long size,
                                                pgprot_t vma_prot);
 
+       /* Idle loop for this platform, leave empty for default idle loop */
+       int             (*idle_loop)(void);
 };
 
+extern int default_idle(void);
+extern int native_idle(void);
+
 extern struct machdep_calls ppc_md;
 extern char cmd_line[COMMAND_LINE_SIZE];
 
index af28aa55d8c1fe1cec34a17760af92a02c77ab3e..352306cfb579909177da4fec25492fd8b53adb2b 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/ptrace.h>
 #include <asm/types.h>
 #include <asm/systemcfg.h>
+#include <asm/cputable.h>
 
 /* Machine State Register (MSR) Fields */
 #define MSR_SF_LG      63              /* Enable 64 bit mode */
@@ -501,24 +502,37 @@ static inline void ppc64_runlatch_on(void)
 {
        unsigned long ctrl;
 
-       ctrl = mfspr(SPRN_CTRLF);
-       ctrl |= CTRL_RUNLATCH;
-       mtspr(SPRN_CTRLT, ctrl);
+       if (cpu_has_feature(CPU_FTR_CTRL)) {
+               ctrl = mfspr(SPRN_CTRLF);
+               ctrl |= CTRL_RUNLATCH;
+               mtspr(SPRN_CTRLT, ctrl);
+       }
 }
 
 static inline void ppc64_runlatch_off(void)
 {
        unsigned long ctrl;
 
-       ctrl = mfspr(SPRN_CTRLF);
-       ctrl &= ~CTRL_RUNLATCH;
-       mtspr(SPRN_CTRLT, ctrl);
+       if (cpu_has_feature(CPU_FTR_CTRL)) {
+               ctrl = mfspr(SPRN_CTRLF);
+               ctrl &= ~CTRL_RUNLATCH;
+               mtspr(SPRN_CTRLT, ctrl);
+       }
 }
 
 #endif /* __KERNEL__ */
 
 #endif /* __ASSEMBLY__ */
 
+#ifdef __KERNEL__
+#define RUNLATCH_ON(REG)                       \
+BEGIN_FTR_SECTION                              \
+       mfspr   (REG),SPRN_CTRLF;               \
+       ori     (REG),(REG),CTRL_RUNLATCH;      \
+       mtspr   SPRN_CTRLT,(REG);               \
+END_FTR_SECTION_IFSET(CPU_FTR_CTRL)
+#endif
+
 /*
  * Number of entries in the SLB. If this ever changes we should handle
  * it with a use a cpu feature fixup.
index 605d91e011ec10406f96e37cbb40220f3f801a0c..4a94acf6bfedd52c403b56b3ac1eb1fa99d415a3 100644 (file)
 #define __NR_rtas              255
 /* Number 256 is reserved for sys_debug_setcontext */
 /* Number 257 is reserved for vserver */
-/* Number 258 is reserved for new sys_remap_file_pages */
+/* 258 currently unused */
 #define __NR_mbind             259
 #define __NR_get_mempolicy     260
 #define __NR_set_mempolicy     261
 #define __NR_request_key       270
 #define __NR_keyctl            271
 #define __NR_waitid            272
+#define __NR_ioprio_set                273
+#define __NR_ioprio_get                274
 
-#define __NR_syscalls          273
+#define __NR_syscalls          275
 #ifdef __KERNEL__
 #define NR_syscalls    __NR_syscalls
 #endif
index 6a12f3ac035941768add42abb979606f834a18c9..a1cd4974630b4dbac56661a554e1f7b9f61e8f7d 100644 (file)
@@ -1,9 +1,10 @@
-/* $Id: param.h,v 1.2 2000/10/30 21:01:41 davem Exp $ */
 #ifndef _ASMSPARC64_PARAM_H
 #define _ASMSPARC64_PARAM_H
 
+#include <linux/config.h>
+
 #ifdef __KERNEL__
-# define HZ            1000    /* Internal kernel timer frequency */
+# define HZ            CONFIG_HZ       /* Internal kernel timer frequency */
 # define USER_HZ       100     /* .. some user interfaces are in "ticks" */
 # define CLOCKS_PER_SEC (USER_HZ)
 #endif
index 89bff310b7a908befa611258e8073526a064b1dd..7529c9c853dda226c1e42749121ed74b4b3e958e 100644 (file)
@@ -7,7 +7,9 @@
 #define __UM_MMU_CONTEXT_H
 
 #include "linux/sched.h"
+#include "linux/config.h"
 #include "choose-mode.h"
+#include "um_mmu.h"
 
 #define get_mmu_context(task) do ; while(0)
 #define activate_context(tsk) do ; while(0)
@@ -18,8 +20,6 @@ static inline void activate_mm(struct mm_struct *old, struct mm_struct *new)
 {
 }
 
-extern void switch_mm_skas(int mm_fd);
-
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, 
                             struct task_struct *tsk)
 {
@@ -30,7 +30,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
                cpu_set(cpu, next->cpu_vm_mask);
                if(next != &init_mm)
                        CHOOSE_MODE((void) 0, 
-                                   switch_mm_skas(next->context.skas.mm_fd));
+                                   switch_mm_skas(&next->context.skas.id));
        }
 }
 
index f2f073642d6295fdeaa97ce94f7c9fee4510f797..6c813eb521f339f363a71e21caca53ba204bfcf8 100644 (file)
@@ -15,6 +15,13 @@ extern void pda_init(int);
 extern void early_idt_handler(void);
 
 extern void mcheck_init(struct cpuinfo_x86 *c);
+#ifdef CONFIG_MTRR
+extern void mtrr_ap_init(void);
+extern void mtrr_bp_init(void);
+#else
+#define mtrr_ap_init() do {} while (0)
+#define mtrr_bp_init() do {} while (0)
+#endif
 extern void init_memory_mapping(unsigned long start, unsigned long end);
 
 extern void system_call(void); 
index 64c64dd83ba45129ad6239e6dfc0ce983a3c5736..6b39d6609d9c0c0fd2be7d05011e137ee73a631a 100644 (file)
 
 #include <linux/linkage.h>
 
-//#define __NR_setup             0 /* used only by init, to get system going */
 #define __NR_spill               0
 #define __NR_exit                1
-#define __NR_fork                2
 #define __NR_read                3
 #define __NR_write               4
 #define __NR_open                5
 #define __NR_close               6
-#define __NR_waitpid             7
 #define __NR_creat               8
 #define __NR_link                9
 #define __NR_unlink             10
 #define __NR_execve             11
 #define __NR_chdir              12
-#define __NR_time               13
 #define __NR_mknod              14
 #define __NR_chmod              15
 #define __NR_lchown             16
 #define __NR_break              17
-#define __NR_oldstat            18
 #define __NR_lseek              19
 #define __NR_getpid             20
 #define __NR_mount              21
-#define __NR_oldumount          22
 #define __NR_setuid             23
 #define __NR_getuid             24
-#define __NR_stime              25
 #define __NR_ptrace             26
-#define __NR_alarm              27
-#define __NR_oldfstat           28
-#define __NR_pause              29
 #define __NR_utime              30
 #define __NR_stty               31
 #define __NR_gtty               32
 #define __NR_access             33
-#define __NR_nice               34
 #define __NR_ftime              35
 #define __NR_sync               36
 #define __NR_kill               37
 #define __NR_geteuid            49
 #define __NR_getegid            50
 #define __NR_acct               51
-#define __NR_umount             52
 #define __NR_lock               53
 #define __NR_ioctl              54
 #define __NR_fcntl              55
-#define __NR_mpx                56
 #define __NR_setpgid            57
 #define __NR_ulimit             58
-#define __NR_oldolduname        59
 #define __NR_umask              60
 #define __NR_chroot             61
 #define __NR_ustat              62
 #define __NR_dup2               63
 #define __NR_getppid            64
-#define __NR_getpgrp            65
 #define __NR_setsid             66
 #define __NR_sigaction          67
-#define __NR_sgetmask           68
-#define __NR_ssetmask           69
 #define __NR_setreuid           70
 #define __NR_setregid           71
 #define __NR_sigsuspend                 72
 #define __NR_setgroups          81
 #define __NR_select             82
 #define __NR_symlink            83
-#define __NR_oldlstat           84
 #define __NR_readlink           85
 #define __NR_uselib             86
 #define __NR_swapon             87
 #define __NR_reboot             88
-#define __NR_readdir            89
-#define __NR_mmap               90
 #define __NR_munmap             91
 #define __NR_truncate           92
 #define __NR_ftruncate          93
 #define __NR_statfs             99
 #define __NR_fstatfs           100
 #define __NR_ioperm            101
-#define __NR_socketcall                102
 #define __NR_syslog            103
 #define __NR_setitimer         104
 #define __NR_getitimer         105
 #define __NR_stat              106
 #define __NR_lstat             107
 #define __NR_fstat             108
-#define __NR_olduname          109
 #define __NR_iopl              110
 #define __NR_vhangup           111
 #define __NR_idle              112
-#define __NR_vm86              113
 #define __NR_wait4             114
 #define __NR_swapoff           115
 #define __NR_sysinfo           116
-#define __NR_ipc               117
 #define __NR_fsync             118
 #define __NR_sigreturn         119
 #define __NR_clone             120
 #define __NR_modify_ldt                123
 #define __NR_adjtimex          124
 #define __NR_mprotect          125
-#define __NR_sigprocmask       126
 #define __NR_create_module     127
 #define __NR_init_module       128
 #define __NR_delete_module     129
-#define __NR_get_kernel_syms   130
 #define __NR_quotactl          131
 #define __NR_getpgid           132
 #define __NR_fchdir            133
 #define __NR_bdflush           134
 #define __NR_sysfs             135
 #define __NR_personality       136
-#define __NR_afs_syscall       137 /* Syscall for Andrew File System */
 #define __NR_setfsuid          138
 #define __NR_setfsgid          139
 #define __NR__llseek           140
 #define __NR_capset            205
 #define __NR_sigaltstack       206
 #define __NR_sendfile          207
-#define __NR_streams1          208     /* some people actually want it */
-#define __NR_streams2          209     /* some people actually want it */
 #define __NR_mmap2             210
 #define __NR_truncate64                211
 #define __NR_ftruncate64       212
 #define __NR_mincore           217
 #define __NR_madvise           218
 #define __NR_getdents64                219
-#define __NR_vfork             220
 
 /* Keep this last; should always equal the last valid call number. */
 #define __NR_Linux_syscalls     220
@@ -448,55 +418,7 @@ __syscall_return(type,__res); \
 
 
 #ifdef __KERNEL_SYSCALLS__
-
-#include <linux/compiler.h>
-#include <linux/types.h>
-#include <linux/syscalls.h>
-
-/*
- * we need this inline - forking from kernel space will result
- * in NO COPY ON WRITE (!!!), until an execve is executed. This
- * is no problem, but for the stack. This is handled by not letting
- * main() use the stack at all after fork(). Thus, no function
- * calls - which means inline code for fork too, as otherwise we
- * would use the stack upon exit from 'fork()'.
- *
- * Actually only pause and fork are needed inline, so that there
- * won't be any messing with the stack from main(), but we define
- * some others too.
- */
-
-#define __NR__exit __NR_exit
-
-static __inline__ _syscall0(int,pause)
-//static __inline__ _syscall1(int,setup,int,magic) FIXME
-static __inline__ _syscall0(int,sync)
-static __inline__ _syscall0(pid_t,setsid)
-static __inline__ _syscall3(int,write,int,fd,const char *,buf,off_t,count)
-static __inline__ _syscall3(int,read,int,fd,char *,buf,off_t,count)
-static __inline__ _syscall3(off_t,lseek,int,fd,off_t,offset,int,count)
-static __inline__ _syscall1(int,dup,int,fd)
 static __inline__ _syscall3(int,execve,const char*,file,char**,argv,char**,envp)
-static __inline__ _syscall3(int,open,const char *,file,int,flag,int,mode)
-static __inline__ _syscall1(int,close,int,fd)
-static __inline__ _syscall1(int,_exit,int,exitcode)
-static __inline__ _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
-static __inline__ _syscall1(int,delete_module,const char *,name)
-
-struct stat;
-static __inline__ _syscall2(int,fstat,int,fd,struct stat *,buf)
-static __inline__ _syscall0(pid_t,getpid)
-static __inline__ _syscall2(int,kill,int,pid,int,sig)
-static __inline__ _syscall2(int,stat,const char *, path,struct stat *,buf)
-static __inline__ _syscall1(int,unlink,char *,pathname)
-
-
-
-extern pid_t waitpid(int, int*, int );
-static __inline__ pid_t wait(int * wait_stat)
-{
-       return waitpid(-1,wait_stat,0);
-}
 #endif
 
 /*
@@ -508,30 +430,10 @@ static __inline__ pid_t wait(int * wait_stat)
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
 
 #ifdef __KERNEL__
-#define __ARCH_WANT_IPC_PARSE_VERSION
-#define __ARCH_WANT_OLD_READDIR
-#define __ARCH_WANT_OLD_STAT
 #define __ARCH_WANT_STAT64
-#define __ARCH_WANT_SYS_ALARM
-#define __ARCH_WANT_SYS_GETHOSTNAME
-#define __ARCH_WANT_SYS_PAUSE
-#define __ARCH_WANT_SYS_SGETMASK
-#define __ARCH_WANT_SYS_SIGNAL
-#define __ARCH_WANT_SYS_TIME
 #define __ARCH_WANT_SYS_UTIME
-#define __ARCH_WANT_SYS_WAITPID
-#define __ARCH_WANT_SYS_SOCKETCALL
-#define __ARCH_WANT_SYS_FADVISE64
-#define __ARCH_WANT_SYS_GETPGRP
 #define __ARCH_WANT_SYS_LLSEEK
-#define __ARCH_WANT_SYS_NICE
-#define __ARCH_WANT_SYS_OLD_GETRLIMIT
-#define __ARCH_WANT_SYS_OLDUMOUNT
-#define __ARCH_WANT_SYS_SIGPENDING
-#define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #endif
 
-
-
 #endif /* _XTENSA_UNISTD_H */
index 802c91e9b3da8b19c91f0a16c774a9bee342acee..90828493791f1d996ed3dc5e39c43219daf747e1 100644 (file)
@@ -19,6 +19,9 @@ enum bh_state_bits {
        BH_Dirty,       /* Is dirty */
        BH_Lock,        /* Is locked */
        BH_Req,         /* Has been submitted for I/O */
+       BH_Uptodate_Lock,/* Used by the first bh in a page, to serialise
+                         * IO completion of other buffers in the page
+                         */
 
        BH_Mapped,      /* Has a disk mapping */
        BH_New,         /* Disk mapping was newly created by get_block */
index 4d767b93738a9461268910c87757c6f1fe7e5e4c..2b66a36d85f021461c7bca4fd590109470c5dc20 100644 (file)
 #define SMP_CACHE_BYTES L1_CACHE_BYTES
 #endif
 
+#ifdef CONFIG_X86
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#else
+#define __read_mostly
+#endif
+
 #ifndef ____cacheline_aligned
 #define ____cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
 #endif
index 927daa86c9b366e52b41ff388303879896e6c6a4..ff7f80f48df1ba2fb87b1fac151d826532b2867d 100644 (file)
@@ -201,7 +201,7 @@ struct cpufreq_driver {
 
        /* optional */
        int     (*exit)         (struct cpufreq_policy *policy);
-       int     (*suspend)      (struct cpufreq_policy *policy, u32 state);
+       int     (*suspend)      (struct cpufreq_policy *policy, pm_message_t pmsg);
        int     (*resume)       (struct cpufreq_policy *policy);
        struct freq_attr        **attr;
 };
index 047bde30836ac0c1278e289bbff500dae39f570b..302ec20838caa6bcde0ce7c2303d22f72d1d6e1d 100644 (file)
@@ -1435,6 +1435,7 @@ extern struct inode * igrab(struct inode *);
 extern ino_t iunique(struct super_block *, ino_t);
 extern int inode_needs_sync(struct inode *inode);
 extern void generic_delete_inode(struct inode *inode);
+extern void generic_drop_inode(struct inode *inode);
 
 extern struct inode *ilookup5(struct super_block *sb, unsigned long hashval,
                int (*test)(struct inode *, void *), void *data);
index 8d6bf608b19942c91fd6939bbb1685c765174fd5..7c7400137e97f11dffd425004321d1e675b802a0 100644 (file)
@@ -12,8 +12,8 @@ struct vm_area_struct;
  * GFP bitmasks..
  */
 /* Zone modifiers in GFP_ZONEMASK (see linux/mmzone.h - low two bits) */
-#define __GFP_DMA      0x01
-#define __GFP_HIGHMEM  0x02
+#define __GFP_DMA      0x01u
+#define __GFP_HIGHMEM  0x02u
 
 /*
  * Action modifiers - doesn't change the zoning
index 390e760a96d3d12262a3519c53d76290bf4b7f7d..0c31ef0b5badc3d9dffb39a7414459d2101ae5dd 100644 (file)
@@ -148,7 +148,6 @@ struct ip_sf_socklist
 struct ip_mc_socklist
 {
        struct ip_mc_socklist   *next;
-       int                     count;
        struct ip_mreqn         multi;
        unsigned int            sfmode;         /* MCAST_{INCLUDE,EXCLUDE} */
        struct ip_sf_socklist   *sflist;
index 8a453a0b5e4b2b38ac20f2e1ae6c78c5ea5da598..88d5961f7a3f91e5651bf908703adbad8d578598 100644 (file)
@@ -34,9 +34,6 @@ enum {
  */
 #define IOPRIO_BE_NR   (8)
 
-asmlinkage int sys_ioprio_set(int, int, int);
-asmlinkage int sys_ioprio_get(int, int);
-
 enum {
        IOPRIO_WHO_PROCESS = 1,
        IOPRIO_WHO_PGRP,
index 8b8d3b9beefdc4f91cfa12d9275976408590cbcc..74b4727a4e3023aef8b411118a2e705e26321b75 100644 (file)
@@ -34,7 +34,7 @@ struct vfsmount
        int mnt_expiry_mark;            /* true if marked for expiry */
        char *mnt_devname;              /* Name of device e.g. /dev/dsk/hda1 */
        struct list_head mnt_list;
-       struct list_head mnt_fslink;    /* link in fs-specific expiry list */
+       struct list_head mnt_expire;    /* link in fs-specific expiry list */
        struct namespace *mnt_namespace; /* containing namespace */
 };
 
@@ -47,7 +47,7 @@ static inline struct vfsmount *mntget(struct vfsmount *mnt)
 
 extern void __mntput(struct vfsmount *mnt);
 
-static inline void _mntput(struct vfsmount *mnt)
+static inline void mntput_no_expire(struct vfsmount *mnt)
 {
        if (mnt) {
                if (atomic_dec_and_test(&mnt->mnt_count))
@@ -59,7 +59,7 @@ static inline void mntput(struct vfsmount *mnt)
 {
        if (mnt) {
                mnt->mnt_expiry_mark = 0;
-               _mntput(mnt);
+               mntput_no_expire(mnt);
        }
 }
 
index 697991b69f9b6d09e7d18f087490e66b018a78d1..0e5a86f13b2f8b4bbac4b50f32836827fef9fae8 100644 (file)
@@ -17,7 +17,8 @@ extern void __put_namespace(struct namespace *namespace);
 
 static inline void put_namespace(struct namespace *namespace)
 {
-       if (atomic_dec_and_test(&namespace->count))
+       if (atomic_dec_and_lock(&namespace->count, &vfsmount_lock))
+               /* releases vfsmount_lock */
                __put_namespace(namespace);
 }
 
index 5791dfd30dd02854a9ba0b1a163c3dba75ebb9a6..6d5a24f3fc6d902aad24b9c532d15dec3a863da1 100644 (file)
@@ -124,6 +124,7 @@ int         nfsd_statfs(struct svc_rqst *, struct svc_fh *,
 
 int            nfsd_notify_change(struct inode *, struct iattr *);
 int            nfsd_permission(struct svc_export *, struct dentry *, int);
+void           nfsd_sync_dir(struct dentry *dp);
 
 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
 #ifdef CONFIG_NFSD_V2_ACL
@@ -230,6 +231,7 @@ void                nfsd_lockd_shutdown(void);
 #define        nfserr_reclaim_bad      __constant_htonl(NFSERR_RECLAIM_BAD)
 #define        nfserr_badname          __constant_htonl(NFSERR_BADNAME)
 #define        nfserr_cb_path_down     __constant_htonl(NFSERR_CB_PATH_DOWN)
+#define        nfserr_locked           __constant_htonl(NFSERR_LOCKED)
 
 /* error codes for internal use */
 /* if a request fails due to kmalloc failure, it gets dropped.
index a84a3fa99be1b03a3102677ea31a28240389d419..8bf23cf8b6035d0a849bd02c1016f23d53522552 100644 (file)
@@ -203,7 +203,9 @@ struct nfs4_stateowner {
        int                     so_is_open_owner; /* 1=openowner,0=lockowner */
        u32                     so_id;
        struct nfs4_client *    so_client;
-       u32                     so_seqid;    
+       /* after increment in ENCODE_SEQID_OP_TAIL, represents the next
+        * sequence id expected from the client: */
+       u32                     so_seqid;
        struct xdr_netobj       so_owner;     /* open owner name */
        int                     so_confirmed; /* successful OPEN_CONFIRM? */
        struct nfs4_replay      so_replay;
@@ -235,6 +237,10 @@ struct nfs4_file {
 *       st_perlockowner: (open stateid) list of lock nfs4_stateowners
 *      st_access_bmap: used only for open stateid
 *      st_deny_bmap: used only for open stateid
+*      st_openstp: open stateid lock stateid was derived from
+*
+* XXX: open stateids and lock stateids have diverged sufficiently that
+* we should consider defining separate structs for the two cases.
 */
 
 struct nfs4_stateid {
@@ -248,6 +254,7 @@ struct nfs4_stateid {
        struct file                 * st_vfs_file;
        unsigned long                 st_access_bmap;
        unsigned long                 st_deny_bmap;
+       struct nfs4_stateid         * st_openstp;
 };
 
 /* flags for preprocess_seqid_op() */
index 14b9504134954d2b624494d1d8590e66c92081eb..5d4a990d5577b15dfc2fdeb14174969f184830fb 100644 (file)
@@ -300,20 +300,26 @@ struct sk_buff {
 #include <asm/system.h>
 
 extern void           __kfree_skb(struct sk_buff *skb);
-extern struct sk_buff *alloc_skb(unsigned int size, int priority);
+extern struct sk_buff *alloc_skb(unsigned int size,
+                                unsigned int __nocast priority);
 extern struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp,
-                                           unsigned int size, int priority);
+                                           unsigned int size,
+                                           unsigned int __nocast priority);
 extern void           kfree_skbmem(struct sk_buff *skb);
-extern struct sk_buff *skb_clone(struct sk_buff *skb, int priority);
-extern struct sk_buff *skb_copy(const struct sk_buff *skb, int priority);
-extern struct sk_buff *pskb_copy(struct sk_buff *skb, int gfp_mask);
+extern struct sk_buff *skb_clone(struct sk_buff *skb,
+                                unsigned int __nocast priority);
+extern struct sk_buff *skb_copy(const struct sk_buff *skb,
+                               unsigned int __nocast priority);
+extern struct sk_buff *pskb_copy(struct sk_buff *skb,
+                                unsigned int __nocast gfp_mask);
 extern int            pskb_expand_head(struct sk_buff *skb,
-                                       int nhead, int ntail, int gfp_mask);
+                                       int nhead, int ntail,
+                                       unsigned int __nocast gfp_mask);
 extern struct sk_buff *skb_realloc_headroom(struct sk_buff *skb,
                                            unsigned int headroom);
 extern struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
                                       int newheadroom, int newtailroom,
-                                      int priority);
+                                      unsigned int __nocast priority);
 extern struct sk_buff *                skb_pad(struct sk_buff *skb, int pad);
 #define dev_kfree_skb(a)       kfree_skb(a)
 extern void          skb_over_panic(struct sk_buff *skb, int len,
@@ -464,7 +470,8 @@ static inline int skb_shared(const struct sk_buff *skb)
  *
  *     NULL is returned on a memory allocation failure.
  */
-static inline struct sk_buff *skb_share_check(struct sk_buff *skb, int pri)
+static inline struct sk_buff *skb_share_check(struct sk_buff *skb,
+                                             unsigned int __nocast pri)
 {
        might_sleep_if(pri & __GFP_WAIT);
        if (skb_shared(skb)) {
@@ -1001,7 +1008,7 @@ static inline void __skb_queue_purge(struct sk_buff_head *list)
  *     %NULL is returned in there is no free memory.
  */
 static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
-                                             int gfp_mask)
+                                             unsigned int __nocast gfp_mask)
 {
        struct sk_buff *skb = alloc_skb(length + 16, gfp_mask);
        if (likely(skb))
@@ -1114,8 +1121,8 @@ static inline int skb_can_coalesce(struct sk_buff *skb, int i,
  *     If there is no free memory -ENOMEM is returned, otherwise zero
  *     is returned and the old skb data released.
  */
-extern int __skb_linearize(struct sk_buff *skb, int gfp);
-static inline int skb_linearize(struct sk_buff *skb, int gfp)
+extern int __skb_linearize(struct sk_buff *skb, unsigned int __nocast gfp);
+static inline int skb_linearize(struct sk_buff *skb, unsigned int __nocast gfp)
 {
        return __skb_linearize(skb, gfp);
 }
index 76cf7e60216c07b7c602e233c6315f6e3d93f09a..4c8e552471b00be3cfb165f6f1606681f3a17306 100644 (file)
@@ -65,7 +65,7 @@ extern void *kmem_cache_alloc(kmem_cache_t *, unsigned int __nocast);
 extern void kmem_cache_free(kmem_cache_t *, void *);
 extern unsigned int kmem_cache_size(kmem_cache_t *);
 extern const char *kmem_cache_name(kmem_cache_t *);
-extern kmem_cache_t *kmem_find_general_cachep(size_t size, int gfpflags);
+extern kmem_cache_t *kmem_find_general_cachep(size_t size, unsigned int __nocast gfpflags);
 
 /* Size description struct for general caches. */
 struct cache_sizes {
@@ -105,7 +105,7 @@ extern unsigned int ksize(const void *);
 
 #ifdef CONFIG_NUMA
 extern void *kmem_cache_alloc_node(kmem_cache_t *, int flags, int node);
-extern void *kmalloc_node(size_t size, int flags, int node);
+extern void *kmalloc_node(size_t size, unsigned int __nocast flags, int node);
 #else
 static inline void *kmem_cache_alloc_node(kmem_cache_t *cachep, int flags, int node)
 {
index 93994c61309538a8847c84911c6d78ded396bcd7..dab2652acbd8354a5f19745d6d1cac4ad7500ea0 100644 (file)
@@ -88,7 +88,7 @@ extern int memcmp(const void *,const void *,__kernel_size_t);
 extern void * memchr(const void *,int,__kernel_size_t);
 #endif
 
-extern char *kstrdup(const char *s, int gfp);
+extern char *kstrdup(const char *s, unsigned int __nocast gfp);
 
 #ifdef __cplusplus
 }
index 2343f999e6e11e287fa20532608d81796c3b58db..c75954f2d868213a2abbac0a9f3d8ddef3fb2fbb 100644 (file)
@@ -148,7 +148,7 @@ struct swap_list_t {
 #define vm_swap_full() (nr_swap_pages*2 < total_swap_pages)
 
 /* linux/mm/oom_kill.c */
-extern void out_of_memory(unsigned int __nocast gfp_mask);
+extern void out_of_memory(unsigned int __nocast gfp_mask, int order);
 
 /* linux/mm/memory.c */
 extern void swapin_readahead(swp_entry_t, unsigned long, struct vm_area_struct *);
index 52830b6d94e5c8fc926f291452b29bef4dcee91e..425f58c8ea4ae4c12ef53545e334542b3f161010 100644 (file)
@@ -506,4 +506,7 @@ asmlinkage long sys_request_key(const char __user *_type,
 asmlinkage long sys_keyctl(int cmd, unsigned long arg2, unsigned long arg3,
                           unsigned long arg4, unsigned long arg5);
 
+asmlinkage long sys_ioprio_set(int which, int who, int ioprio);
+asmlinkage long sys_ioprio_get(int which, int who);
+
 #endif
index 71d6af83b631702d3053e77814ea0b2eec250f29..92c828029cd8d46d8a753e3f7a3c54882572be89 100644 (file)
@@ -224,7 +224,7 @@ int  irda_device_is_receiving(struct net_device *dev);
 /* Interface for internal use */
 static inline int irda_device_txqueue_empty(const struct net_device *dev)
 {
-       return (skb_queue_len(&dev->qdisc->q) == 0);
+       return skb_queue_empty(&dev->qdisc->q);
 }
 int  irda_device_set_raw_mode(struct net_device* self, int status);
 struct net_device *alloc_irdadev(int sizeof_priv);
index 47727c7cc628abe7af68a9c69defdb7f11343ee0..7435528a1747564e394c61f80457295109cc93e7 100644 (file)
@@ -582,7 +582,6 @@ void sctp_datamsg_track(struct sctp_chunk *);
 void sctp_chunk_fail(struct sctp_chunk *, int error);
 int sctp_chunk_abandoned(struct sctp_chunk *);
 
-
 /* RFC2960 1.4 Key Terms
  *
  * o Chunk: A unit of information within an SCTP packet, consisting of
@@ -592,13 +591,8 @@ int sctp_chunk_abandoned(struct sctp_chunk *);
  * each chunk as well as a few other header pointers...
  */
 struct sctp_chunk {
-       /* These first three elements MUST PRECISELY match the first
-        * three elements of struct sk_buff.  This allows us to reuse
-        * all the skb_* queue management functions.
-        */
-       struct sctp_chunk *next;
-       struct sctp_chunk *prev;
-       struct sk_buff_head *list;
+       struct list_head list;
+
        atomic_t refcnt;
 
        /* This is our link to the per-transport transmitted list.  */
@@ -717,7 +711,7 @@ struct sctp_packet {
        __u32 vtag;
 
        /* This contains the payload chunks.  */
-       struct sk_buff_head chunks;
+       struct list_head chunk_list;
 
        /* This is the overhead of the sctp and ip headers. */
        size_t overhead;
@@ -974,7 +968,7 @@ struct sctp_inq {
        /* This is actually a queue of sctp_chunk each
         * containing a partially decoded packet.
         */
-       struct sk_buff_head in;
+       struct list_head in_chunk_list;
        /* This is the packet which is currently off the in queue and is
         * being worked on through the inbound chunk processing.
         */
@@ -1017,7 +1011,7 @@ struct sctp_outq {
        struct sctp_association *asoc;
 
        /* Data pending that has never been transmitted.  */
-       struct sk_buff_head out;
+       struct list_head out_chunk_list;
 
        unsigned out_qlen;      /* Total length of queued data chunks. */
 
@@ -1025,7 +1019,7 @@ struct sctp_outq {
        unsigned error;
 
        /* These are control chunks we want to send.  */
-       struct sk_buff_head control;
+       struct list_head control_chunk_list;
 
        /* These are chunks that have been sacked but are above the
         * CTSN, or cumulative tsn ack point.
@@ -1672,7 +1666,7 @@ struct sctp_association {
         *  which already resides in sctp_outq.  Please move this
         *  queue and its supporting logic down there.  --piggy]
         */
-       struct sk_buff_head addip_chunks;
+       struct list_head addip_chunk_list;
 
        /* ADDIP Section 4.1 ASCONF Chunk Procedures
         *
index 7b76f891ae2d4b9cdba1954dd02823c4eb3353a0..a1042d08becd538c4bb330d32ee64cd550ca2f39 100644 (file)
@@ -684,16 +684,17 @@ extern void FASTCALL(release_sock(struct sock *sk));
 #define bh_lock_sock(__sk)     spin_lock(&((__sk)->sk_lock.slock))
 #define bh_unlock_sock(__sk)   spin_unlock(&((__sk)->sk_lock.slock))
 
-extern struct sock             *sk_alloc(int family, int priority,
+extern struct sock             *sk_alloc(int family,
+                                         unsigned int __nocast priority,
                                          struct proto *prot, int zero_it);
 extern void                    sk_free(struct sock *sk);
 
 extern struct sk_buff          *sock_wmalloc(struct sock *sk,
                                              unsigned long size, int force,
-                                             int priority);
+                                             unsigned int __nocast priority);
 extern struct sk_buff          *sock_rmalloc(struct sock *sk,
                                              unsigned long size, int force,
-                                             int priority);
+                                             unsigned int __nocast priority);
 extern void                    sock_wfree(struct sk_buff *skb);
 extern void                    sock_rfree(struct sk_buff *skb);
 
@@ -708,7 +709,8 @@ extern struct sk_buff               *sock_alloc_send_skb(struct sock *sk,
                                                     unsigned long size,
                                                     int noblock,
                                                     int *errcode);
-extern void *sock_kmalloc(struct sock *sk, int size, int priority);
+extern void *sock_kmalloc(struct sock *sk, int size,
+                         unsigned int __nocast priority);
 extern void sock_kfree_s(struct sock *sk, void *mem, int size);
 extern void sk_send_sigurg(struct sock *sk);
 
@@ -1132,7 +1134,8 @@ static inline void sk_stream_moderate_sndbuf(struct sock *sk)
 }
 
 static inline struct sk_buff *sk_stream_alloc_pskb(struct sock *sk,
-                                                  int size, int mem, int gfp)
+                                                  int size, int mem,
+                                                  unsigned int __nocast gfp)
 {
        struct sk_buff *skb;
        int hdr_len;
@@ -1155,7 +1158,8 @@ static inline struct sk_buff *sk_stream_alloc_pskb(struct sock *sk,
 }
 
 static inline struct sk_buff *sk_stream_alloc_skb(struct sock *sk,
-                                                 int size, int gfp)
+                                                 int size,
+                                                 unsigned int __nocast gfp)
 {
        return sk_stream_alloc_pskb(sk, size, 0, gfp);
 }
@@ -1188,7 +1192,7 @@ static inline int sock_writeable(const struct sock *sk)
        return atomic_read(&sk->sk_wmem_alloc) < (sk->sk_sndbuf / 2);
 }
 
-static inline int gfp_any(void)
+static inline unsigned int __nocast gfp_any(void)
 {
        return in_softirq() ? GFP_ATOMIC : GFP_KERNEL;
 }
index a166918ca56d2f36f80f21d7678dd92b86c88454..f4f9aba07ac2ae59c6830f95ce7ae392d3bc2c42 100644 (file)
@@ -860,7 +860,8 @@ extern void tcp_send_probe0(struct sock *);
 extern void tcp_send_partial(struct sock *);
 extern int  tcp_write_wakeup(struct sock *);
 extern void tcp_send_fin(struct sock *sk);
-extern void tcp_send_active_reset(struct sock *sk, int priority);
+extern void tcp_send_active_reset(struct sock *sk,
+                                  unsigned int __nocast priority);
 extern int  tcp_send_synack(struct sock *);
 extern void tcp_push_one(struct sock *, unsigned int mss_now);
 extern void tcp_send_ack(struct sock *sk);
@@ -991,7 +992,7 @@ static __inline__ void tcp_fast_path_on(struct tcp_sock *tp)
 
 static inline void tcp_fast_path_check(struct sock *sk, struct tcp_sock *tp)
 {
-       if (skb_queue_len(&tp->out_of_order_queue) == 0 &&
+       if (skb_queue_empty(&tp->out_of_order_queue) &&
            tp->rcv_wnd &&
            atomic_read(&sk->sk_rmem_alloc) < sk->sk_rcvbuf &&
            !tp->urg_data)
index b42ddc0c1143348b896adb42c707fed132b5525e..2cab39f49eb2098a32b547fd51d2980608848615 100644 (file)
@@ -68,21 +68,9 @@ typedef struct adjust_t {
 #define RES_ALLOCATED                  0x20
 #define RES_REMOVED                    0x40
 
-typedef struct servinfo_t {
-    char       Signature[2];
-    u_int      Count;
-    u_int      Revision;
-    u_int      CSLevel;
-    char       *VendorString;
-} servinfo_t;
-
 typedef struct event_callback_args_t {
-    client_handle_t client_handle;
-    void       *info;
-    void       *mtdrequest;
-    void       *buffer;
-    void       *misc;
-    void       *client_data;
+       struct pcmcia_device    *client_handle;
+       void                    *client_data;
 } event_callback_args_t;
 
 /* for GetConfigurationInfo */
@@ -393,25 +381,25 @@ enum service {
 
 struct pcmcia_socket;
 
-int pcmcia_access_configuration_register(client_handle_t handle, conf_reg_t *reg);
-int pcmcia_deregister_client(client_handle_t handle);
-int pcmcia_get_configuration_info(client_handle_t handle, config_info_t *config);
+int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, conf_reg_t *reg);
+int pcmcia_deregister_client(struct pcmcia_device *p_dev);
+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(client_handle_t handle, cs_status_t *status);
+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(client_handle_t handle, modconf_t *mod);
+int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod);
 int pcmcia_register_client(client_handle_t *handle, client_reg_t *req);
-int pcmcia_release_configuration(client_handle_t handle);
-int pcmcia_release_io(client_handle_t handle, io_req_t *req);
-int pcmcia_release_irq(client_handle_t handle, irq_req_t *req);
+int pcmcia_release_configuration(struct pcmcia_device *p_dev);
+int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req);
+int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req);
 int pcmcia_release_window(window_handle_t win);
-int pcmcia_request_configuration(client_handle_t handle, config_req_t *req);
-int pcmcia_request_io(client_handle_t handle, io_req_t *req);
-int pcmcia_request_irq(client_handle_t handle, irq_req_t *req);
-int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle_t *wh);
-int pcmcia_reset_card(client_handle_t handle, client_req_t *req);
+int pcmcia_request_configuration(struct pcmcia_device *p_dev, config_req_t *req);
+int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req);
+int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req);
+int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_handle_t *wh);
+int pcmcia_reset_card(struct pcmcia_device *p_dev, client_req_t *req);
 int pcmcia_suspend_card(struct pcmcia_socket *skt);
 int pcmcia_resume_card(struct pcmcia_socket *skt);
 int pcmcia_eject_card(struct pcmcia_socket *skt);
index 7881d40aac8d5ffa9e1b8eead5c04171df38baa0..c1d1629fcd272a038bc359f81d9fa700eb4d8524 100644 (file)
@@ -34,8 +34,8 @@ typedef u_int event_t;
 typedef u_char cisdata_t;
 typedef u_short        page_t;
 
-struct client_t;
-typedef struct client_t *client_handle_t;
+struct pcmcia_device;
+typedef struct pcmcia_device *client_handle_t;
 
 struct window_t;
 typedef struct window_t *window_handle_t;
index 2b52553f2d945d3ff7c65ecdfb838b440745b1c5..0190e766e1a7b4a0ce07579dbbe38f0ad03df7cb 100644 (file)
@@ -49,7 +49,6 @@ typedef struct mtd_info_t {
 } mtd_info_t;
 
 typedef union ds_ioctl_arg_t {
-    servinfo_t         servinfo;
     adjust_t           adjust;
     config_info_t      config;
     tuple_t            tuple;
@@ -65,7 +64,6 @@ typedef union ds_ioctl_arg_t {
     cisdump_t          cisdump;
 } ds_ioctl_arg_t;
 
-#define DS_GET_CARD_SERVICES_INFO      _IOR ('d', 1, servinfo_t)
 #define DS_ADJUST_RESOURCE_INFO                _IOWR('d', 2, adjust_t)
 #define DS_GET_CONFIGURATION_INFO      _IOWR('d', 3, config_info_t)
 #define DS_GET_FIRST_TUPLE             _IOWR('d', 4, tuple_t)
@@ -133,6 +131,8 @@ struct pcmcia_socket;
 
 struct pcmcia_driver {
        dev_link_t              *(*attach)(void);
+       int (*event)            (event_t event, int priority,
+                                event_callback_args_t *);
        void                    (*detach)(dev_link_t *);
        struct module           *owner;
        struct pcmcia_device_id *id_table;
@@ -159,16 +159,8 @@ struct pcmcia_device {
        /* deprecated, a cleaned up version will be moved into this
           struct soon */
        dev_link_t              *instance;
-       struct client_t {
-               u_short                 client_magic;
-               struct pcmcia_socket    *Socket;
-               u_char                  Function;
-               u_int                   state;
-               event_t                 EventMask;
-               int (*event_handler)    (event_t event, int priority,
-                                        event_callback_args_t *);
-               event_callback_args_t   event_callback_args;
-       }                       client;
+       event_callback_args_t   event_callback_args;
+       u_int                   state;
 
        /* information about this device */
        u8                      has_manf_id:1;
@@ -193,8 +185,8 @@ struct pcmcia_device {
 #define to_pcmcia_dev(n) container_of(n, struct pcmcia_device, dev)
 #define to_pcmcia_drv(n) container_of(n, struct pcmcia_driver, drv)
 
-#define handle_to_pdev(handle) container_of(handle, struct pcmcia_device, client);
-#define handle_to_dev(handle) ((container_of(handle, struct pcmcia_device, client))->dev)
+#define handle_to_pdev(handle) (handle)
+#define handle_to_dev(handle) (handle->dev)
 
 /* error reporting */
 void cs_error(client_handle_t handle, int func, int ret);
index eb88263fc8d59df4d553e72929cdf331bfd9c8ae..5ad9c5e198b62ebadebd043d826f6805d44fa80f 100644 (file)
@@ -1,4 +1,3 @@
 /* version.h 1.94 2000/10/03 17:55:48 (David Hinds) */
 
-#define CS_RELEASE "3.1.22"
-#define CS_RELEASE_CODE 0x3116
+/* This file will be removed, please don't include it */
index 70e4e4e10fd184002fad4dab2a3c5056f6f08036..3881d564c66837ad6a925ae7a43e429cf30cd482 100644 (file)
@@ -572,6 +572,7 @@ static inline int put_compat_shminfo(struct shminfo64 *smi,
        err |= __put_user(smi->shmmni, &up->shmmni);
        err |= __put_user(smi->shmseg, &up->shmseg);
        err |= __put_user(smi->shmall, &up->shmall);
+       return err;
 }
 
 static inline int put_compat_shm_info(struct shm_info __user *ip,
index fb8de63c29192061a6938417bac924a55e800851..c51a4d96d4ebc68c469d40bb1cdd3c31605c1aad 100644 (file)
@@ -234,6 +234,16 @@ static int software_resume(void)
 {
        int error;
 
+       if (!swsusp_resume_device) {
+               if (!strlen(resume_file))
+                       return -ENOENT;
+               swsusp_resume_device = name_to_dev_t(resume_file);
+               pr_debug("swsusp: Resume From Partition %s\n", resume_file);
+       } else {
+               pr_debug("swsusp: Resume From Partition %d:%d\n",
+                        MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device));
+       }
+
        if (noresume) {
                /**
                 * FIXME: If noresume is specified, we need to find the partition
index 0a086640bcfc15cce008901702549fd0061a498c..3bd0d261818f5d7769af8b265544dbe8abf5d519 100644 (file)
@@ -59,6 +59,7 @@ int freeze_processes(void)
        int todo;
        unsigned long start_time;
        struct task_struct *g, *p;
+       unsigned long flags;
 
        printk( "Stopping tasks: " );
        start_time = jiffies;
@@ -66,12 +67,9 @@ int freeze_processes(void)
                todo = 0;
                read_lock(&tasklist_lock);
                do_each_thread(g, p) {
-                       unsigned long flags;
                        if (!freezeable(p))
                                continue;
-                       if ((frozen(p)) ||
-                           (p->state == TASK_TRACED) ||
-                           (p->state == TASK_STOPPED))
+                       if (frozen(p))
                                continue;
 
                        freeze(p);
index c285fc5a232094c9f7b5e27950525ae942bc99b1..7d7801cd01f0fabdcae0bbad78d24fe0a4da2b66 100644 (file)
@@ -869,13 +869,6 @@ extern asmlinkage int swsusp_arch_resume(void);
 
 asmlinkage int swsusp_save(void)
 {
-       int error = 0;
-
-       if ((error = swsusp_swap_check())) {
-               printk(KERN_ERR "swsusp: FATAL: cannot find swap device, try "
-                               "swapon -a!\n");
-               return error;
-       }
        return suspend_prepare_image();
 }
 
@@ -892,14 +885,20 @@ int swsusp_suspend(void)
         * at resume time, and evil weirdness ensues.
         */
        if ((error = device_power_down(PMSG_FREEZE))) {
-               printk(KERN_ERR "Some devices failed to power down, aborting suspend\n");
                local_irq_enable();
-               swsusp_free();
                return error;
        }
+
+       if ((error = swsusp_swap_check())) {
+               printk(KERN_ERR "swsusp: FATAL: cannot find swap device, try "
+                               "swapon -a!\n");
+               local_irq_enable();
+               return error;
+       }
+
        save_processor_state();
        if ((error = swsusp_arch_suspend()))
-               swsusp_free();
+               printk("Error %d suspending\n", error);
        /* Restore control flow magically appears here */
        restore_processor_state();
        BUG_ON (nr_copy_pages_check != nr_copy_pages);
@@ -1166,9 +1165,9 @@ static int bio_write_page(pgoff_t page_off, void * page)
 static const char * sanity_check(void)
 {
        dump_info();
-       if(swsusp_info.version_code != LINUX_VERSION_CODE)
+       if (swsusp_info.version_code != LINUX_VERSION_CODE)
                return "kernel version";
-       if(swsusp_info.num_physpages != num_physpages)
+       if (swsusp_info.num_physpages != num_physpages)
                return "memory size";
        if (strcmp(swsusp_info.uts.sysname,system_utsname.sysname))
                return "system type";
@@ -1356,16 +1355,6 @@ int swsusp_check(void)
 {
        int error;
 
-       if (!swsusp_resume_device) {
-               if (!strlen(resume_file))
-                       return -ENOENT;
-               swsusp_resume_device = name_to_dev_t(resume_file);
-               pr_debug("swsusp: Resume From Partition %s\n", resume_file);
-       } else {
-               pr_debug("swsusp: Resume From Partition %d:%d\n",
-                        MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device));
-       }
-
        resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ);
        if (!IS_ERR(resume_bdev)) {
                set_blocksize(resume_bdev, PAGE_SIZE);
index ad8cbb75ffa2c4921031a161b497df10fcf0a22f..f89248e6d70479f73e34e78faf62fefa6fb532fe 100644 (file)
@@ -35,11 +35,11 @@ struct profile_hit {
 #define NR_PROFILE_GRP         (NR_PROFILE_HIT/PROFILE_GRPSZ)
 
 /* Oprofile timer tick hook */
-int (*timer_hook)(struct pt_regs *);
+int (*timer_hook)(struct pt_regs *) __read_mostly;
 
 static atomic_t *prof_buffer;
 static unsigned long prof_len, prof_shift;
-static int prof_on;
+static int prof_on __read_mostly;
 static cpumask_t prof_cpu_mask = CPU_MASK_ALL;
 #ifdef CONFIG_SMP
 static DEFINE_PER_CPU(struct profile_hit *[2], cpu_profile_hits);
index 5f2182d42241d20b41a12eb9da9671927b5b36d8..4107db0dc0919767b72b31e8dd88a5580294a578 100644 (file)
@@ -3877,6 +3877,13 @@ asmlinkage long sys_sched_yield(void)
 
 static inline void __cond_resched(void)
 {
+       /*
+        * The BKS might be reacquired before we have dropped
+        * PREEMPT_ACTIVE, which could trigger a second
+        * cond_resched() call.
+        */
+       if (unlikely(preempt_count()))
+               return;
        do {
                add_preempt_count(PREEMPT_ACTIVE);
                schedule();
index 04d664377f2c628bf5bc102df3c311532f3a65f7..10bed1c8c3c3012b861a055eaaf095af7906e8e5 100644 (file)
@@ -58,7 +58,7 @@ struct radix_tree_path {
 #define RADIX_TREE_INDEX_BITS  (8 /* CHAR_BIT */ * sizeof(unsigned long))
 #define RADIX_TREE_MAX_PATH (RADIX_TREE_INDEX_BITS/RADIX_TREE_MAP_SHIFT + 2)
 
-static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH];
+static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH] __read_mostly;
 
 /*
  * Radix tree node cache.
index 9a72f7d918fa251bd7b21720ba964af5c1cdc341..65f2957b8d518b7a6d244a339fd4dc5ce85ab9a9 100644 (file)
@@ -205,7 +205,7 @@ void * mempool_alloc(mempool_t *pool, unsigned int __nocast gfp_mask)
        void *element;
        unsigned long flags;
        wait_queue_t wait;
-       int gfp_temp;
+       unsigned int gfp_temp;
 
        might_sleep_if(gfp_mask & __GFP_WAIT);
 
index 59666d905f1997521c89f4a7b1a492df4414be0e..1e56076672f5870e9766753270d77442e5743ac9 100644 (file)
@@ -253,14 +253,16 @@ static struct mm_struct *oom_kill_process(struct task_struct *p)
  * OR try to be smart about which process to kill. Note that we
  * don't have to be perfect here, we just have to be good.
  */
-void out_of_memory(unsigned int __nocast gfp_mask)
+void out_of_memory(unsigned int __nocast gfp_mask, int order)
 {
        struct mm_struct *mm = NULL;
        task_t * p;
 
-       printk("oom-killer: gfp_mask=0x%x\n", gfp_mask);
-       /* print memory stats */
-       show_mem();
+       if (printk_ratelimit()) {
+               printk("oom-killer: gfp_mask=0x%x, order=%d\n",
+                       gfp_mask, order);
+               show_mem();
+       }
 
        read_lock(&tasklist_lock);
 retry:
index 3c9f7f88112543d2e72021c576cc377a2244e295..1d6ba6a4b594e7db82617c67449831482f52412d 100644 (file)
@@ -897,12 +897,6 @@ rebalance:
        cond_resched();
 
        if (likely(did_some_progress)) {
-               /*
-                * Go through the zonelist yet one more time, keep
-                * very high watermark here, this is only to catch
-                * a parallel oom killing, we must fail if we're still
-                * under heavy pressure.
-                */
                for (i = 0; (z = zones[i]) != NULL; i++) {
                        if (!zone_watermark_ok(z, order, z->pages_min,
                                               classzone_idx, can_try_harder,
@@ -936,7 +930,7 @@ rebalance:
                                goto got_pg;
                }
 
-               out_of_memory(gfp_mask);
+               out_of_memory(gfp_mask, order);
                goto restart;
        }
 
index e57abd45eede051ff73c6ded3f9f754fbb9b7144..c9e706db46340f81f723e899d45510cdfe78d50c 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -584,7 +584,8 @@ static inline struct array_cache *ac_data(kmem_cache_t *cachep)
        return cachep->array[smp_processor_id()];
 }
 
-static inline kmem_cache_t *__find_general_cachep(size_t size, int gfpflags)
+static inline kmem_cache_t *__find_general_cachep(size_t size,
+                                               unsigned int __nocast gfpflags)
 {
        struct cache_sizes *csizep = malloc_sizes;
 
@@ -608,7 +609,8 @@ static inline kmem_cache_t *__find_general_cachep(size_t size, int gfpflags)
        return csizep->cs_cachep;
 }
 
-kmem_cache_t *kmem_find_general_cachep(size_t size, int gfpflags)
+kmem_cache_t *kmem_find_general_cachep(size_t size,
+               unsigned int __nocast gfpflags)
 {
        return __find_general_cachep(size, gfpflags);
 }
@@ -2100,7 +2102,7 @@ cache_alloc_debugcheck_before(kmem_cache_t *cachep, unsigned int __nocast flags)
 #if DEBUG
 static void *
 cache_alloc_debugcheck_after(kmem_cache_t *cachep,
-                       unsigned long flags, void *objp, void *caller)
+                       unsigned int __nocast flags, void *objp, void *caller)
 {
        if (!objp)      
                return objp;
@@ -2442,7 +2444,7 @@ got_slabp:
 }
 EXPORT_SYMBOL(kmem_cache_alloc_node);
 
-void *kmalloc_node(size_t size, int flags, int node)
+void *kmalloc_node(size_t size, unsigned int __nocast flags, int node)
 {
        kmem_cache_t *cachep;
 
@@ -3094,7 +3096,7 @@ unsigned int ksize(const void *objp)
  * @s: the string to duplicate
  * @gfp: the GFP mask used in the kmalloc() call when allocating memory
  */
-char *kstrdup(const char *s, int gfp)
+char *kstrdup(const char *s, unsigned int __nocast gfp)
 {
        size_t len;
        char *buf;
index 2e341de3e7634fda2ff7ee7bf912cc56f8003643..901eff7ebe74072d0c7f15df3ad5a420248b85a5 100644 (file)
@@ -213,7 +213,7 @@ static int cmtp_send_frame(struct cmtp_session *session, unsigned char *data, in
        return kernel_sendmsg(sock, &msg, &iv, 1, len);
 }
 
-static int cmtp_process_transmit(struct cmtp_session *session)
+static void cmtp_process_transmit(struct cmtp_session *session)
 {
        struct sk_buff *skb, *nskb;
        unsigned char *hdr;
@@ -223,7 +223,7 @@ static int cmtp_process_transmit(struct cmtp_session *session)
 
        if (!(nskb = alloc_skb(session->mtu, GFP_ATOMIC))) {
                BT_ERR("Can't allocate memory for new frame");
-               return -ENOMEM;
+               return;
        }
 
        while ((skb = skb_dequeue(&session->transmit))) {
@@ -275,8 +275,6 @@ static int cmtp_process_transmit(struct cmtp_session *session)
        cmtp_send_frame(session, nskb->data, nskb->len);
 
        kfree_skb(nskb);
-
-       return skb_queue_len(&session->transmit);
 }
 
 static int cmtp_session(void *arg)
index affbc55462e860f8a525ac9cecac09ca2cdf9ef9..de8af5f423942750c9677dd86f461366b9f56923 100644 (file)
@@ -428,7 +428,7 @@ static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
        return kernel_sendmsg(sock, &msg, &iv, 1, len);
 }
 
-static int hidp_process_transmit(struct hidp_session *session)
+static void hidp_process_transmit(struct hidp_session *session)
 {
        struct sk_buff *skb;
 
@@ -453,9 +453,6 @@ static int hidp_process_transmit(struct hidp_session *session)
                hidp_set_timer(session);
                kfree_skb(skb);
        }
-
-       return skb_queue_len(&session->ctrl_transmit) +
-                               skb_queue_len(&session->intr_transmit);
 }
 
 static int hidp_session(void *arg)
index f3f6355a2786c78eefe8213fe95dd67cfb93b31f..63a123c5c41b38dedef853b56c44ac4f55d55d16 100644 (file)
@@ -590,8 +590,11 @@ static long rfcomm_sock_data_wait(struct sock *sk, long timeo)
        for (;;) {
                set_current_state(TASK_INTERRUPTIBLE);
 
-               if (skb_queue_len(&sk->sk_receive_queue) || sk->sk_err || (sk->sk_shutdown & RCV_SHUTDOWN) ||
-                               signal_pending(current) || !timeo)
+               if (!skb_queue_empty(&sk->sk_receive_queue) ||
+                   sk->sk_err ||
+                   (sk->sk_shutdown & RCV_SHUTDOWN) ||
+                   signal_pending(current) ||
+                   !timeo)
                        break;
 
                set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
index 6d689200bcf3e9c68113b964b610668d6c631f68..6304590fd36a5f6d132f8a6262d5acdb616c0ebf 100644 (file)
@@ -781,7 +781,7 @@ static int rfcomm_tty_chars_in_buffer(struct tty_struct *tty)
 
        BT_DBG("tty %p dev %p", tty, dev);
 
-       if (skb_queue_len(&dlc->tx_queue))
+       if (!skb_queue_empty(&dlc->tx_queue))
                return dlc->mtu;
 
        return 0;
index 7f5f62c651156683734b0adf2c4aea31cb2f846f..ff9dc029233a850cfa3985525c89d1da761601f8 100644 (file)
@@ -1127,7 +1127,7 @@ static inline int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
 extern void skb_release_data(struct sk_buff *);
 
 /* Keep head the same: replace data */
-int __skb_linearize(struct sk_buff *skb, int gfp_mask)
+int __skb_linearize(struct sk_buff *skb, unsigned int __nocast gfp_mask)
 {
        unsigned int size;
        u8 *data;
index 733deee24b9f6004452881f09d4477383c171c69..d9f7b06fe88678882f3a8fdd6dc42a43db39786b 100644 (file)
@@ -129,7 +129,7 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here)
  *     Buffers may only be allocated from interrupts using a @gfp_mask of
  *     %GFP_ATOMIC.
  */
-struct sk_buff *alloc_skb(unsigned int size, int gfp_mask)
+struct sk_buff *alloc_skb(unsigned int size, unsigned int __nocast gfp_mask)
 {
        struct sk_buff *skb;
        u8 *data;
@@ -182,7 +182,8 @@ nodata:
  *     %GFP_ATOMIC.
  */
 struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp,
-                                    unsigned int size, int gfp_mask)
+                                    unsigned int size,
+                                    unsigned int __nocast gfp_mask)
 {
        struct sk_buff *skb;
        u8 *data;
@@ -322,7 +323,7 @@ void __kfree_skb(struct sk_buff *skb)
  *     %GFP_ATOMIC.
  */
 
-struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask)
+struct sk_buff *skb_clone(struct sk_buff *skb, unsigned int __nocast gfp_mask)
 {
        struct sk_buff *n = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
 
@@ -460,7 +461,7 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
  *     header is going to be modified. Use pskb_copy() instead.
  */
 
-struct sk_buff *skb_copy(const struct sk_buff *skb, int gfp_mask)
+struct sk_buff *skb_copy(const struct sk_buff *skb, unsigned int __nocast gfp_mask)
 {
        int headerlen = skb->data - skb->head;
        /*
@@ -499,7 +500,7 @@ struct sk_buff *skb_copy(const struct sk_buff *skb, int gfp_mask)
  *     The returned buffer has a reference count of 1.
  */
 
-struct sk_buff *pskb_copy(struct sk_buff *skb, int gfp_mask)
+struct sk_buff *pskb_copy(struct sk_buff *skb, unsigned int __nocast gfp_mask)
 {
        /*
         *      Allocate the copy buffer
@@ -557,7 +558,8 @@ out:
  *     reloaded after call to this function.
  */
 
-int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, int gfp_mask)
+int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
+                    unsigned int __nocast gfp_mask)
 {
        int i;
        u8 *data;
@@ -647,7 +649,8 @@ struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom)
  *     only by netfilter in the cases when checksum is recalculated? --ANK
  */
 struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
-                               int newheadroom, int newtailroom, int gfp_mask)
+                               int newheadroom, int newtailroom,
+                               unsigned int __nocast gfp_mask)
 {
        /*
         *      Allocate the copy buffer
index a6ec3ada7f9e73fd748de17aff5b9c08f73a6f97..8b35ccdc2b3b7889f4cf8715389ce25ef43c90f9 100644 (file)
@@ -622,7 +622,8 @@ lenout:
  *     @prot: struct proto associated with this new sock instance
  *     @zero_it: if we should zero the newly allocated sock
  */
-struct sock *sk_alloc(int family, int priority, struct proto *prot, int zero_it)
+struct sock *sk_alloc(int family, unsigned int __nocast priority,
+                     struct proto *prot, int zero_it)
 {
        struct sock *sk = NULL;
        kmem_cache_t *slab = prot->slab;
@@ -750,7 +751,8 @@ unsigned long sock_i_ino(struct sock *sk)
 /*
  * Allocate a skb from the socket's send buffer.
  */
-struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, int priority)
+struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force,
+                            unsigned int __nocast priority)
 {
        if (force || atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) {
                struct sk_buff * skb = alloc_skb(size, priority);
@@ -765,7 +767,8 @@ struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, int
 /*
  * Allocate a skb from the socket's receive buffer.
  */ 
-struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, int priority)
+struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force,
+                            unsigned int __nocast priority)
 {
        if (force || atomic_read(&sk->sk_rmem_alloc) < sk->sk_rcvbuf) {
                struct sk_buff *skb = alloc_skb(size, priority);
@@ -780,7 +783,7 @@ struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, int
 /* 
  * Allocate a memory block from the socket's option memory buffer.
  */ 
-void *sock_kmalloc(struct sock *sk, int size, int priority)
+void *sock_kmalloc(struct sock *sk, int size, unsigned int __nocast priority)
 {
        if ((unsigned)size <= sysctl_optmem_max &&
            atomic_read(&sk->sk_omem_alloc) + size < sysctl_optmem_max) {
index 29bb3cd219655bb93e1fe6bc13d82eb40f4f9654..96a02800cd283648e7d92d24c05e863ac4706353 100644 (file)
@@ -536,7 +536,7 @@ static void dn_keepalive(struct sock *sk)
         * we are double checking that we are not sending too
         * many of these keepalive frames.
         */
-       if (skb_queue_len(&scp->other_xmit_queue) == 0)
+       if (skb_queue_empty(&scp->other_xmit_queue))
                dn_nsp_send_link(sk, DN_NOCHANGE, 0);
 }
 
@@ -1191,7 +1191,7 @@ static unsigned int dn_poll(struct file *file, struct socket *sock, poll_table
        struct dn_scp *scp = DN_SK(sk);
        int mask = datagram_poll(file, sock, wait);
 
-       if (skb_queue_len(&scp->other_receive_queue))
+       if (!skb_queue_empty(&scp->other_receive_queue))
                mask |= POLLRDBAND;
 
        return mask;
@@ -1214,7 +1214,7 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 
        case SIOCATMARK:
                lock_sock(sk);
-               val = (skb_queue_len(&scp->other_receive_queue) != 0);
+               val = !skb_queue_empty(&scp->other_receive_queue);
                if (scp->state != DN_RUN)
                        val = -ENOTCONN;
                release_sock(sk);
@@ -1630,7 +1630,7 @@ static int dn_data_ready(struct sock *sk, struct sk_buff_head *q, int flags, int
        int len = 0;
 
        if (flags & MSG_OOB)
-               return skb_queue_len(q) ? 1 : 0;
+               return !skb_queue_empty(q) ? 1 : 0;
 
        while(skb != (struct sk_buff *)q) {
                struct dn_skb_cb *cb = DN_SKB_CB(skb);
@@ -1707,7 +1707,7 @@ static int dn_recvmsg(struct kiocb *iocb, struct socket *sock,
                if (sk->sk_err)
                        goto out;
 
-               if (skb_queue_len(&scp->other_receive_queue)) {
+               if (!skb_queue_empty(&scp->other_receive_queue)) {
                        if (!(flags & MSG_OOB)) {
                                msg->msg_flags |= MSG_OOB;
                                if (!scp->other_report) {
index 42abbf3f524f671b2a94307c216c38ff31f215bc..8cce1fdbda907ac29dc29c2ea530102cc8f36d86 100644 (file)
@@ -342,7 +342,8 @@ int dn_nsp_xmit_timeout(struct sock *sk)
 
        dn_nsp_output(sk);
 
-       if (skb_queue_len(&scp->data_xmit_queue) || skb_queue_len(&scp->other_xmit_queue))
+       if (!skb_queue_empty(&scp->data_xmit_queue) ||
+           !skb_queue_empty(&scp->other_xmit_queue))
                scp->persist = dn_nsp_persist(sk);
 
        return 0;
index cb759484979d94d46d946a66cca3ef4bf87d84a1..279f57abfecb5f3bbe8c10c23a4445f7180bd01e 100644 (file)
@@ -970,7 +970,8 @@ int icmp_rcv(struct sk_buff *skb)
                 *      RFC 1122: 3.2.2.8 An ICMP_TIMESTAMP MAY be silently
                 *        discarded if to broadcast/multicast.
                 */
-               if (icmph->type == ICMP_ECHO &&
+               if ((icmph->type == ICMP_ECHO ||
+                    icmph->type == ICMP_TIMESTAMP) &&
                    sysctl_icmp_echo_ignore_broadcasts) {
                        goto error;
                }
index 1f3183168a90ef749b83e289ca99eb4fb7d4d875..5088f90835ae00694a31a8cdfa9b91829a4c5396 100644 (file)
@@ -1615,9 +1615,10 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
 {
        int err;
        u32 addr = imr->imr_multiaddr.s_addr;
-       struct ip_mc_socklist *iml, *i;
+       struct ip_mc_socklist *iml=NULL, *i;
        struct in_device *in_dev;
        struct inet_sock *inet = inet_sk(sk);
+       int ifindex;
        int count = 0;
 
        if (!MULTICAST(addr))
@@ -1633,37 +1634,30 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
                goto done;
        }
 
-       iml = (struct ip_mc_socklist *)sock_kmalloc(sk, sizeof(*iml), GFP_KERNEL);
-
        err = -EADDRINUSE;
+       ifindex = imr->imr_ifindex;
        for (i = inet->mc_list; i; i = i->next) {
-               if (memcmp(&i->multi, imr, sizeof(*imr)) == 0) {
-                       /* New style additions are reference counted */
-                       if (imr->imr_address.s_addr == 0) {
-                               i->count++;
-                               err = 0;
-                       }
+               if (i->multi.imr_multiaddr.s_addr == addr &&
+                   i->multi.imr_ifindex == ifindex)
                        goto done;
-               }
                count++;
        }
        err = -ENOBUFS;
-       if (iml == NULL || count >= sysctl_igmp_max_memberships)
+       if (count >= sysctl_igmp_max_memberships)
+               goto done;
+       iml = (struct ip_mc_socklist *)sock_kmalloc(sk,sizeof(*iml),GFP_KERNEL);
+       if (iml == NULL)
                goto done;
+
        memcpy(&iml->multi, imr, sizeof(*imr));
        iml->next = inet->mc_list;
-       iml->count = 1;
        iml->sflist = NULL;
        iml->sfmode = MCAST_EXCLUDE;
        inet->mc_list = iml;
        ip_mc_inc_group(in_dev, addr);
-       iml = NULL;
        err = 0;
-
 done:
        rtnl_shunlock();
-       if (iml)
-               sock_kfree_s(sk, iml, sizeof(*iml));
        return err;
 }
 
@@ -1693,30 +1687,25 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
 {
        struct inet_sock *inet = inet_sk(sk);
        struct ip_mc_socklist *iml, **imlp;
+       struct in_device *in_dev;
+       u32 group = imr->imr_multiaddr.s_addr;
+       u32 ifindex;
 
        rtnl_lock();
+       in_dev = ip_mc_find_dev(imr);
+       if (!in_dev) {
+               rtnl_unlock();
+               return -ENODEV;
+       }
+       ifindex = imr->imr_ifindex;
        for (imlp = &inet->mc_list; (iml = *imlp) != NULL; imlp = &iml->next) {
-               if (iml->multi.imr_multiaddr.s_addr==imr->imr_multiaddr.s_addr &&
-                   iml->multi.imr_address.s_addr==imr->imr_address.s_addr &&
-                   (!imr->imr_ifindex || iml->multi.imr_ifindex==imr->imr_ifindex)) {
-                       struct in_device *in_dev;
-
-                       in_dev = inetdev_by_index(iml->multi.imr_ifindex);
-                       if (in_dev)
-                               (void) ip_mc_leave_src(sk, iml, in_dev);
-                       if (--iml->count) {
-                               rtnl_unlock();
-                               if (in_dev)
-                                       in_dev_put(in_dev);
-                               return 0;
-                       }
+               if (iml->multi.imr_multiaddr.s_addr == group &&
+                   iml->multi.imr_ifindex == ifindex) {
+                       (void) ip_mc_leave_src(sk, iml, in_dev);
 
                        *imlp = iml->next;
 
-                       if (in_dev) {
-                               ip_mc_dec_group(in_dev, imr->imr_multiaddr.s_addr);
-                               in_dev_put(in_dev);
-                       }
+                       ip_mc_dec_group(in_dev, group);
                        rtnl_unlock();
                        sock_kfree_s(sk, iml, sizeof(*iml));
                        return 0;
@@ -1736,6 +1725,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
        struct in_device *in_dev = NULL;
        struct inet_sock *inet = inet_sk(sk);
        struct ip_sf_socklist *psl;
+       int leavegroup = 0;
        int i, j, rv;
 
        if (!MULTICAST(addr))
@@ -1755,15 +1745,20 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
        err = -EADDRNOTAVAIL;
 
        for (pmc=inet->mc_list; pmc; pmc=pmc->next) {
-               if (memcmp(&pmc->multi, mreqs, 2*sizeof(__u32)) == 0)
+               if (pmc->multi.imr_multiaddr.s_addr == imr.imr_multiaddr.s_addr
+                   && pmc->multi.imr_ifindex == imr.imr_ifindex)
                        break;
        }
-       if (!pmc)               /* must have a prior join */
+       if (!pmc) {             /* must have a prior join */
+               err = -EINVAL;
                goto done;
+       }
        /* if a source filter was set, must be the same mode as before */
        if (pmc->sflist) {
-               if (pmc->sfmode != omode)
+               if (pmc->sfmode != omode) {
+                       err = -EINVAL;
                        goto done;
+               }
        } else if (pmc->sfmode != omode) {
                /* allow mode switches for empty-set filters */
                ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 0, NULL, 0);
@@ -1775,7 +1770,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
        psl = pmc->sflist;
        if (!add) {
                if (!psl)
-                       goto done;
+                       goto done;      /* err = -EADDRNOTAVAIL */
                rv = !0;
                for (i=0; i<psl->sl_count; i++) {
                        rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
@@ -1784,7 +1779,13 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
                                break;
                }
                if (rv)         /* source not found */
+                       goto done;      /* err = -EADDRNOTAVAIL */
+
+               /* special case - (INCLUDE, empty) == LEAVE_GROUP */
+               if (psl->sl_count == 1 && omode == MCAST_INCLUDE) {
+                       leavegroup = 1;
                        goto done;
+               }
 
                /* update the interface filter */
                ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, omode, 1, 
@@ -1842,18 +1843,21 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
                &mreqs->imr_sourceaddr, 1);
 done:
        rtnl_shunlock();
+       if (leavegroup)
+               return ip_mc_leave_group(sk, &imr);
        return err;
 }
 
 int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
 {
-       int err;
+       int err = 0;
        struct ip_mreqn imr;
        u32 addr = msf->imsf_multiaddr;
        struct ip_mc_socklist *pmc;
        struct in_device *in_dev;
        struct inet_sock *inet = inet_sk(sk);
        struct ip_sf_socklist *newpsl, *psl;
+       int leavegroup = 0;
 
        if (!MULTICAST(addr))
                return -EINVAL;
@@ -1872,15 +1876,22 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
                err = -ENODEV;
                goto done;
        }
-       err = -EADDRNOTAVAIL;
+
+       /* special case - (INCLUDE, empty) == LEAVE_GROUP */
+       if (msf->imsf_fmode == MCAST_INCLUDE && msf->imsf_numsrc == 0) {
+               leavegroup = 1;
+               goto done;
+       }
 
        for (pmc=inet->mc_list; pmc; pmc=pmc->next) {
                if (pmc->multi.imr_multiaddr.s_addr == msf->imsf_multiaddr &&
                    pmc->multi.imr_ifindex == imr.imr_ifindex)
                        break;
        }
-       if (!pmc)               /* must have a prior join */
+       if (!pmc) {             /* must have a prior join */
+               err = -EINVAL;
                goto done;
+       }
        if (msf->imsf_numsrc) {
                newpsl = (struct ip_sf_socklist *)sock_kmalloc(sk,
                                IP_SFLSIZE(msf->imsf_numsrc), GFP_KERNEL);
@@ -1909,8 +1920,11 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
                        0, NULL, 0);
        pmc->sflist = newpsl;
        pmc->sfmode = msf->imsf_fmode;
+       err = 0;
 done:
        rtnl_shunlock();
+       if (leavegroup)
+               err = ip_mc_leave_group(sk, &imr);
        return err;
 }
 
index f8b172f89811d2b6fa2d9a762e1a20d47679b36b..fc7c481d0d79378981841ff6989bcaebc0b14f23 100644 (file)
@@ -677,11 +677,11 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
                                mreq.imr_address.s_addr = mreqs.imr_interface;
                                mreq.imr_ifindex = 0;
                                err = ip_mc_join_group(sk, &mreq);
-                               if (err)
+                               if (err && err != -EADDRINUSE)
                                        break;
                                omode = MCAST_INCLUDE;
                                add = 1;
-                       } else /*IP_DROP_SOURCE_MEMBERSHIP */ {
+                       } else /* IP_DROP_SOURCE_MEMBERSHIP */ {
                                omode = MCAST_INCLUDE;
                                add = 0;
                        }
@@ -754,7 +754,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
                                mreq.imr_address.s_addr = 0;
                                mreq.imr_ifindex = greqs.gsr_interface;
                                err = ip_mc_join_group(sk, &mreq);
-                               if (err)
+                               if (err && err != -EADDRINUSE)
                                        break;
                                greqs.gsr_interface = mreq.imr_ifindex;
                                omode = MCAST_INCLUDE;
index 29894c74916336afd45dcd30f43e2ef2b34e3cfc..ddb6ce4ecff291e9ecec53e86a2781eefe61a3bb 100644 (file)
@@ -1105,7 +1105,7 @@ static void tcp_prequeue_process(struct sock *sk)
        struct sk_buff *skb;
        struct tcp_sock *tp = tcp_sk(sk);
 
-       NET_ADD_STATS_USER(LINUX_MIB_TCPPREQUEUED, skb_queue_len(&tp->ucopy.prequeue));
+       NET_INC_STATS_USER(LINUX_MIB_TCPPREQUEUED);
 
        /* RX process wants to run with disabled BHs, though it is not
         * necessary */
@@ -1369,7 +1369,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                         * is not empty. It is more elegant, but eats cycles,
                         * unfortunately.
                         */
-                       if (skb_queue_len(&tp->ucopy.prequeue))
+                       if (!skb_queue_empty(&tp->ucopy.prequeue))
                                goto do_prequeue;
 
                        /* __ Set realtime policy in scheduler __ */
@@ -1394,7 +1394,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                        }
 
                        if (tp->rcv_nxt == tp->copied_seq &&
-                           skb_queue_len(&tp->ucopy.prequeue)) {
+                           !skb_queue_empty(&tp->ucopy.prequeue)) {
 do_prequeue:
                                tcp_prequeue_process(sk);
 
@@ -1476,7 +1476,7 @@ skip_copy:
        } while (len > 0);
 
        if (user_recv) {
-               if (skb_queue_len(&tp->ucopy.prequeue)) {
+               if (!skb_queue_empty(&tp->ucopy.prequeue)) {
                        int chunk;
 
                        tp->ucopy.len = copied > 0 ? len : 0;
index 8de2f1071c2bf5dd161026ff75da87227b1f73ec..53a8a5399f1e6e6de3b13a05d691612c533f433c 100644 (file)
@@ -2802,7 +2802,7 @@ static void tcp_sack_remove(struct tcp_sock *tp)
        int this_sack;
 
        /* Empty ofo queue, hence, all the SACKs are eaten. Clear. */
-       if (skb_queue_len(&tp->out_of_order_queue) == 0) {
+       if (skb_queue_empty(&tp->out_of_order_queue)) {
                tp->rx_opt.num_sacks = 0;
                tp->rx_opt.eff_sacks = tp->rx_opt.dsack;
                return;
@@ -2935,13 +2935,13 @@ queue_and_out:
                if(th->fin)
                        tcp_fin(skb, sk, th);
 
-               if (skb_queue_len(&tp->out_of_order_queue)) {
+               if (!skb_queue_empty(&tp->out_of_order_queue)) {
                        tcp_ofo_queue(sk);
 
                        /* RFC2581. 4.2. SHOULD send immediate ACK, when
                         * gap in queue is filled.
                         */
-                       if (!skb_queue_len(&tp->out_of_order_queue))
+                       if (skb_queue_empty(&tp->out_of_order_queue))
                                tp->ack.pingpong = 0;
                }
 
@@ -3249,9 +3249,8 @@ static int tcp_prune_queue(struct sock *sk)
         * This must not ever occur. */
 
        /* First, purge the out_of_order queue. */
-       if (skb_queue_len(&tp->out_of_order_queue)) {
-               NET_ADD_STATS_BH(LINUX_MIB_OFOPRUNED, 
-                                skb_queue_len(&tp->out_of_order_queue));
+       if (!skb_queue_empty(&tp->out_of_order_queue)) {
+               NET_INC_STATS_BH(LINUX_MIB_OFOPRUNED);
                __skb_queue_purge(&tp->out_of_order_queue);
 
                /* Reset SACK state.  A conforming SACK implementation will
index e041d057ec8607150b6b5c9b4801664c338506aa..e3f8ea1bfa9c01179f93094c534c2ea3f07bcd9f 100644 (file)
@@ -1613,7 +1613,7 @@ void tcp_send_fin(struct sock *sk)
  * was unread data in the receive queue.  This behavior is recommended
  * by draft-ietf-tcpimpl-prob-03.txt section 3.10.  -DaveM
  */
-void tcp_send_active_reset(struct sock *sk, int priority)
+void tcp_send_active_reset(struct sock *sk, unsigned int __nocast priority)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        struct sk_buff *skb;
index b127b4498565f1801444d11abe92cefd6c1c5c54..0084227438c28d26bc2d089b1facc4675310f741 100644 (file)
@@ -231,11 +231,10 @@ static void tcp_delack_timer(unsigned long data)
        }
        tp->ack.pending &= ~TCP_ACK_TIMER;
 
-       if (skb_queue_len(&tp->ucopy.prequeue)) {
+       if (!skb_queue_empty(&tp->ucopy.prequeue)) {
                struct sk_buff *skb;
 
-               NET_ADD_STATS_BH(LINUX_MIB_TCPSCHEDULERFAILED, 
-                                skb_queue_len(&tp->ucopy.prequeue));
+               NET_INC_STATS_BH(LINUX_MIB_TCPSCHEDULERFAILED);
 
                while ((skb = __skb_dequeue(&tp->ucopy.prequeue)) != NULL)
                        sk->sk_backlog_rcv(sk, skb);
index 562fcd14fdeab0acd75afd019d822ee79968ede1..29fed6e58d0aa631c19d55c967d0bb9ff909c5f4 100644 (file)
@@ -281,7 +281,7 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
        }
        write_unlock_bh(&ipv6_sk_mc_lock);
 
-       return -ENOENT;
+       return -EADDRNOTAVAIL;
 }
 
 static struct inet6_dev *ip6_mc_find_dev(struct in6_addr *group, int ifindex)
@@ -386,12 +386,16 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
                if (ipv6_addr_equal(&pmc->addr, group))
                        break;
        }
-       if (!pmc)               /* must have a prior join */
+       if (!pmc) {             /* must have a prior join */
+               err = -EINVAL;
                goto done;
+       }
        /* if a source filter was set, must be the same mode as before */
        if (pmc->sflist) {
-               if (pmc->sfmode != omode)
+               if (pmc->sfmode != omode) {
+                       err = -EINVAL;
                        goto done;
+               }
        } else if (pmc->sfmode != omode) {
                /* allow mode switches for empty-set filters */
                ip6_mc_add_src(idev, group, omode, 0, NULL, 0);
@@ -402,7 +406,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
        psl = pmc->sflist;
        if (!add) {
                if (!psl)
-                       goto done;
+                       goto done;      /* err = -EADDRNOTAVAIL */
                rv = !0;
                for (i=0; i<psl->sl_count; i++) {
                        rv = memcmp(&psl->sl_addr[i], source,
@@ -411,7 +415,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
                                break;
                }
                if (rv)         /* source not found */
-                       goto done;
+                       goto done;      /* err = -EADDRNOTAVAIL */
 
                /* special case - (INCLUDE, empty) == LEAVE_GROUP */
                if (psl->sl_count == 1 && omode == MCAST_INCLUDE) {
@@ -488,6 +492,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
        struct inet6_dev *idev;
        struct ipv6_pinfo *inet6 = inet6_sk(sk);
        struct ip6_sf_socklist *newpsl, *psl;
+       int leavegroup = 0;
        int i, err;
 
        group = &((struct sockaddr_in6 *)&gsf->gf_group)->sin6_addr;
@@ -503,7 +508,12 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
        if (!idev)
                return -ENODEV;
        dev = idev->dev;
-       err = -EADDRNOTAVAIL;
+
+       err = 0;
+       if (gsf->gf_fmode == MCAST_INCLUDE && gsf->gf_numsrc == 0) {
+               leavegroup = 1;
+               goto done;
+       }
 
        for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) {
                if (pmc->ifindex != gsf->gf_interface)
@@ -511,8 +521,10 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
                if (ipv6_addr_equal(&pmc->addr, group))
                        break;
        }
-       if (!pmc)               /* must have a prior join */
+       if (!pmc) {             /* must have a prior join */
+               err = -EINVAL;
                goto done;
+       }
        if (gsf->gf_numsrc) {
                newpsl = (struct ip6_sf_socklist *)sock_kmalloc(sk,
                                IP6_SFLSIZE(gsf->gf_numsrc), GFP_ATOMIC);
@@ -544,10 +556,13 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
                (void) ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0);
        pmc->sflist = newpsl;
        pmc->sfmode = gsf->gf_fmode;
+       err = 0;
 done:
        read_unlock_bh(&idev->lock);
        in6_dev_put(idev);
        dev_put(dev);
+       if (leavegroup)
+               err = ipv6_sock_mc_drop(sk, gsf->gf_interface, group);
        return err;
 }
 
index 046ad0750e48d4282e0501f3e1d22387caa3fa6d..7029618f5719fa6659bd096c7d7a0345b29dff70 100644 (file)
@@ -445,9 +445,8 @@ void irlap_disconnect_request(struct irlap_cb *self)
        IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
 
        /* Don't disconnect until all data frames are successfully sent */
-       if (skb_queue_len(&self->txq) > 0) {
+       if (!skb_queue_empty(&self->txq)) {
                self->disconnect_pending = TRUE;
-
                return;
        }
 
index 1cd89f5f3b759320f6472fb06d83800e871be82f..a505b5457608097238f8da41cdd3b6318e243425 100644 (file)
@@ -191,7 +191,7 @@ static void irlap_start_poll_timer(struct irlap_cb *self, int timeout)
         * Send out the RR frames faster if our own transmit queue is empty, or
         * if the peer is busy. The effect is a much faster conversation
         */
-       if ((skb_queue_len(&self->txq) == 0) || (self->remote_busy)) {
+       if (skb_queue_empty(&self->txq) || self->remote_busy) {
                if (self->fast_RR == TRUE) {
                        /*
                         *  Assert that the fast poll timer has not reached the
@@ -263,7 +263,7 @@ void irlap_do_event(struct irlap_cb *self, IRLAP_EVENT event,
                IRDA_DEBUG(2, "%s() : queue len = %d\n", __FUNCTION__,
                           skb_queue_len(&self->txq));
 
-               if (skb_queue_len(&self->txq)) {
+               if (!skb_queue_empty(&self->txq)) {
                        /* Prevent race conditions with irlap_data_request() */
                        self->local_busy = TRUE;
 
@@ -1074,7 +1074,7 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event,
 #else  /* CONFIG_IRDA_DYNAMIC_WINDOW */
                        /* Window has been adjusted for the max packet
                         * size, so much simpler... - Jean II */
-                       nextfit = (skb_queue_len(&self->txq) > 0);
+                       nextfit = !skb_queue_empty(&self->txq);
 #endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
                        /*
                         *  Send data with poll bit cleared only if window > 1
@@ -1814,7 +1814,7 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event,
 #else  /* CONFIG_IRDA_DYNAMIC_WINDOW */
                        /* Window has been adjusted for the max packet
                         * size, so much simpler... - Jean II */
-                       nextfit = (skb_queue_len(&self->txq) > 0);
+                       nextfit = !skb_queue_empty(&self->txq);
 #endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
                        /*
                         *  Send data with final bit cleared only if window > 1
@@ -1937,7 +1937,7 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event,
                                irlap_data_indication(self, skb, FALSE);
 
                                /* Any pending data requests?  */
-                               if ((skb_queue_len(&self->txq) > 0) &&
+                               if (!skb_queue_empty(&self->txq) &&
                                    (self->window > 0))
                                {
                                        self->ack_required = TRUE;
@@ -2038,7 +2038,7 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event,
                        /*
                         *  Any pending data requests?
                         */
-                       if ((skb_queue_len(&self->txq) > 0) &&
+                       if (!skb_queue_empty(&self->txq) &&
                            (self->window > 0) && !self->remote_busy)
                        {
                                irlap_data_indication(self, skb, TRUE);
@@ -2069,7 +2069,7 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event,
                 */
                nr_status = irlap_validate_nr_received(self, info->nr);
                if (nr_status == NR_EXPECTED) {
-                       if ((skb_queue_len( &self->txq) > 0) &&
+                       if (!skb_queue_empty(&self->txq) &&
                            (self->window > 0)) {
                                self->remote_busy = FALSE;
 
index 040abe714aa35f11161ffb37e88ecebe7c71bef8..6dafbb43b5296922f62cacf8c596d9987d835c0f 100644 (file)
@@ -1018,11 +1018,10 @@ void irlap_resend_rejected_frames(struct irlap_cb *self, int command)
        /*
         *  We can now fill the window with additional data frames
         */
-       while (skb_queue_len( &self->txq) > 0) {
+       while (!skb_queue_empty(&self->txq)) {
 
                IRDA_DEBUG(0, "%s(), sending additional frames!\n", __FUNCTION__);
-               if ((skb_queue_len( &self->txq) > 0) &&
-                   (self->window > 0)) {
+               if (self->window > 0) {
                        skb = skb_dequeue( &self->txq);
                        IRDA_ASSERT(skb != NULL, return;);
 
@@ -1031,8 +1030,7 @@ void irlap_resend_rejected_frames(struct irlap_cb *self, int command)
                         *  bit cleared
                         */
                        if ((self->window > 1) &&
-                           skb_queue_len(&self->txq) > 0)
-                       {
+                           !skb_queue_empty(&self->txq)) {
                                irlap_send_data_primary(self, skb);
                        } else {
                                irlap_send_data_primary_poll(self, skb);
index d091ccf773b3db03abc6bcda3c009b5d6c4f4975..6602d901f8b111ba51e2947f51b4ebaf452d5dbb 100644 (file)
@@ -1513,7 +1513,7 @@ int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
        /*
         *  Check if there is still data segments in the transmit queue
         */
-       if (skb_queue_len(&self->tx_queue) > 0) {
+       if (!skb_queue_empty(&self->tx_queue)) {
                if (priority == P_HIGH) {
                        /*
                         *  No need to send the queued data, if we are
index cd130c3b72bc438063597d2245a5db26e6ec38d6..d5bdb53a348f3002c184f3f0059ebbf183ba3309 100644 (file)
@@ -84,7 +84,7 @@ static u16 llc_util_nr_inside_tx_window(struct sock *sk, u8 nr)
        if (llc->dev->flags & IFF_LOOPBACK)
                goto out;
        rc = 1;
-       if (!skb_queue_len(&llc->pdu_unack_q))
+       if (skb_queue_empty(&llc->pdu_unack_q))
                goto out;
        skb = skb_peek(&llc->pdu_unack_q);
        pdu = llc_pdu_sn_hdr(skb);
index fc456a7aaec39bad1c147a8eff9a9d01e48b722c..3405fdf41b93ab1950f739673614499b06b0ad3f 100644 (file)
@@ -858,7 +858,7 @@ static inline void netlink_rcv_wake(struct sock *sk)
 {
        struct netlink_sock *nlk = nlk_sk(sk);
 
-       if (!skb_queue_len(&sk->sk_receive_queue))
+       if (skb_queue_empty(&sk->sk_receive_queue))
                clear_bit(0, &nlk->state);
        if (!test_bit(0, &nlk->state))
                wake_up_interruptible(&nlk->wait);
index 664d0e47374fd1003ec8f0296aa96afa8ed92c9d..7845d045eec4d1434037eaf0a964f33f70fcb0e9 100644 (file)
@@ -385,7 +385,7 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt)
        memcpy(q->Stab, RTA_DATA(tb[TCA_RED_STAB-1]), 256);
 
        q->qcount = -1;
-       if (skb_queue_len(&sch->q) == 0)
+       if (skb_queue_empty(&sch->q))
                PSCHED_SET_PASTPERFECT(q->qidlestart);
        sch_tree_unlock(sch);
        return 0;
index 7ae6aa772dab76388a70d22e19e74e76b3a215e9..4b47dd6f2485ad3ae0d52bb4803c1a48277a76ad 100644 (file)
@@ -203,7 +203,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
         */
        asoc->addip_serial = asoc->c.initial_tsn;
 
-       skb_queue_head_init(&asoc->addip_chunks);
+       INIT_LIST_HEAD(&asoc->addip_chunk_list);
 
        /* Make an empty list of remote transport addresses.  */
        INIT_LIST_HEAD(&asoc->peer.transport_addr_list);
index 339f7acfdb647b7eca56aa43c2a35e0aa9afb735..5e085e041a6ef1f5528c9eb5fbd85a198f9712b2 100644 (file)
@@ -115,6 +115,17 @@ static void sctp_rcv_set_owner_r(struct sk_buff *skb, struct sock *sk)
        atomic_add(sizeof(struct sctp_chunk),&sk->sk_rmem_alloc);
 }
 
+struct sctp_input_cb {
+       union {
+               struct inet_skb_parm    h4;
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+               struct inet6_skb_parm   h6;
+#endif
+       } header;
+       struct sctp_chunk *chunk;
+};
+#define SCTP_INPUT_CB(__skb)   ((struct sctp_input_cb *)&((__skb)->cb[0]))
+
 /*
  * This is the routine which IP calls when receiving an SCTP packet.
  */
@@ -243,6 +254,7 @@ int sctp_rcv(struct sk_buff *skb)
                ret = -ENOMEM;
                goto discard_release;
        }
+       SCTP_INPUT_CB(skb)->chunk = chunk;
 
        sctp_rcv_set_owner_r(skb,sk);
 
@@ -265,9 +277,9 @@ int sctp_rcv(struct sk_buff *skb)
        sctp_bh_lock_sock(sk);
 
        if (sock_owned_by_user(sk))
-               sk_add_backlog(sk, (struct sk_buff *) chunk);
+               sk_add_backlog(sk, skb);
        else
-               sctp_backlog_rcv(sk, (struct sk_buff *) chunk);
+               sctp_backlog_rcv(sk, skb);
 
        /* Release the sock and any reference counts we took in the
         * lookup calls.
@@ -302,14 +314,8 @@ discard_release:
  */
 int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 {
-       struct sctp_chunk *chunk;
-       struct sctp_inq *inqueue;
-
-       /* One day chunk will live inside the skb, but for
-        * now this works.
-        */
-       chunk = (struct sctp_chunk *) skb;
-       inqueue = &chunk->rcvr->inqueue;
+       struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
+       struct sctp_inq *inqueue = &chunk->rcvr->inqueue;
 
        sctp_inq_push(inqueue, chunk);
         return 0;
index cedf4351556cc0262957f967bc7b7baa86341d48..2d33922c044bb5108075de3fbff111a1207d66c7 100644 (file)
@@ -50,7 +50,7 @@
 /* Initialize an SCTP inqueue.  */
 void sctp_inq_init(struct sctp_inq *queue)
 {
-       skb_queue_head_init(&queue->in);
+       INIT_LIST_HEAD(&queue->in_chunk_list);
        queue->in_progress = NULL;
 
        /* Create a task for delivering data.  */
@@ -62,11 +62,13 @@ void sctp_inq_init(struct sctp_inq *queue)
 /* Release the memory associated with an SCTP inqueue.  */
 void sctp_inq_free(struct sctp_inq *queue)
 {
-       struct sctp_chunk *chunk;
+       struct sctp_chunk *chunk, *tmp;
 
        /* Empty the queue.  */
-       while ((chunk = (struct sctp_chunk *) skb_dequeue(&queue->in)) != NULL)
+       list_for_each_entry_safe(chunk, tmp, &queue->in_chunk_list, list) {
+               list_del_init(&chunk->list);
                sctp_chunk_free(chunk);
+       }
 
        /* If there is a packet which is currently being worked on,
         * free it as well.
@@ -92,7 +94,7 @@ void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *packet)
         * Eventually, we should clean up inqueue to not rely
         * on the BH related data structures.
         */
-       skb_queue_tail(&(q->in), (struct sk_buff *) packet);
+       list_add_tail(&packet->list, &q->in_chunk_list);
        q->immediate.func(q->immediate.data);
 }
 
@@ -131,12 +133,16 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
 
        /* Do we need to take the next packet out of the queue to process? */
        if (!chunk) {
+               struct list_head *entry;
+
                /* Is the queue empty?  */
-               if (skb_queue_empty(&queue->in))
+               if (list_empty(&queue->in_chunk_list))
                        return NULL;
 
+               entry = queue->in_chunk_list.next;
                chunk = queue->in_progress =
-                       (struct sctp_chunk *) skb_dequeue(&queue->in);
+                       list_entry(entry, struct sctp_chunk, list);
+               list_del_init(entry);
 
                /* This is the first chunk in the packet.  */
                chunk->singleton = 1;
index 84b5b370b09d7b0025152062643284160d80e107..9313716334648fa90c7c39c6faaba289cebbe5d7 100644 (file)
@@ -108,7 +108,7 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet,
        packet->transport = transport;
        packet->source_port = sport;
        packet->destination_port = dport;
-       skb_queue_head_init(&packet->chunks);
+       INIT_LIST_HEAD(&packet->chunk_list);
        if (asoc) {
                struct sctp_sock *sp = sctp_sk(asoc->base.sk);  
                overhead = sp->pf->af->net_header_len; 
@@ -129,12 +129,14 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet,
 /* Free a packet.  */
 void sctp_packet_free(struct sctp_packet *packet)
 {
-       struct sctp_chunk *chunk;
+       struct sctp_chunk *chunk, *tmp;
 
        SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet);
 
-        while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks)) != NULL)
+       list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) {
+               list_del_init(&chunk->list);
                sctp_chunk_free(chunk);
+       }
 
        if (packet->malloced)
                kfree(packet);
@@ -276,7 +278,7 @@ append:
                packet->has_sack = 1;
 
        /* It is OK to send this chunk.  */
-       __skb_queue_tail(&packet->chunks, (struct sk_buff *)chunk);
+       list_add_tail(&chunk->list, &packet->chunk_list);
        packet->size += chunk_len;
        chunk->transport = packet->transport;
 finish:
@@ -295,7 +297,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
        struct sctphdr *sh;
        __u32 crc32;
        struct sk_buff *nskb;
-       struct sctp_chunk *chunk;
+       struct sctp_chunk *chunk, *tmp;
        struct sock *sk;
        int err = 0;
        int padding;            /* How much padding do we need?  */
@@ -305,11 +307,11 @@ int sctp_packet_transmit(struct sctp_packet *packet)
        SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet);
 
        /* Do NOT generate a chunkless packet. */
-       chunk = (struct sctp_chunk *)skb_peek(&packet->chunks);
-       if (unlikely(!chunk))
+       if (list_empty(&packet->chunk_list))
                return err;
 
        /* Set up convenience variables... */
+       chunk = list_entry(packet->chunk_list.next, struct sctp_chunk, list);
        sk = chunk->skb->sk;
 
        /* Allocate the new skb.  */
@@ -370,7 +372,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
         * [This whole comment explains WORD_ROUND() below.]
         */
        SCTP_DEBUG_PRINTK("***sctp_transmit_packet***\n");
-       while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks)) != NULL) {
+       list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) {
+               list_del_init(&chunk->list);
                if (sctp_chunk_is_data(chunk)) {
 
                        if (!chunk->has_tsn) {
@@ -511,7 +514,8 @@ err:
         * will get resent or dropped later.
         */
 
-       while ((chunk = (struct sctp_chunk *)__skb_dequeue(&packet->chunks)) != NULL) {
+       list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) {
+               list_del_init(&chunk->list);
                if (!sctp_chunk_is_data(chunk))
                        sctp_chunk_free(chunk);
        }
index 4eb81a1407b7e027c7da1302a8af43705be3015a..efb72faba20cd50aec065d4fe498c85ecae8d4ae 100644 (file)
@@ -75,7 +75,7 @@ static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 sack_ctsn);
 static inline void sctp_outq_head_data(struct sctp_outq *q,
                                        struct sctp_chunk *ch)
 {
-       __skb_queue_head(&q->out, (struct sk_buff *)ch);
+       list_add(&ch->list, &q->out_chunk_list);
        q->out_qlen += ch->skb->len;
        return;
 }
@@ -83,17 +83,22 @@ static inline void sctp_outq_head_data(struct sctp_outq *q,
 /* Take data from the front of the queue. */
 static inline struct sctp_chunk *sctp_outq_dequeue_data(struct sctp_outq *q)
 {
-       struct sctp_chunk *ch;
-       ch = (struct sctp_chunk *)__skb_dequeue(&q->out);
-       if (ch)
+       struct sctp_chunk *ch = NULL;
+
+       if (!list_empty(&q->out_chunk_list)) {
+               struct list_head *entry = q->out_chunk_list.next;
+
+               ch = list_entry(entry, struct sctp_chunk, list);
+               list_del_init(entry);
                q->out_qlen -= ch->skb->len;
+       }
        return ch;
 }
 /* Add data chunk to the end of the queue. */
 static inline void sctp_outq_tail_data(struct sctp_outq *q,
                                       struct sctp_chunk *ch)
 {
-       __skb_queue_tail(&q->out, (struct sk_buff *)ch);
+       list_add_tail(&ch->list, &q->out_chunk_list);
        q->out_qlen += ch->skb->len;
        return;
 }
@@ -197,8 +202,8 @@ static inline int sctp_cacc_skip(struct sctp_transport *primary,
 void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
 {
        q->asoc = asoc;
-       skb_queue_head_init(&q->out);
-       skb_queue_head_init(&q->control);
+       INIT_LIST_HEAD(&q->out_chunk_list);
+       INIT_LIST_HEAD(&q->control_chunk_list);
        INIT_LIST_HEAD(&q->retransmit);
        INIT_LIST_HEAD(&q->sacked);
        INIT_LIST_HEAD(&q->abandoned);
@@ -217,7 +222,7 @@ void sctp_outq_teardown(struct sctp_outq *q)
 {
        struct sctp_transport *transport;
        struct list_head *lchunk, *pos, *temp;
-       struct sctp_chunk *chunk;
+       struct sctp_chunk *chunk, *tmp;
 
        /* Throw away unacknowledged chunks. */
        list_for_each(pos, &q->asoc->peer.transport_addr_list) {
@@ -269,8 +274,10 @@ void sctp_outq_teardown(struct sctp_outq *q)
        q->error = 0;
 
        /* Throw away any leftover control chunks. */
-       while ((chunk = (struct sctp_chunk *) skb_dequeue(&q->control)) != NULL)
+       list_for_each_entry_safe(chunk, tmp, &q->control_chunk_list, list) {
+               list_del_init(&chunk->list);
                sctp_chunk_free(chunk);
+       }
 }
 
 /* Free the outqueue structure and any related pending chunks.  */
@@ -333,7 +340,7 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
                        break;
                };
        } else {
-               __skb_queue_tail(&q->control, (struct sk_buff *) chunk);
+               list_add_tail(&chunk->list, &q->control_chunk_list);
                SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
        }
 
@@ -650,10 +657,9 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
        __u16 sport = asoc->base.bind_addr.port;
        __u16 dport = asoc->peer.port;
        __u32 vtag = asoc->peer.i.init_tag;
-       struct sk_buff_head *queue;
        struct sctp_transport *transport = NULL;
        struct sctp_transport *new_transport;
-       struct sctp_chunk *chunk;
+       struct sctp_chunk *chunk, *tmp;
        sctp_xmit_t status;
        int error = 0;
        int start_timer = 0;
@@ -675,8 +681,9 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
         *   ...
         */
 
-       queue = &q->control;
-       while ((chunk = (struct sctp_chunk *)skb_dequeue(queue)) != NULL) {
+       list_for_each_entry_safe(chunk, tmp, &q->control_chunk_list, list) {
+               list_del_init(&chunk->list);
+
                /* Pick the right transport to use. */
                new_transport = chunk->transport;
 
@@ -814,8 +821,6 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
 
                /* Finally, transmit new packets.  */
                start_timer = 0;
-               queue = &q->out;
-
                while ((chunk = sctp_outq_dequeue_data(q)) != NULL) {
                        /* RFC 2960 6.5 Every DATA chunk MUST carry a valid
                         * stream identifier.
@@ -1149,8 +1154,9 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
        /* See if all chunks are acked.
         * Make sure the empty queue handler will get run later.
         */
-       q->empty = skb_queue_empty(&q->out) && skb_queue_empty(&q->control) &&
-                       list_empty(&q->retransmit);
+       q->empty = (list_empty(&q->out_chunk_list) &&
+                   list_empty(&q->control_chunk_list) &&
+                   list_empty(&q->retransmit));
        if (!q->empty)
                goto finish;
 
@@ -1679,9 +1685,9 @@ static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn)
                if (TSN_lte(tsn, ctsn)) {
                        list_del_init(lchunk);
                        if (!chunk->tsn_gap_acked) {
-                       chunk->transport->flight_size -=
-                                                sctp_data_size(chunk);
-                       q->outstanding_bytes -= sctp_data_size(chunk);
+                               chunk->transport->flight_size -=
+                                       sctp_data_size(chunk);
+                               q->outstanding_bytes -= sctp_data_size(chunk);
                        }
                        sctp_chunk_free(chunk);
                } else {
@@ -1729,7 +1735,7 @@ static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn)
                                              nskips, &ftsn_skip_arr[0]); 
 
        if (ftsn_chunk) {
-               __skb_queue_tail(&q->control, (struct sk_buff *)ftsn_chunk);
+               list_add_tail(&ftsn_chunk->list, &q->control_chunk_list);
                SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
        }
 }
index 5baed9bb7de51a64c7cfede056ac0ccdf5ede850..773cd93fa3d03a0f342ca3644e897e3162eb4f18 100644 (file)
@@ -1003,6 +1003,7 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb,
                SCTP_DEBUG_PRINTK("chunkifying skb %p w/o an sk\n", skb);
        }
 
+       INIT_LIST_HEAD(&retval->list);
        retval->skb             = skb;
        retval->asoc            = (struct sctp_association *)asoc;
        retval->resent          = 0;
@@ -1116,8 +1117,7 @@ static void sctp_chunk_destroy(struct sctp_chunk *chunk)
 /* Possibly, free the chunk.  */
 void sctp_chunk_free(struct sctp_chunk *chunk)
 {
-       /* Make sure that we are not on any list.  */
-       skb_unlink((struct sk_buff *) chunk);
+       BUG_ON(!list_empty(&chunk->list));
        list_del_init(&chunk->transmitted_list);
 
        /* Release our reference on the message tracker. */
@@ -2739,8 +2739,12 @@ int sctp_process_asconf_ack(struct sctp_association *asoc,
        asoc->addip_last_asconf = NULL;
 
        /* Send the next asconf chunk from the addip chunk queue. */
-       asconf = (struct sctp_chunk *)__skb_dequeue(&asoc->addip_chunks);
-       if (asconf) {
+       if (!list_empty(&asoc->addip_chunk_list)) {
+               struct list_head *entry = asoc->addip_chunk_list.next;
+               asconf = list_entry(entry, struct sctp_chunk, list);
+
+               list_del_init(entry);
+
                /* Hold the chunk until an ASCONF_ACK is received. */
                sctp_chunk_hold(asconf);
                if (sctp_primitive_ASCONF(asoc, asconf))
index aad55dc3792b39b1195e8cc3a0db7ea0176187ec..091a66f06a35a7518f9f1d2ab8143d0631b6efec 100644 (file)
@@ -406,7 +406,7 @@ static int sctp_send_asconf(struct sctp_association *asoc,
         * transmission.
         */     
        if (asoc->addip_last_asconf) {
-               __skb_queue_tail(&asoc->addip_chunks, (struct sk_buff *)chunk);
+               list_add_tail(&chunk->list, &asoc->addip_chunk_list);
                goto out;       
        }
 
index 269f217918a3c736087a4577aa5389ed38c5410b..3c654e06b08455477185df8b20f48f8bc4928f12 100644 (file)
@@ -145,8 +145,6 @@ __xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
        if (test_and_set_bit(XPRT_LOCKED, &xprt->sockstate)) {
                if (task == xprt->snd_task)
                        return 1;
-               if (task == NULL)
-                       return 0;
                goto out_sleep;
        }
        if (xprt->nocong || __xprt_get_cong(xprt, task)) {
index c420eba4876b50fd853b816c78f04e5c5f127674..d403e34088ad75c1c12ee5fbba7bf8d90e233cfc 100644 (file)
@@ -302,7 +302,7 @@ static void unix_write_space(struct sock *sk)
  * may receive messages only from that peer. */
 static void unix_dgram_disconnected(struct sock *sk, struct sock *other)
 {
-       if (skb_queue_len(&sk->sk_receive_queue)) {
+       if (!skb_queue_empty(&sk->sk_receive_queue)) {
                skb_queue_purge(&sk->sk_receive_queue);
                wake_up_interruptible_all(&unix_sk(sk)->peer_wait);
 
@@ -1619,7 +1619,7 @@ static long unix_stream_data_wait(struct sock * sk, long timeo)
        for (;;) {
                prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
 
-               if (skb_queue_len(&sk->sk_receive_queue) ||
+               if (!skb_queue_empty(&sk->sk_receive_queue) ||
                    sk->sk_err ||
                    (sk->sk_shutdown & RCV_SHUTDOWN) ||
                    signal_pending(current) ||
index 90a551e4da662209b411d1b90f8a5094b8f34d40..a1f6bac647a1c3a673bfbb2b4b03d0556cc9be88 100644 (file)
@@ -129,7 +129,7 @@ static int keyring_duplicate(struct key *keyring, const struct key *source)
        int loop, ret;
 
        const unsigned limit =
-               (PAGE_SIZE - sizeof(*klist)) / sizeof(struct key);
+               (PAGE_SIZE - sizeof(*klist)) / sizeof(struct key *);
 
        ret = 0;
 
@@ -150,7 +150,7 @@ static int keyring_duplicate(struct key *keyring, const struct key *source)
                        max = limit;
 
                ret = -ENOMEM;
-               size = sizeof(*klist) + sizeof(struct key) * max;
+               size = sizeof(*klist) + sizeof(struct key *) * max;
                klist = kmalloc(size, GFP_KERNEL);
                if (!klist)
                        goto error;
@@ -163,7 +163,7 @@ static int keyring_duplicate(struct key *keyring, const struct key *source)
                klist->nkeys = sklist->nkeys;
                memcpy(klist->keys,
                       sklist->keys,
-                      sklist->nkeys * sizeof(struct key));
+                      sklist->nkeys * sizeof(struct key *));
 
                for (loop = klist->nkeys - 1; loop >= 0; loop--)
                        atomic_inc(&klist->keys[loop]->usage);
@@ -783,7 +783,7 @@ int __key_link(struct key *keyring, struct key *key)
                ret = -ENFILE;
                if (max > 65535)
                        goto error3;
-               size = sizeof(*klist) + sizeof(*key) * max;
+               size = sizeof(*klist) + sizeof(struct key *) * max;
                if (size > PAGE_SIZE)
                        goto error3;
 
@@ -895,7 +895,8 @@ int key_unlink(struct key *keyring, struct key *key)
 
 key_is_present:
        /* we need to copy the key list for RCU purposes */
-       nklist = kmalloc(sizeof(*klist) + sizeof(*key) * klist->maxkeys,
+       nklist = kmalloc(sizeof(*klist) +
+                        sizeof(struct key *) * klist->maxkeys,
                         GFP_KERNEL);
        if (!nklist)
                goto nomem;
@@ -905,12 +906,12 @@ key_is_present:
        if (loop > 0)
                memcpy(&nklist->keys[0],
                       &klist->keys[0],
-                      loop * sizeof(klist->keys[0]));
+                      loop * sizeof(struct key *));
 
        if (loop < nklist->nkeys)
                memcpy(&nklist->keys[loop],
                       &klist->keys[loop + 1],
-                      (nklist->nkeys - loop) * sizeof(klist->keys[0]));
+                      (nklist->nkeys - loop) * sizeof(struct key *));
 
        /* adjust the user's quota */
        key_payload_reserve(keyring,
index 9e42a1a67ca469d2c9f319bb076b2dbd2401b3ea..cb998e8c0fdd51f844fd30ada385adda9587af8c 100644 (file)
@@ -4174,7 +4174,7 @@ static int cs_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int
                                list_for_each(entry, &cs46xx_devs)
                                {
                                        card = list_entry(entry, struct cs_card, list);
-                                       cs46xx_suspend(card, 0);
+                                       cs46xx_suspend(card, PMSG_ON);
                                }
 
                        }
@@ -5749,7 +5749,7 @@ static int cs46xx_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
                        case PM_SUSPEND:
                                CS_DBGOUT(CS_PM, 2, printk(KERN_INFO
                                        "cs46xx: PM suspend request\n"));
-                               if(cs46xx_suspend(card, 0))
+                               if(cs46xx_suspend(card, PMSG_SUSPEND))
                                {
                                    CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO
                                        "cs46xx: PM suspend request refused\n"));
@@ -5779,7 +5779,7 @@ static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state)
        struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev);
        CS_DBGOUT(CS_PM | CS_FUNCTION, 2, 
                printk(KERN_INFO "cs46xx: cs46xx_suspend_tbl request\n"));
-       cs46xx_suspend(s, 0);
+       cs46xx_suspend(s, state);
        return 0;
 }
 
index 2d4f8e28478b037183ef34db38b49ce3d5e22571..d6918b453f28dfe685db56a6992c920353910489 100644 (file)
@@ -22,7 +22,6 @@
 #include <sound/core.h>
 #include <linux/slab.h>
 #include <linux/moduleparam.h>
-#include <pcmcia/version.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/cisreg.h>
 #include "pdaudiocf.h"
@@ -171,14 +170,6 @@ static dev_link_t *snd_pdacf_attach(void)
 
        /* Register with Card Services */
        client_reg.dev_info = &dev_info;
-       client_reg.EventMask = 
-               CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL
-#ifdef CONFIG_PM
-               | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET
-               | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME
-#endif
-               ;
-       client_reg.event_handler = &pdacf_event;
        client_reg.Version = 0x0210;
        client_reg.event_callback_args.client_data = link;
 
@@ -387,12 +378,13 @@ static struct pcmcia_device_id snd_pdacf_ids[] = {
 MODULE_DEVICE_TABLE(pcmcia, snd_pdacf_ids);
 
 static struct pcmcia_driver pdacf_cs_driver = {
-       .owner          = THIS_MODULE,
-       .drv            = {
-               .name   = "snd-pdaudiocf",
+       .owner          = THIS_MODULE,
+       .drv            = {
+               .name   = "snd-pdaudiocf",
        },
-       .attach         = snd_pdacf_attach,
-       .detach         = snd_pdacf_detach,
+       .attach         = snd_pdacf_attach,
+       .event          = pdacf_event,
+       .detach         = snd_pdacf_detach,
        .id_table       = snd_pdacf_ids,
 };
 
index 332bbca3dfc4ff0459ca7b57526204c90e4a268c..df7a39ba9680829b3ff1ddd4ac74b600dee5b676 100644 (file)
@@ -35,7 +35,6 @@ MODULE_LICENSE("GPL");
  * prototypes
  */
 static void vxpocket_config(dev_link_t *link);
-static int vxpocket_event(event_t event, int priority, event_callback_args_t *args);
 
 
 static void vxpocket_release(dev_link_t *link)
@@ -169,14 +168,6 @@ dev_link_t *snd_vxpocket_attach(struct snd_vxp_entry *hw)
        /* Register with Card Services */
        memset(&client_reg, 0, sizeof(client_reg));
        client_reg.dev_info = hw->dev_info;
-       client_reg.EventMask = 
-               CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL
-#ifdef CONFIG_PM
-               | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET
-               | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME
-#endif
-               ;
-       client_reg.event_handler = &vxpocket_event;
        client_reg.Version = 0x0210;
        client_reg.event_callback_args.client_data = link;
 
@@ -321,7 +312,7 @@ failed:
 /*
  * event callback
  */
-static int vxpocket_event(event_t event, int priority, event_callback_args_t *args)
+int vxpocket_event(event_t event, int priority, event_callback_args_t *args)
 {
        dev_link_t *link = args->client_data;
        vx_core_t *chip = link->priv;
@@ -380,4 +371,5 @@ static int vxpocket_event(event_t event, int priority, event_callback_args_t *ar
  */
 EXPORT_SYMBOL(snd_vxpocket_ops);
 EXPORT_SYMBOL(snd_vxpocket_attach);
+EXPORT_SYMBOL(vxpocket_event);
 EXPORT_SYMBOL(snd_vxpocket_detach);
index 5f4c1326415912018ce590b5f0c6ba9e5f339c98..62d6fa1281487c335320b88a8582022f44e56a35 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/init.h>
 #include <linux/moduleparam.h>
 #include <sound/core.h>
-#include <pcmcia/version.h>
 #include "vxpocket.h"
 #include <sound/initval.h>
 
This page took 1.731985 seconds and 5 git commands to generate.