linux-cvs-patches
[Top] [All Lists]

CVS Update@linux-mips.org: linux

To: linux-cvs-patches@linux-mips.org
Subject: CVS Update@linux-mips.org: linux
From: ralf@linux-mips.org
Date: Thu, 26 May 2005 10:12:55 +0100
Reply-to: linux-mips@linux-mips.org
Sender: linux-cvs-patches-bounce@linux-mips.org
CVSROOT:        /home/cvs
Module name:    linux
Changes by:     ralf@ftp.linux-mips.org 05/05/26 10:12:50

Modified files:
        .              : CREDITS Makefile 
        Documentation  : cpusets.txt feature-removal-schedule.txt 
        Documentation/dvb: bt8xx.txt get_dvb_firmware 
        Documentation/filesystems: sysfs-pci.txt 
        Documentation/power: devices.txt 
        Documentation/powerpc: hvcs.txt 
        Documentation/x86_64: boot-options.txt 
        arch/alpha/kernel: osf_sys.c 
        arch/arm/mach-s3c2410: clock.c s3c2440.c 
        arch/arm/mm    : Kconfig copypage-v6.c flush.c mm-armv.c 
        arch/i386/kernel: smpboot.c 
        arch/i386/kernel/cpu: amd.c common.c 
        arch/i386/mach-voyager: voyager_smp.c 
        arch/i386/mm   : ioremap.c 
        arch/i386/pci  : fixup.c 
        arch/ia64/ia32 : ia32_ioctl.c 
        arch/mips      : defconfig 
        arch/mips/configs: atlas_defconfig capcella_defconfig 
                           cobalt_defconfig db1000_defconfig 
                           db1100_defconfig db1500_defconfig 
                           db1550_defconfig ddb5476_defconfig 
                           ddb5477_defconfig decstation_defconfig 
                           e55_defconfig ev64120_defconfig 
                           ev96100_defconfig ip22_defconfig 
                           ip27_defconfig ip32_defconfig 
                           it8172_defconfig ivr_defconfig 
                           jaguar-atx_defconfig jmr3927_defconfig 
                           lasat200_defconfig malta_defconfig 
                           mpc30x_defconfig ocelot_3_defconfig 
                           ocelot_c_defconfig ocelot_defconfig 
                           ocelot_g_defconfig osprey_defconfig 
                           pb1100_defconfig pb1500_defconfig 
                           pb1550_defconfig rm200_defconfig 
                           sb1250-swarm_defconfig sead_defconfig 
                           tb0226_defconfig tb0229_defconfig 
                           workpad_defconfig yosemite_defconfig 
        arch/ppc/kernel: head_44x.S setup.c 
        arch/ppc/lib   : string.S 
        arch/ppc/mm    : init.c 
        arch/ppc/syslib: ipic.c mpc83xx_devices.c mpc85xx_devices.c 
                         open_pic.c 
        arch/ppc64/kernel: pmac_smp.c prom_init.c 
        arch/sparc64/kernel: pci_iommu.c sbus.c 
        arch/um        : Kconfig_x86_64 
        arch/um/drivers: chan_kern.c mcast_kern.c mcast_user.c 
                         ubd_kern.c 
        arch/um/include/sysdep-i386: ptrace.h 
        arch/um/include/sysdep-x86_64: checksum.h ptrace.h 
        arch/um/kernel : Makefile irq_user.c ksyms.c mem.c ptrace.c 
                         trap_kern.c uml.lds.S 
        arch/um/kernel/tt: ksyms.c 
        arch/um/sys-i386: Makefile delay.c 
        arch/um/sys-x86_64: Makefile delay.c ksyms.c ptrace.c syscalls.c 
                            user-offsets.c 
        arch/x86_64    : Kconfig defconfig 
        arch/x86_64/kernel: Makefile apic.c entry.S io_apic.c mpparse.c 
                            nmi.c ptrace.c setup.c signal.c smpboot.c 
                            time.c vsyscall.c 
        arch/x86_64/mm : fault.c ioremap.c 
        crypto         : crypto_null.c internal.h 
        drivers/base   : Makefile bus.c core.c 
        drivers/base/power: power.h resume.c shutdown.c suspend.c 
        drivers/block  : ioctl.c pktcdvd.c 
        drivers/char   : raw.c 
        drivers/char/ipmi: ipmi_devintf.c 
        drivers/char/watchdog: i8xx_tco.c 
        drivers/i2c/busses: i2c-keywest.c 
        drivers/ide    : ide-proc.c 
        drivers/ieee1394: Kconfig ieee1394_core.c 
                          ieee1394_transactions.c 
                          ieee1394_transactions.h nodemgr.c ohci1394.c 
                          ohci1394.h pcilynx.c pcilynx.h video1394.c 
        drivers/input/keyboard: atkbd.c 
        drivers/input/mouse: alps.c 
        drivers/input/serio: serio.c serport.c 
        drivers/md     : linear.c multipath.c raid1.c raid10.c raid5.c 
                         raid6main.c 
        drivers/media/common: saa7146_core.c 
        drivers/media/dvb: Kconfig 
        drivers/media/dvb/b2c2: Kconfig Makefile skystar2.c 
        drivers/media/dvb/bt8xx: Kconfig Makefile bt878.c bt878.h dst.c 
                                 dst_priv.h dvb-bt8xx.c dvb-bt8xx.h 
        drivers/media/dvb/cinergyT2: cinergyT2.c 
        drivers/media/dvb/dibusb: dvb-dibusb-dvb.c dvb-dibusb-fe-i2c.c 
                                  dvb-dibusb.h 
        drivers/media/dvb/dvb-core: dmxdev.c dvb_ca_en50221.c 
                                    dvb_frontend.c dvb_net.c dvbdev.c 
                                    dvbdev.h 
        drivers/media/dvb/frontends: Kconfig at76c651.c cx22700.c 
                                     cx22702.c cx24110.c dib3000mb.c 
                                     dib3000mc.c dvb-pll.h 
                                     dvb_dummy_fe.c l64781.c mt312.c 
                                     mt352.c mt352.h nxt2002.c nxt6000.c 
                                     nxt6000_priv.h or51132.c sp8870.c 
                                     sp887x.c stv0297.c stv0299.c 
                                     tda10021.c tda1004x.c tda1004x.h 
                                     tda8083.c tda80xx.c ves1820.c 
                                     ves1x93.c 
        drivers/media/dvb/ttpci: av7110.c av7110.h av7110_av.c 
                                 av7110_ca.c av7110_hw.c av7110_hw.h 
                                 av7110_ir.c av7110_v4l.c budget-av.c 
                                 budget-ci.c budget-core.c 
                                 budget-patch.c budget.c budget.h 
        drivers/media/dvb/ttusb-budget: dvb-ttusb-budget.c 
        drivers/media/dvb/ttusb-dec: ttusb_dec.c 
        drivers/media/video: Kconfig bttv-cards.c video-buf-dvb.c 
        drivers/media/video/saa7134: saa6752hs.c 
        drivers/mmc    : Kconfig mmc_block.c wbsd.c wbsd.h 
        drivers/net    : Makefile tg3.c tg3.h 
        drivers/net/ibm_emac: ibm_emac_core.c 
        drivers/net/tulip: tulip_core.c 
        drivers/net/wireless: Kconfig 
        drivers/pci    : hotplug.c pci-sysfs.c pci.h 
        drivers/pci/hotplug: cpci_hotplug.h cpci_hotplug_core.c 
                             cpci_hotplug_pci.c pciehp.h pciehp_core.c 
                             pciehp_hpc.c shpchp_core.c shpchp_ctrl.c 
        drivers/pci/pcie: portdrv_bus.c 
        drivers/pcmcia : ds.c 
        drivers/s390/block: dasd.c 
        drivers/sbus/char: aurora.c 
        drivers/scsi   : libata-core.c libata-scsi.c sata_svw.c 
                         scsi_transport_spi.c 
        drivers/scsi/aic7xxx: aic7770_osm.c aic7xxx_osm.c aic7xxx_osm.h 
                              aic7xxx_osm_pci.c aic7xxx_proc.c aiclib.c 
        drivers/serial : 21285.c 8250.c amba-pl010.c amba-pl011.c 
                         clps711x.c pxa.c s3c2410.c sa1100.c serial_cs.c 
                         serial_lh7a40x.c serial_txx9.c sunsab.c 
                         sunsab.h 
        drivers/usb/core: sysfs.c 
        drivers/usb/host: ehci-hub.c 
        drivers/usb/net: Kconfig usbnet.c 
        drivers/usb/serial: cypress_m8.c cypress_m8.h 
        fs             : binfmt_elf.c buffer.c namei.c 
        fs/ext3        : super.c 
        fs/proc        : mmu.c 
        fs/reiserfs    : stree.c super.c 
        include/asm-arm: page.h 
        include/asm-arm/arch-imx: imx-regs.h 
        include/asm-arm/arch-s3c2410: regs-nand.h 
        include/asm-um : elf-i386.h elf-x86_64.h 
        include/asm-x86_64: apicdef.h io_apic.h nmi.h processor.h 
                            proto.h vsyscall.h 
        include/linux  : device.h err.h if_tr.h libata.h net.h 
                         netdevice.h pci_ids.h serial_core.h spinlock.h 
                         vmalloc.h wait.h 
        include/linux/mmc: protocol.h 
        include/media  : video-buf-dvb.h 
        include/net    : act_generic.h 
        include/scsi   : scsi_transport_spi.h 
        kernel         : printk.c profile.c sched.c signal.c spinlock.c 
        kernel/irq     : handle.c 
        kernel/power   : main.c 
        mm             : filemap.c memory.c mmap.c mremap.c nommu.c 
                         rmap.c swapfile.c vmalloc.c 
        net/ipv4       : ip_output.c tcp_input.c 
        net/ipv4/ipvs  : ip_vs_xmit.c 
        net/ipv4/netfilter: ip_conntrack_core.c 
        net/ipv6       : ip6_output.c xfrm6_output.c 
        net/netlink    : af_netlink.c 
        net/unix       : af_unix.c 
        net/xfrm       : xfrm_algo.c xfrm_user.c 
        security/selinux/ss: services.c 
Added files:
        Documentation/dvb: README.flexcop ci.txt 
        arch/arm/mm    : copypage-v4mc.c 
        arch/um/kernel : initrd.c 
        arch/x86_64/kernel: pmtimer.c 
        drivers/media/dvb/b2c2: flexcop-common.h flexcop-dma.c 
                                flexcop-eeprom.c flexcop-fe-tuner.c 
                                flexcop-hw-filter.c flexcop-i2c.c 
                                flexcop-misc.c flexcop-pci.c 
                                flexcop-reg.h flexcop-sram.c 
                                flexcop-usb.c flexcop-usb.h flexcop.c 
                                flexcop.h 
        drivers/media/dvb/bt8xx: dst_ca.c dst_ca.h dst_common.h 
Removed files:
        arch/arm/mm    : copypage-v4mc.S 
        drivers/base   : interface.c 
        drivers/media/dvb/b2c2: b2c2-common.c b2c2-usb-core.c 
        drivers/media/dvb/bt8xx: dst.h 
        include/asm-ia64: ioctl32.h 
        include/asm-x86_64: ioctl32.h 

Log message:
        Merge with Linux 2.6.12-rc5.

diff -urN linux/CREDITS linux/CREDITS
--- linux/CREDITS       2005/05/19 12:08:04     1.143
+++ linux/CREDITS       2005/05/26 09:12:35     1.144
@@ -882,13 +882,12 @@
 S: USA
 
 N: Randy Dunlap
-E: rddunlap@osdl.org
+E: rdunlap@xenotime.net
 W: http://www.xenotime.net/linux/linux.html
 W: http://www.linux-usb.org
 D: Linux-USB subsystem, USB core/UHCI/printer/storage drivers
 D: x86 SMP, ACPI, bootflag hacking
-S: 12725 SW Millikan Way, Suite 400
-S: Beaverton, Oregon 97005
+S: (ask for current address)
 S: USA
 
 N: Bob Dunlop
diff -urN linux/Makefile linux/Makefile
--- linux/Makefile      2005/05/19 12:08:04     1.251
+++ linux/Makefile      2005/05/26 09:12:35     1.252
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 12
-EXTRAVERSION =-rc4
+EXTRAVERSION =-rc5
 NAME=Woozy Numbat
 
 # *DOCUMENTATION*
@@ -528,7 +528,7 @@
 include $(srctree)/arch/$(ARCH)/Makefile
 
 # arch Makefile may override CC so keep this after arch Makefile is included
-NOSTDINC_FLAGS := -nostdinc -isystem $(shell $(CC) -print-file-name=include)
+NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
 CHECKFLAGS     += $(NOSTDINC_FLAGS)
 
 # warn about C99 declaration after statement
diff -urN linux/Documentation/cpusets.txt linux/Documentation/cpusets.txt
--- linux/Documentation/cpusets.txt     2005/04/08 18:57:46     1.2
+++ linux/Documentation/cpusets.txt     2005/05/26 09:12:36     1.3
@@ -252,8 +252,7 @@
 There is an exception to the above.  If hotplug funtionality is used
 to remove all the CPUs that are currently assigned to a cpuset,
 then the kernel will automatically update the cpus_allowed of all
-tasks attached to CPUs in that cpuset with the online CPUs of the
-nearest parent cpuset that still has some CPUs online.  When memory
+tasks attached to CPUs in that cpuset to allow all CPUs.  When memory
 hotplug functionality for removing Memory Nodes is available, a
 similar exception is expected to apply there as well.  In general,
 the kernel prefers to violate cpuset placement, over starving a task
diff -urN linux/Documentation/feature-removal-schedule.txt 
linux/Documentation/feature-removal-schedule.txt
--- linux/Documentation/feature-removal-schedule.txt    2005/05/19 12:08:05     
1.6
+++ linux/Documentation/feature-removal-schedule.txt    2005/05/26 09:12:36     
1.7
@@ -63,3 +63,23 @@
        people, who might be using implementations that I am not aware
        of, to adjust to this upcoming change.
 Who:   Paul E. McKenney <paulmck@us.ibm.com>
+
+---------------------------
+
+What:  IEEE1394 Audio and Music Data Transmission Protocol driver,
+       Connection Management Procedures driver
+When:  November 2005
+Files: drivers/ieee1394/{amdtp,cmp}*
+Why:   These are incomplete, have never worked, and are better implemented
+       in userland via raw1394 (see http://freebob.sourceforge.net/ for
+       example.)
+Who:   Jody McIntyre <scjody@steamballoon.com>
+
+---------------------------
+
+What:  raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN
+When:  November 2005
+Why:   Deprecated in favour of the new ioctl-based rawiso interface, which is
+       more efficient.  You should really be using libraw1394 for raw1394
+       access anyway.
+Who:   Jody McIntyre <scjody@steamballoon.com>
diff -urN linux/Documentation/dvb/README.flexcop 
linux/Documentation/dvb/README.flexcop
--- linux/Documentation/dvb/README.flexcop      1970/01/01 00:00:00
+++ linux/Documentation/dvb/README.flexcop      2005-05-26 10:12:36.298881000 
+0100     1.1
@@ -0,0 +1,205 @@
+This README escorted the skystar2-driver rewriting procedure. It describes the
+state of the new flexcop-driver set and some internals are written down here
+too.
+
+This document hopefully describes things about the flexcop and its
+device-offsprings. Goal was to write an easy-to-write and easy-to-read set of
+drivers based on the skystar2.c and other information.
+
+Remark: flexcop-pci.c was a copy of skystar2.c, but every line has been
+touched and rewritten.
+
+History & News
+==============
+  2005-04-01 - correct USB ISOC transfers (thanks to Vadim Catana)
+
+
+
+
+General coding processing
+=========================
+
+We should proceed as follows (as long as no one complains):
+
+0) Think before start writing code!
+
+1) rewriting the skystar2.c with the help of the flexcop register descriptions
+and splitting up the files to a pci-bus-part and a flexcop-part.
+The new driver will be called b2c2-flexcop-pci.ko/b2c2-flexcop-usb.ko for the
+device-specific part and b2c2-flexcop.ko for the common flexcop-functions.
+
+2) Search for errors in the leftover of flexcop-pci.c (compare with pluto2.c
+and other pci drivers)
+
+3) make some beautification (see 'Improvements when rewriting (refactoring) is
+done')
+
+4) Testing the new driver and maybe substitute the skystar2.c with it, to reach
+a wider tester audience.
+
+5) creating an usb-bus-part using the already written flexcop code for the pci
+card.
+
+Idea: create a kernel-object for the flexcop and export all important
+functions. This option saves kernel-memory, but maybe a lot of functions have
+to be exported to kernel namespace.
+
+
+Current situation
+=================
+
+0) Done :)
+1) Done (some minor issues left)
+2) Done
+3) Not ready yet, more information is necessary
+4) next to be done (see the table below)
+5) USB driver is working (yes, there are some minor issues)
+
+What seems to be ready?
+-----------------------
+
+1) Rewriting
+1a) i2c is cut off from the flexcop-pci.c and seems to work
+1b) moved tuner and demod stuff from flexcop-pci.c to flexcop-tuner-fe.c
+1c) moved lnb and diseqc stuff from flexcop-pci.c to flexcop-tuner-fe.c
+1e) eeprom (reading MAC address)
+1d) sram (no dynamic sll size detection (commented out) (using default as JJ 
told me))
+1f) misc. register accesses for reading parameters (e.g. resetting, revision)
+1g) pid/mac filter (flexcop-hw-filter.c)
+1i) dvb-stuff initialization in flexcop.c (done)
+1h) dma stuff (now just using the size-irq, instead of all-together, to be 
done)
+1j) remove flexcop initialization from flexcop-pci.c completely (done)
+1l) use a well working dma IRQ method (done, see 'Known bugs and problems and 
TODO')
+1k) cleanup flexcop-files (remove unused EXPORT_SYMBOLs, make static from
+non-static where possible, moved code to proper places)
+
+2) Search for errors in the leftover of flexcop-pci.c (partially done)
+5a) add MAC address reading
+5c) feeding of ISOC data to the software demux (format of the isochronous data
+and speed optimization, no real error) (thanks to Vadim Catana)
+
+What to do in the near future?
+--------------------------------------
+(no special order here)
+
+5) USB driver
+5b) optimize isoc-transfer (submitting/killing isoc URBs when transfer is 
starting)
+
+Testing changes
+---------------
+
+O             = item is working
+P             = item is partially working
+X             = item is not working
+N             = item does not apply here
+<empty field> = item need to be examined
+
+       | PCI                               | USB
+item   | mt352 | nxt2002 | stv0299 | mt312 | mt352 | nxt2002 | stv0299 | mt312
+-------+-------+---------+---------+-------+-------+---------+---------+-------
+1a)    | O     |         |         |       | N     | N       | N       | N
+1b)    | O     |         |         |       |       |         | O       |
+1c)    | N     | N       |         |       | N     | N       | O       |
+1d)    |                 O                 |                 O
+1e)    |                 O                 |                 O
+1f)    |                                   P
+1g)    |                                   O
+1h)    |                 P                 |
+1i)    |                 O                 |                 N
+1j)    |                 O                 |                 N
+1l)    |                 O                 |                 N
+2)     |                 O                 |                 N
+5a)    |                 N                 |                 O
+5b)*   |                 N                 |
+5c)    |                 N                 |                 O
+
+* - not done yet
+
+Known bugs and problems and TODO
+--------------------------------
+
+1g/h/l) when pid filtering is enabled on the pci card
+
+DMA usage currently:
+  The DMA is splitted in 2 equal-sized subbuffers. The Flexcop writes to first
+  address and triggers an IRQ when it's full and starts writing to the second
+  address. When the second address is full, the IRQ is triggered again, and
+  the flexcop writes to first address again, and so on.
+  The buffersize of each address is currently 640*188 bytes.
+
+  Problem is, when using hw-pid-filtering and doing some low-bandwidth
+  operation (like scanning) the buffers won't be filled enough to trigger
+  the IRQ. That's why:
+
+  When PID filtering is activated, the timer IRQ is used. Every 1.97 ms the IRQ
+  is triggered.  Is the current write address of DMA1 different to the one
+  during the last IRQ, then the data is passed to the demuxer.
+
+  There is an additional DMA-IRQ-method: packet count IRQ. This isn't
+  implemented correctly yet.
+
+  The solution is to disable HW PID filtering, but I don't know how the DVB
+  API software demux behaves on slow systems with 45MBit/s TS.
+
+Solved bugs :)
+--------------
+1g) pid-filtering (somehow pid index 4 and 5 (EMM_PID and ECM_PID) aren't
+working)
+SOLUTION: also index 0 was affected, because net_translation is done for
+these indexes by default
+
+5b) isochronous transfer does only work in the first attempt (for the Sky2PC
+USB, Air2PC is working) SOLUTION: the flexcop was going asleep and never really
+woke up again (don't know if this need fixes, see
+flexcop-fe-tuner.c:flexcop_sleep)
+
+NEWS: when the driver is loaded and unloaded and loaded again (w/o doing
+anything in the while the driver is loaded the first time), no transfers take
+place anymore.
+
+Improvements when rewriting (refactoring) is done
+=================================================
+
+- split sleeping of the flexcop (misc_204.ACPI3_sig = 1;) from lnb_control
+  (enable sleeping for other demods than dvb-s)
+- add support for CableStar (stv0297 Microtune 203x/ALPS) (almost done, 
incompatibilities with the Nexus-CA)
+
+Debugging
+---------
+- add verbose debugging to skystar2.c (dump the reg_dw_data) and compare it
+  with this flexcop, this is important, because i2c is now using the
+  flexcop_ibi_value union from flexcop-reg.h (do you have a better idea for
+  that, please tell us so).
+
+Everything which is identical in the following table, can be put into a common
+flexcop-module.
+
+                  PCI                  USB
+-------------------------------------------------------------------------------
+Different:
+Register access:  accessing IO memory  USB control message
+I2C bus:          I2C bus of the FC    USB control message
+Data transfer:    DMA                  isochronous transfer
+EEPROM transfer:  through i2c bus      not clear yet
+
+Identical:
+Streaming:                 accessing registers
+PID Filtering:             accessing registers
+Sram destinations:         accessing registers
+Tuner/Demod:                     I2C bus
+DVB-stuff:            can be written for common use
+
+Acknowledgements (just for the rewriting part)
+================
+
+Bjarne Steinsbo thought a lot in the first place of the pci part for this code
+sharing idea.
+
+Andreas Oberritter for providing a recent PCI initialization template
+(pluto2.c).
+
+Boleslaw Ciesielski for pointing out a problem with firmware loader.
+
+Vadim Catana for correcting the USB transfer.
+
+comments, critics and ideas to linux-dvb@linuxtv.org.
diff -urN linux/Documentation/dvb/ci.txt linux/Documentation/dvb/ci.txt
--- linux/Documentation/dvb/ci.txt      1970/01/01 00:00:00
+++ linux/Documentation/dvb/ci.txt      2005-05-26 10:12:36.310895000 +0100     
1.1
@@ -0,0 +1,219 @@
+* For the user
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+NOTE: This document describes the usage of the high level CI API as
+in accordance to the Linux DVB API. This is a not a documentation for the,
+existing low level CI API.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To utilize the High Level CI capabilities,
+
+(1*) This point is valid only for the Twinhan/clones
+  For the Twinhan/Twinhan clones, the dst_ca module handles the CI
+  hardware handling.This module is loaded automatically if a CI
+  (Common Interface, that holds the CAM (Conditional Access Module)
+  is detected.
+
+(2) one requires a userspace application, ca_zap. This small userland
+  application is in charge of sending the descrambling related information
+  to the CAM.
+
+This application requires the following to function properly as of now.
+
+       (a) Tune to a valid channel, with szap.
+         eg: $ szap -c channels.conf -r "TMC" -x
+
+       (b) a channels.conf containing a valid PMT PID
+
+         eg: TMC:11996:h:0:27500:278:512:650:321
+
+         here 278 is a valid PMT PID. the rest of the values are the
+         same ones that szap uses.
+
+       (c) after running a szap, you have to run ca_zap, for the
+         descrambler to function,
+
+         eg: $ ca_zap patched_channels.conf "TMC"
+
+         The patched means a patch to apply to scan, such that scan can
+         generate a channels.conf_with pmt, which has this PMT PID info
+         (NOTE: szap cannot use this channels.conf with the PMT_PID)
+
+
+       (d) Hopeflly Enjoy your favourite subscribed channel as you do with
+         a FTA card.
+
+(3) Currently ca_zap, and dst_test, both are meant for demonstration
+  purposes only, they can become full fledged applications if necessary.
+
+
+* Cards that fall in this category
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+At present the cards that fall in this category are the Twinhan and it's
+clones, these cards are available as VVMER, Tomato, Hercules, Orange and
+so on.
+
+* CI modules that are supported
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The CI module support is largely dependant upon the firmware on the cards
+Some cards do support almost all of the available CI modules. There is
+nothing much that can be done in order to make additional CI modules
+working with these cards.
+
+Modules that have been tested by this driver at present are
+
+(1) Irdeto 1 and 2 from SCM
+(2) Viaccess from SCM
+(3) Dragoncam
+
+* The High level CI API
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* For the programmer
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+With the High Level CI approach any new card with almost any random
+architecture can be implemented with this style, the definitions
+insidethe switch statement can be easily adapted for any card, thereby
+eliminating the need for any additional ioctls.
+
+The disadvantage is that the driver/hardware has to manage the rest. For
+the application programmer it would be as simple as sending/receiving an
+array to/from the CI ioctls as defined in the Linux DVB API. No changes
+have been made in the API to accomodate this feature.
+
+
+* Why the need for another CI interface ?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This is one of the most commonly asked question. Well a nice question.
+Strictly speaking this is not a new interface.
+
+The CI interface is defined in the DVB API in ca.h as
+
+typedef struct ca_slot_info {
+       int num;               /* slot number */
+
+       int type;              /* CA interface this slot supports */
+#define CA_CI            1     /* CI high level interface */
+#define CA_CI_LINK       2     /* CI link layer level interface */
+#define CA_CI_PHYS       4     /* CI physical layer level interface */
+#define CA_DESCR         8     /* built-in descrambler */
+#define CA_SC          128     /* simple smart card interface */
+
+       unsigned int flags;
+#define CA_CI_MODULE_PRESENT 1 /* module (or card) inserted */
+#define CA_CI_MODULE_READY   2
+} ca_slot_info_t;
+
+
+
+This CI interface follows the CI high level interface, which is not
+implemented by most applications. Hence this area is revisited.
+
+This CI interface is quite different in the case that it tries to
+accomodate all other CI based devices, that fall into the other categories
+
+This means that this CI interface handles the EN50221 style tags in the
+Application layer only and no session management is taken care of by the
+application. The driver/hardware will take care of all that.
+
+This interface is purely an EN50221 interface exchanging APDU's. This
+means that no session management, link layer or a transport layer do
+exist in this case in the application to driver communication. It is
+as simple as that. The driver/hardware has to take care of that.
+
+
+With this High Level CI interface, the interface can be defined with the
+regular ioctls.
+
+All these ioctls are also valid for the High level CI interface
+
+#define CA_RESET          _IO('o', 128)
+#define CA_GET_CAP        _IOR('o', 129, ca_caps_t)
+#define CA_GET_SLOT_INFO  _IOR('o', 130, ca_slot_info_t)
+#define CA_GET_DESCR_INFO _IOR('o', 131, ca_descr_info_t)
+#define CA_GET_MSG        _IOR('o', 132, ca_msg_t)
+#define CA_SEND_MSG       _IOW('o', 133, ca_msg_t)
+#define CA_SET_DESCR      _IOW('o', 134, ca_descr_t)
+#define CA_SET_PID        _IOW('o', 135, ca_pid_t)
+
+
+On querying the device, the device yields information thus
+
+CA_GET_SLOT_INFO
+----------------------------
+Command = [info]
+APP: Number=[1]
+APP: Type=[1]
+APP: flags=[1]
+APP: CI High level interface
+APP: CA/CI Module Present
+
+CA_GET_CAP
+----------------------------
+Command = [caps]
+APP: Slots=[1]
+APP: Type=[1]
+APP: Descrambler keys=[16]
+APP: Type=[1]
+
+CA_SEND_MSG
+----------------------------
+Descriptors(Program Level)=[ 09 06 06 04 05 50 ff f1]
+Found CA descriptor @ program level
+
+(20) ES type=[2] ES pid=[201]  ES length =[0 (0x0)]
+(25) ES type=[4] ES pid=[301]  ES length =[0 (0x0)]
+ca_message length is 25 (0x19) bytes
+EN50221 CA MSG=[ 9f 80 32 19 03 01 2d d1 f0 08 01 09 06 06 04 05 50 ff f1 02 
e0 c9 00 00 04 e1 2d 00 00]
+
+
+Not all ioctl's are implemented in the driver from the API, the other
+features of the hardware that cannot be implemented by the API are achieved
+using the CA_GET_MSG and CA_SEND_MSG ioctls. An EN50221 style wrapper is
+used to exchange the data to maintain compatibility with other hardware.
+
+
+/* a message to/from a CI-CAM */
+typedef struct ca_msg {
+       unsigned int index;
+       unsigned int type;
+       unsigned int length;
+       unsigned char msg[256];
+} ca_msg_t;
+
+
+The flow of data can be described thus,
+
+
+
+
+
+       App (User)
+       -----
+       parse
+         |
+         |
+         v
+       en50221 APDU (package)
+   --------------------------------------
+   |     |                             | High Level CI driver
+   |     |                             |
+   |     v                             |
+   |   en50221 APDU (unpackage)        |
+   |     |                             |
+   |     |                             |
+   |     v                             |
+   |   sanity checks                   |
+   |     |                             |
+   |     |                             |
+   |     v                             |
+   |   do (H/W dep)                    |
+   --------------------------------------
+         |    Hardware
+         |
+         v
+
+
+
+
+The High Level CI interface uses the EN50221 DVB standard, following a
+standard ensures futureproofness.
diff -urN linux/Documentation/dvb/bt8xx.txt linux/Documentation/dvb/bt8xx.txt
--- linux/Documentation/dvb/bt8xx.txt   2004/01/10 04:59:48     1.1
+++ linux/Documentation/dvb/bt8xx.txt   2005/05/26 09:12:36     1.2
@@ -17,74 +17,53 @@
 "Device drivers" => "Multimedia devices"
   => "Video For Linux" => "BT848 Video For Linux"
 
+Furthermore you need to enable
+"Device drivers" => "Multimedia devices" => "Digital Video Broadcasting 
Devices"
+  => "DVB for Linux" "DVB Core Support" "Nebula/Pinnacle PCTV/TwinHan PCI 
Cards"
+
 2) Loading Modules
 ==================
 
 In general you need to load the bttv driver, which will handle the gpio and
-i2c communication for us. Next you need the common dvb-bt8xx device driver
-and one frontend driver.
-
-The bttv driver will HANG YOUR SYSTEM IF YOU DO NOT SPECIFY THE CORRECT 
-CARD ID!
-
-(If you don't get your card running and you suspect that the card id you're
-using is wrong, have a look at "bttv-cards.c" for a list of possible card
-ids.)
-
-Pay attention to failures when you load the frontend drivers
-(e.g. dmesg, /var/log/messages).
+i2c communication for us, plus the common dvb-bt8xx device driver.
+The frontends for Nebula (nxt6000), Pinnacle PCTV (cx24110) and
+TwinHan (dst) are loaded automatically by the dvb-bt8xx device driver.
 
 3a) Nebula / Pinnacle PCTV
 --------------------------
 
-   $ modprobe bttv i2c_hw=1 card=0x68
-   $ modprobe dvb-bt8xx
-   
-For Nebula cards use the "nxt6000" frontend driver:
-   $ modprobe nxt6000
+   $ modprobe bttv (normally bttv is being loaded automatically by kmod)
+   $ modprobe dvb-bt8xx (or just place dvb-bt8xx in /etc/modules for automatic 
loading)
 
-For Pinnacle PCTV cards use the "cx24110" frontend driver:
-   $ modprobe cx24110
 
-3b) TwinHan
------------
+3b) TwinHan and Clones
+--------------------------
 
    $ 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.#
+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 DVB mailing 
list.
+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, in case the
-dst drivers fails to detect your type of card correctly.
+The DST module takes a couple of useful parameters.
 
-dst_type takes values 0 (satellite), 1 (terrestial TV), 2 (cable).
+verbose takes values 0 to 5. These values control the verbosity level.
 
-dst_type_flags takes bit combined values:
-1 = new tuner type packets. You can use this if your card is detected
-    and you have debug and you continually see the tuner packets not
-    working (make sure not a basic problem like dish alignment etc.)
+debug takes values 0 and 1. You can either disable or enable debugging.
 
-2 = TS 204. If your card tunes OK, but the picture is terrible, seemingly
-    breaking up in one half continually, and crc fails a lot, then
-    this is worth a try (or trying to turn off)
+dst_addons takes values 0 and 0x20. A value of 0 means it is a FTA card.
+0x20 means it has a Conditional Access slot.
 
-4 = has symdiv. Some cards, mostly without new tuner packets, require
-    a symbol division algorithm. Doesn't apply to terrestial TV.
-
-You can also specify a value to have the autodetected values turned off
-(e.g. 0). The autodected values are determined bythe cards 'response
+The autodected values are determined bythe cards 'response
 string' which you can see in your logs e.g.
 
-dst_check_ci: recognize DST-MOT
-
-or 
+dst_get_device_id: Recognise [DSTMCI]
 
-dst_check_ci: unable to recognize DSTXCI or STXCI
 
 --
-Authors: Richard Walker, Jamie Honan, Michael Hunold
+Authors: Richard Walker, Jamie Honan, Michael Hunold, Manu Abraham
diff -urN linux/Documentation/dvb/get_dvb_firmware 
linux/Documentation/dvb/get_dvb_firmware
--- linux/Documentation/dvb/get_dvb_firmware    2005/04/08 18:57:46     1.4
+++ linux/Documentation/dvb/get_dvb_firmware    2005/05/26 09:12:36     1.5
@@ -107,7 +107,7 @@
 sub tda10046 {
     my $sourcefile = "tt_budget_217g.zip";
     my $url = "http://www.technotrend.de/new/217g/$sourcefile";;
-    my $hash = "a25b579e37109af60f4a36c37893957c";
+    my $hash = "6a7e1e2f2644b162ff0502367553c72d";
     my $outfile = "dvb-fe-tda10046.fw";
     my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
 
@@ -115,7 +115,7 @@
 
     wgetfile($sourcefile, $url);
     unzip($sourcefile, $tmpdir);
-    extract("$tmpdir/software/OEM/PCI/App/ttlcdacc.dll", 0x3f731, 24479, 
"$tmpdir/fwtmp");
+    extract("$tmpdir/software/OEM/PCI/App/ttlcdacc.dll", 0x3f731, 24478, 
"$tmpdir/fwtmp");
     verify("$tmpdir/fwtmp", $hash);
     copy("$tmpdir/fwtmp", $outfile);
 
diff -urN linux/Documentation/filesystems/sysfs-pci.txt 
linux/Documentation/filesystems/sysfs-pci.txt
--- linux/Documentation/filesystems/sysfs-pci.txt       2005/01/13 14:05:15     
1.1
+++ linux/Documentation/filesystems/sysfs-pci.txt       2005/05/26 09:12:36     
1.2
@@ -7,7 +7,6 @@
      |-- 0000:17:00.0
      |   |-- class
      |   |-- config
-     |   |-- detach_state
      |   |-- device
      |   |-- irq
      |   |-- local_cpus
@@ -19,7 +18,7 @@
      |   |-- subsystem_device
      |   |-- subsystem_vendor
      |   `-- vendor
-     `-- detach_state
+     `-- ...
 
 The topmost element describes the PCI domain and bus number.  In this case,
 the domain number is 0000 and the bus number is 17 (both values are in hex).
@@ -31,7 +30,6 @@
        ----               --------
        class              PCI class (ascii, ro)
        config             PCI config space (binary, rw)
-       detach_state       connection status (bool, rw)
        device             PCI device (ascii, ro)
        irq                IRQ number (ascii, ro)
        local_cpus         nearby CPU mask (cpumask, ro)
@@ -85,4 +83,4 @@
 
 Legacy resources are protected by the HAVE_PCI_LEGACY define.  Platforms
 wishing to support legacy functionality should define it and provide
-pci_legacy_read, pci_legacy_write and pci_mmap_legacy_page_range functions.
\ No newline at end of file
+pci_legacy_read, pci_legacy_write and pci_mmap_legacy_page_range functions.
diff -urN linux/Documentation/power/devices.txt 
linux/Documentation/power/devices.txt
--- linux/Documentation/power/devices.txt       2005/04/08 18:57:47     1.4
+++ linux/Documentation/power/devices.txt       2005/05/26 09:12:36     1.5
@@ -207,27 +207,6 @@
 #READY_AFTER_RESUME
 #
 
-Driver Detach Power Management
-
-The kernel now supports the ability to place a device in a low-power
-state when it is detached from its driver, which happens when its
-module is removed. 
-
-Each device contains a 'detach_state' file in its sysfs directory
-which can be used to control this state. Reading from this file
-displays what the current detach state is set to. This is 0 (On) by
-default. A user may write a positive integer value to this file in the
-range of 1-4 inclusive. 
-
-A value of 1-3 will indicate the device should be placed in that
-low-power state, which will cause ->suspend() to be called for that
-device. A value of 4 indicates that the device should be shutdown, so
-->shutdown() will be called for that device. 
-
-The driver is responsible for reinitializing the device when the
-module is re-inserted during it's ->probe() (or equivalent) method. 
-The driver core will not call any extra functions when binding the
-device to the driver. 
 
 pm_message_t meaning
 
diff -urN linux/Documentation/powerpc/hvcs.txt 
linux/Documentation/powerpc/hvcs.txt
--- linux/Documentation/powerpc/hvcs.txt        2004/09/19 12:30:01     1.2
+++ linux/Documentation/powerpc/hvcs.txt        2005/05/26 09:12:36     1.3
@@ -347,8 +347,8 @@
 looks like the following:
 
        Pow5:/sys/bus/vio/drivers/hvcs/30000004 # ls
-       .   current_vty   devspec  name          partner_vtys
-       ..  detach_state  index    partner_clcs  vterm_state
+       .   current_vty   devspec       name          partner_vtys
+       ..  index         partner_clcs  vterm_state
 
 Each entry is provided, by default with a "name" attribute.  Reading the
 "name" attribute will reveal the device type as shown in the following
diff -urN linux/Documentation/x86_64/boot-options.txt 
linux/Documentation/x86_64/boot-options.txt
--- linux/Documentation/x86_64/boot-options.txt 2005/01/13 14:05:16     1.8
+++ linux/Documentation/x86_64/boot-options.txt 2005/05/26 09:12:36     1.9
@@ -25,6 +25,9 @@
 
    noapictimer  Don't set up the APIC timer
 
+   no_timer_check Don't check the IO-APIC timer. This can work around
+                problems with incorrect timer initialization on some boards.
+
 Early Console
 
    syntax: earlyprintk=vga
diff -urN linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- linux/arch/alpha/kernel/osf_sys.c   2005/05/19 12:08:06     1.55
+++ linux/arch/alpha/kernel/osf_sys.c   2005/05/26 09:12:36     1.56
@@ -1150,16 +1150,13 @@
        if (get_tv32(&tmp, sleep))
                goto fault;
 
-       ticks = tmp.tv_usec;
-       ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ);
-       ticks += tmp.tv_sec * HZ;
+       ticks = timeval_to_jiffies(&tmp);
 
        current->state = TASK_INTERRUPTIBLE;
        ticks = schedule_timeout(ticks);
 
        if (remain) {
-               tmp.tv_sec = ticks / HZ;
-               tmp.tv_usec = ticks % HZ;
+               jiffies_to_timeval(ticks, &tmp);
                if (put_tv32(remain, &tmp))
                        goto fault;
        }
diff -urN linux/arch/arm/mach-s3c2410/clock.c 
linux/arch/arm/mach-s3c2410/clock.c
--- linux/arch/arm/mach-s3c2410/clock.c 2005/03/18 17:36:46     1.7
+++ linux/arch/arm/mach-s3c2410/clock.c 2005/05/26 09:12:36     1.8
@@ -478,7 +478,7 @@
 {
        unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
 
-       s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal.rate) * 2;
+       s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal.rate);
 
        printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n",
               print_mhz(s3c2440_clk_upll.rate));
diff -urN linux/arch/arm/mach-s3c2410/s3c2440.c 
linux/arch/arm/mach-s3c2410/s3c2440.c
--- linux/arch/arm/mach-s3c2410/s3c2440.c       2005/04/08 18:57:52     1.8
+++ linux/arch/arm/mach-s3c2410/s3c2440.c       2005/05/26 09:12:36     1.9
@@ -192,9 +192,11 @@
 
        iotable_init(s3c2440_iodesc, ARRAY_SIZE(s3c2440_iodesc));
        iotable_init(mach_desc, size);
+
        /* rename any peripherals used differing from the s3c2410 */
 
-       s3c_device_i2c.name = "s3c2440-i2c";
+       s3c_device_i2c.name  = "s3c2440-i2c";
+       s3c_device_nand.name = "s3c2440-nand";
 
        /* change irq for watchdog */
 
@@ -225,7 +227,7 @@
                break;
 
        case S3C2440_CLKDIVN_HDIVN_2:
-               hdiv = 1;
+               hdiv = 2;
                break;
 
        case S3C2440_CLKDIVN_HDIVN_4_8:
diff -urN linux/arch/arm/mm/copypage-v4mc.c linux/arch/arm/mm/copypage-v4mc.c
--- linux/arch/arm/mm/copypage-v4mc.c   1970/01/01 00:00:00
+++ linux/arch/arm/mm/copypage-v4mc.c   2005-05-26 10:12:36.862745000 +0100     
1.1
@@ -0,0 +1,111 @@
+/*
+ *  linux/arch/arm/lib/copypage-armv4mc.S
+ *
+ *  Copyright (C) 1995-2005 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This handles the mini data cache, as found on SA11x0 and XScale
+ * processors.  When we copy a user page page, we map it in such a way
+ * that accesses to this page will not touch the main data cache, but
+ * will be cached in the mini data cache.  This prevents us thrashing
+ * the main data cache on page faults.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+/*
+ * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
+ * specific hacks for copying pages efficiently.
+ */
+#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
+                                 L_PTE_CACHEABLE)
+
+#define TOP_PTE(x)     pte_offset_kernel(top_pmd, x)
+
+static DEFINE_SPINLOCK(minicache_lock);
+
+/*
+ * ARMv4 mini-dcache optimised copy_user_page
+ *
+ * We flush the destination cache lines just before we write the data into the
+ * corresponding address.  Since the Dcache is read-allocate, this removes the
+ * Dcache aliasing issue.  The writes will be forwarded to the write buffer,
+ * and merged as appropriate.
+ *
+ * Note: We rely on all ARMv4 processors implementing the "invalidate D line"
+ * instruction.  If your processor does not supply this, you have to write your
+ * own copy_user_page that does the right thing.
+ */
+static void __attribute__((naked))
+mc_copy_user_page(void *from, void *to)
+{
+       asm volatile(
+       "stmfd  sp!, {r4, lr}                   @ 2\n\
+       mov     r4, %2                          @ 1\n\
+       ldmia   %0!, {r2, r3, ip, lr}           @ 4\n\
+1:     mcr     p15, 0, %1, c7, c6, 1           @ 1   invalidate D line\n\
+       stmia   %1!, {r2, r3, ip, lr}           @ 4\n\
+       ldmia   %0!, {r2, r3, ip, lr}           @ 4+1\n\
+       stmia   %1!, {r2, r3, ip, lr}           @ 4\n\
+       ldmia   %0!, {r2, r3, ip, lr}           @ 4\n\
+       mcr     p15, 0, %1, c7, c6, 1           @ 1   invalidate D line\n\
+       stmia   %1!, {r2, r3, ip, lr}           @ 4\n\
+       ldmia   %0!, {r2, r3, ip, lr}           @ 4\n\
+       subs    r4, r4, #1                      @ 1\n\
+       stmia   %1!, {r2, r3, ip, lr}           @ 4\n\
+       ldmneia %0!, {r2, r3, ip, lr}           @ 4\n\
+       bne     1b                              @ 1\n\
+       ldmfd   sp!, {r4, pc}                   @ 3"
+       :
+       : "r" (from), "r" (to), "I" (PAGE_SIZE / 64));
+}
+
+void v4_mc_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr)
+{
+       spin_lock(&minicache_lock);
+
+       set_pte(TOP_PTE(0xffff8000), pfn_pte(__pa(kfrom) >> PAGE_SHIFT, 
minicache_pgprot));
+       flush_tlb_kernel_page(0xffff8000);
+
+       mc_copy_user_page((void *)0xffff8000, kto);
+
+       spin_unlock(&minicache_lock);
+}
+
+/*
+ * ARMv4 optimised clear_user_page
+ */
+void __attribute__((naked))
+v4_mc_clear_user_page(void *kaddr, unsigned long vaddr)
+{
+       asm volatile(
+       "str    lr, [sp, #-4]!\n\
+       mov     r1, %0                          @ 1\n\
+       mov     r2, #0                          @ 1\n\
+       mov     r3, #0                          @ 1\n\
+       mov     ip, #0                          @ 1\n\
+       mov     lr, #0                          @ 1\n\
+1:     mcr     p15, 0, r0, c7, c6, 1           @ 1   invalidate D line\n\
+       stmia   r0!, {r2, r3, ip, lr}           @ 4\n\
+       stmia   r0!, {r2, r3, ip, lr}           @ 4\n\
+       mcr     p15, 0, r0, c7, c6, 1           @ 1   invalidate D line\n\
+       stmia   r0!, {r2, r3, ip, lr}           @ 4\n\
+       stmia   r0!, {r2, r3, ip, lr}           @ 4\n\
+       subs    r1, r1, #1                      @ 1\n\
+       bne     1b                              @ 1\n\
+       ldr     pc, [sp], #4"
+       :
+       : "I" (PAGE_SIZE / 64));
+}
+
+struct cpu_user_fns v4_mc_user_fns __initdata = {
+       .cpu_clear_user_page    = v4_mc_clear_user_page, 
+       .cpu_copy_user_page     = v4_mc_copy_user_page,
+};
diff -urN linux/arch/arm/mm/Kconfig linux/arch/arm/mm/Kconfig
--- linux/arch/arm/mm/Kconfig   2005/05/19 12:08:07     1.17
+++ linux/arch/arm/mm/Kconfig   2005/05/26 09:12:36     1.18
@@ -412,21 +412,20 @@
 
 config TLS_REG_EMUL
        bool
-       default y if (SMP || CPU_32v6) && (CPU_32v5 || CPU_32v4 || CPU_32v3)
+       default y if SMP && (CPU_32v5 || CPU_32v4 || CPU_32v3)
        help
-         We might be running on an ARMv6+ processor which should have the TLS
-         register but for some reason we can't use it, or maybe an SMP system
-         using a pre-ARMv6 processor (there are apparently a few prototypes
-         like that in existence) and therefore access to that register must
-         be emulated.
+         An SMP system using a pre-ARMv6 processor (there are apparently
+         a few prototypes like that in existence) and therefore access to
+         that required register must be emulated.
 
 config HAS_TLS_REG
        bool
-       depends on CPU_32v6
-       default y if !TLS_REG_EMUL
+       depends on !TLS_REG_EMUL
+       default y if SMP || CPU_32v7
        help
          This selects support for the CP15 thread register.
-         It is defined to be available on ARMv6 or later.  If a particular
-         ARMv6 or later CPU doesn't support it then it must omc;ide "select
-         TLS_REG_EMUL" along with its other caracteristics.
+         It is defined to be available on some ARMv6 processors (including
+         all SMP capable ARMv6's) or later processors.  User space may
+         assume directly accessing that register and always obtain the
+         expected value only on ARMv7 and above.
 
diff -urN linux/arch/arm/mm/copypage-v6.c linux/arch/arm/mm/copypage-v6.c
--- linux/arch/arm/mm/copypage-v6.c     2005/01/25 04:27:54     1.5
+++ linux/arch/arm/mm/copypage-v6.c     2005/05/26 09:12:36     1.6
@@ -26,8 +26,8 @@
 #define to_address     (0xffffc000)
 #define to_pgprot      PAGE_KERNEL
 
-static pte_t *from_pte;
-static pte_t *to_pte;
+#define TOP_PTE(x)     pte_offset_kernel(top_pmd, x)
+
 static DEFINE_SPINLOCK(v6_lock);
 
 #define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
@@ -74,8 +74,8 @@
         */
        spin_lock(&v6_lock);
 
-       set_pte(from_pte + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, 
from_pgprot));
-       set_pte(to_pte + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, to_pgprot));
+       set_pte(TOP_PTE(from_address) + offset, pfn_pte(__pa(kfrom) >> 
PAGE_SHIFT, from_pgprot));
+       set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, 
to_pgprot));
 
        from = from_address + (offset << PAGE_SHIFT);
        to   = to_address + (offset << PAGE_SHIFT);
@@ -114,7 +114,7 @@
         */
        spin_lock(&v6_lock);
 
-       set_pte(to_pte + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot));
+       set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kaddr) >> 
PAGE_SHIFT, to_pgprot));
        flush_tlb_kernel_page(to);
        clear_page((void *)to);
 
@@ -129,21 +129,6 @@
 static int __init v6_userpage_init(void)
 {
        if (cache_is_vipt_aliasing()) {
-               pgd_t *pgd;
-               pmd_t *pmd;
-
-               pgd = pgd_offset_k(from_address);
-               pmd = pmd_alloc(&init_mm, pgd, from_address);
-               if (!pmd)
-                       BUG();
-               from_pte = pte_alloc_kernel(&init_mm, pmd, from_address);
-               if (!from_pte)
-                       BUG();
-
-               to_pte = pte_alloc_kernel(&init_mm, pmd, to_address);
-               if (!to_pte)
-                       BUG();
-
                cpu_user.cpu_clear_user_page = v6_clear_user_page_aliasing;
                cpu_user.cpu_copy_user_page = v6_copy_user_page_aliasing;
        }
@@ -151,5 +136,4 @@
        return 0;
 }
 
-__initcall(v6_userpage_init);
-
+core_initcall(v6_userpage_init);
diff -urN linux/arch/arm/mm/flush.c linux/arch/arm/mm/flush.c
--- linux/arch/arm/mm/flush.c   2005/03/18 17:36:47     1.2
+++ linux/arch/arm/mm/flush.c   2005/05/26 09:12:36     1.3
@@ -13,6 +13,29 @@
 
 #include <asm/cacheflush.h>
 #include <asm/system.h>
+#include <asm/tlbflush.h>
+
+#ifdef CONFIG_CPU_CACHE_VIPT
+#define ALIAS_FLUSH_START      0xffff4000
+
+#define TOP_PTE(x)     pte_offset_kernel(top_pmd, x)
+
+static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
+{
+       unsigned long to = ALIAS_FLUSH_START + (CACHE_COLOUR(vaddr) << 
PAGE_SHIFT);
+
+       set_pte(TOP_PTE(to), pfn_pte(pfn, PAGE_KERNEL));
+       flush_tlb_kernel_page(to);
+
+       asm(    "mcrr   p15, 0, %1, %0, c14\n"
+       "       mcrr    p15, 0, %1, %0, c5\n"
+           :
+           : "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES)
+           : "cc");
+}
+#else
+#define flush_pfn_alias(pfn,vaddr)     do { } while (0)
+#endif
 
 static void __flush_dcache_page(struct address_space *mapping, struct page 
*page)
 {
@@ -37,6 +60,18 @@
                return;
 
        /*
+        * This is a page cache page.  If we have a VIPT cache, we
+        * only need to do one flush - which would be at the relevant
+        * userspace colour, which is congruent with page->index.
+        */
+       if (cache_is_vipt()) {
+               if (cache_is_vipt_aliasing())
+                       flush_pfn_alias(page_to_pfn(page),
+                                       page->index << PAGE_CACHE_SHIFT);
+               return;
+       }
+
+       /*
         * There are possible user space mappings of this page:
         * - VIVT cache: we need to also write back and invalidate all user
         *   data in the current VM view associated with this page.
@@ -57,8 +92,6 @@
                        continue;
                offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
                flush_cache_page(mpnt, mpnt->vm_start + offset, 
page_to_pfn(page));
-               if (cache_is_vipt())
-                       break;
        }
        flush_dcache_mmap_unlock(mapping);
 }
diff -urN linux/arch/arm/mm/mm-armv.c linux/arch/arm/mm/mm-armv.c
--- linux/arch/arm/mm/mm-armv.c 2005/05/19 12:08:07     1.47
+++ linux/arch/arm/mm/mm-armv.c 2005/05/26 09:12:36     1.48
@@ -37,6 +37,8 @@
 
 EXPORT_SYMBOL(pgprot_kernel);
 
+pmd_t *top_pmd;
+
 struct cachepolicy {
        const char      policy[16];
        unsigned int    cr_mask;
@@ -142,6 +144,16 @@
 
 #define FIRST_KERNEL_PGD_NR    (FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
 
+static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
+{
+       return pmd_offset(pgd, virt);
+}
+
+static inline pmd_t *pmd_off_k(unsigned long virt)
+{
+       return pmd_off(pgd_offset_k(virt), virt);
+}
+
 /*
  * need to get a 16k page for level 1
  */
@@ -220,7 +232,7 @@
                return;
 
        /* pgd is always present and good */
-       pmd = (pmd_t *)pgd;
+       pmd = pmd_off(pgd, 0);
        if (pmd_none(*pmd))
                goto free;
        if (pmd_bad(*pmd)) {
@@ -246,9 +258,8 @@
 static inline void
 alloc_init_section(unsigned long virt, unsigned long phys, int prot)
 {
-       pmd_t *pmdp;
+       pmd_t *pmdp = pmd_off_k(virt);
 
-       pmdp = pmd_offset(pgd_offset_k(virt), virt);
        if (virt & (1 << 20))
                pmdp++;
 
@@ -283,11 +294,9 @@
 static inline void
 alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, 
pgprot_t prot)
 {
-       pmd_t *pmdp;
+       pmd_t *pmdp = pmd_off_k(virt);
        pte_t *ptep;
 
-       pmdp = pmd_offset(pgd_offset_k(virt), virt);
-
        if (pmd_none(*pmdp)) {
                unsigned long pmdval;
                ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
@@ -310,7 +319,7 @@
  */
 static inline void clear_mapping(unsigned long virt)
 {
-       pmd_clear(pmd_offset(pgd_offset_k(virt), virt));
+       pmd_clear(pmd_off_k(virt));
 }
 
 struct mem_types {
@@ -578,7 +587,7 @@
                         PMD_TYPE_SECT;
                if (cpu_arch <= CPU_ARCH_ARMv5)
                        pmdval |= PMD_BIT4;
-               pmd = pmd_offset(pgd + i, i << PGDIR_SHIFT);
+               pmd = pmd_off(pgd, i << PGDIR_SHIFT);
                pmd[0] = __pmd(pmdval);
                pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
                flush_pmd_entry(pmd);
@@ -675,6 +684,8 @@
 
        flush_cache_all();
        flush_tlb_all();
+
+       top_pmd = pmd_off_k(0xffff0000);
 }
 
 /*
diff -urN linux/arch/arm/mm/copypage-v4mc.S linux/arch/arm/mm/copypage-v4mc.S
--- linux/arch/arm/mm/Attic/copypage-v4mc.S     2005-05-26 10:12:36.945954000 
+0100     1.4
+++ linux/arch/arm/mm/Attic/copypage-v4mc.S     1970/01/01 00:00:00+0100
@@ -1,80 +0,0 @@
-/*
- *  linux/arch/arm/lib/copy_page-armv4mc.S
- *
- *  Copyright (C) 1995-2001 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *  ASM optimised string functions
- */
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/constants.h>
-
-       .text
-       .align  5
-/*
- * ARMv4 mini-dcache optimised copy_user_page
- *
- * We flush the destination cache lines just before we write the data into the
- * corresponding address.  Since the Dcache is read-allocate, this removes the
- * Dcache aliasing issue.  The writes will be forwarded to the write buffer,
- * and merged as appropriate.
- *
- * Note: We rely on all ARMv4 processors implementing the "invalidate D line"
- * instruction.  If your processor does not supply this, you have to write your
- * own copy_user_page that does the right thing.
- */
-ENTRY(v4_mc_copy_user_page)
-       stmfd   sp!, {r4, lr}                   @ 2
-       mov     r4, r0
-       mov     r0, r1
-       bl      map_page_minicache
-       mov     r1, #PAGE_SZ/64                 @ 1
-       ldmia   r0!, {r2, r3, ip, lr}           @ 4
-1:     mcr     p15, 0, r4, c7, c6, 1           @ 1   invalidate D line
-       stmia   r4!, {r2, r3, ip, lr}           @ 4
-       ldmia   r0!, {r2, r3, ip, lr}           @ 4+1
-       stmia   r4!, {r2, r3, ip, lr}           @ 4
-       ldmia   r0!, {r2, r3, ip, lr}           @ 4
-       mcr     p15, 0, r4, c7, c6, 1           @ 1   invalidate D line
-       stmia   r4!, {r2, r3, ip, lr}           @ 4
-       ldmia   r0!, {r2, r3, ip, lr}           @ 4
-       subs    r1, r1, #1                      @ 1
-       stmia   r4!, {r2, r3, ip, lr}           @ 4
-       ldmneia r0!, {r2, r3, ip, lr}           @ 4
-       bne     1b                              @ 1
-       ldmfd   sp!, {r4, pc}                   @ 3
-
-       .align  5
-/*
- * ARMv4 optimised clear_user_page
- *
- * Same story as above.
- */
-ENTRY(v4_mc_clear_user_page)
-       str     lr, [sp, #-4]!
-       mov     r1, #PAGE_SZ/64                 @ 1
-       mov     r2, #0                          @ 1
-       mov     r3, #0                          @ 1
-       mov     ip, #0                          @ 1
-       mov     lr, #0                          @ 1
-1:     mcr     p15, 0, r0, c7, c6, 1           @ 1   invalidate D line
-       stmia   r0!, {r2, r3, ip, lr}           @ 4
-       stmia   r0!, {r2, r3, ip, lr}           @ 4
-       mcr     p15, 0, r0, c7, c6, 1           @ 1   invalidate D line
-       stmia   r0!, {r2, r3, ip, lr}           @ 4
-       stmia   r0!, {r2, r3, ip, lr}           @ 4
-       subs    r1, r1, #1                      @ 1
-       bne     1b                              @ 1
-       ldr     pc, [sp], #4
-
-       __INITDATA
-
-       .type   v4_mc_user_fns, #object
-ENTRY(v4_mc_user_fns)
-       .long   v4_mc_clear_user_page
-       .long   v4_mc_copy_user_page
-       .size   v4_mc_user_fns, . - v4_mc_user_fns
diff -urN linux/arch/i386/kernel/smpboot.c linux/arch/i386/kernel/smpboot.c
--- linux/arch/i386/kernel/smpboot.c    2005/05/19 12:08:08     1.69
+++ linux/arch/i386/kernel/smpboot.c    2005/05/26 09:12:36     1.70
@@ -888,6 +888,7 @@
 
 cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
 cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
+EXPORT_SYMBOL(cpu_core_map);
 
 static void __init smp_boot_cpus(unsigned int max_cpus)
 {
diff -urN linux/arch/i386/kernel/cpu/amd.c linux/arch/i386/kernel/cpu/amd.c
--- linux/arch/i386/kernel/cpu/amd.c    2005/05/19 12:08:08     1.15
+++ linux/arch/i386/kernel/cpu/amd.c    2005/05/26 09:12:37     1.16
@@ -24,9 +24,6 @@
 
 static void __init init_amd(struct cpuinfo_x86 *c)
 {
-#ifdef CONFIG_X86_SMP
-       int cpu = c == &boot_cpu_data ? 0 : c - cpu_data;
-#endif
        u32 l, h;
        int mbytes = num_physpages >> (20-PAGE_SHIFT);
        int r;
@@ -198,14 +195,19 @@
                        c->x86_num_cores = 1;
        }
 
-#ifdef CONFIG_X86_SMP
+#ifdef CONFIG_X86_HT
        /*
         * On a AMD dual core setup the lower bits of the APIC id
         * distingush the cores.  Assumes number of cores is a power
         * of two.
         */
        if (c->x86_num_cores > 1) {
-               cpu_core_id[cpu] = cpu >> hweight32(c->x86_num_cores - 1);
+               int cpu = smp_processor_id();
+               unsigned bits = 0;
+               while ((1 << bits) < c->x86_num_cores)
+                       bits++;
+               cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1);
+               phys_proc_id[cpu] >>= bits;
                printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
                       cpu, c->x86_num_cores, cpu_core_id[cpu]);
        }
diff -urN linux/arch/i386/kernel/cpu/common.c 
linux/arch/i386/kernel/cpu/common.c
--- linux/arch/i386/kernel/cpu/common.c 2005/04/29 11:15:01     1.31
+++ linux/arch/i386/kernel/cpu/common.c 2005/05/26 09:12:37     1.32
@@ -243,6 +243,10 @@
        }
 
        early_intel_workaround(c);
+
+#ifdef CONFIG_X86_HT
+       phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
+#endif
 }
 
 void __init generic_identify(struct cpuinfo_x86 * c)
diff -urN linux/arch/i386/mach-voyager/voyager_smp.c 
linux/arch/i386/mach-voyager/voyager_smp.c
--- linux/arch/i386/mach-voyager/voyager_smp.c  2005/03/18 17:36:50     1.22
+++ linux/arch/i386/mach-voyager/voyager_smp.c  2005/05/26 09:12:37     1.23
@@ -97,7 +97,6 @@
 static void vic_enable_cpi(void);
 static void do_boot_cpu(__u8 cpuid);
 static void do_quad_bootstrap(void);
-static inline void wrapper_smp_local_timer_interrupt(struct pt_regs *);
 
 int hard_smp_processor_id(void);
 
@@ -126,6 +125,14 @@
 }
 
 static inline void
+wrapper_smp_local_timer_interrupt(struct pt_regs *regs)
+{
+       irq_enter();
+       smp_local_timer_interrupt(regs);
+       irq_exit();
+}
+
+static inline void
 send_one_CPI(__u8 cpu, __u8 cpi)
 {
        if(voyager_quad_processors & (1<<cpu))
@@ -1249,14 +1256,6 @@
        smp_local_timer_interrupt(regs);
 }
 
-static inline void
-wrapper_smp_local_timer_interrupt(struct pt_regs *regs)
-{
-       irq_enter();
-       smp_local_timer_interrupt(regs);
-       irq_exit();
-}
-
 /* local (per CPU) timer interrupt.  It does both profiling and
  * process statistics/rescheduling.
  *
diff -urN linux/arch/i386/mm/ioremap.c linux/arch/i386/mm/ioremap.c
--- linux/arch/i386/mm/ioremap.c        2005/03/18 17:36:50     1.30
+++ linux/arch/i386/mm/ioremap.c        2005/05/26 09:12:37     1.31
@@ -238,19 +238,21 @@
                        addr < phys_to_virt(ISA_END_ADDRESS))
                return;
 
-       p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
+       write_lock(&vmlist_lock);
+       p = __remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) 
addr));
        if (!p) { 
-               printk("__iounmap: bad address %p\n", addr);
-               return;
+               printk("iounmap: bad address %p\n", addr);
+               goto out_unlock;
        }
 
        if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) {
-               /* p->size includes the guard page, but cpa doesn't like that */
                change_page_attr(virt_to_page(__va(p->phys_addr)),
                                 p->size >> PAGE_SHIFT,
                                 PAGE_KERNEL);
                global_flush_tlb();
        } 
+out_unlock:
+       write_unlock(&vmlist_lock);
        kfree(p); 
 }
 
diff -urN linux/arch/i386/pci/fixup.c linux/arch/i386/pci/fixup.c
--- linux/arch/i386/pci/fixup.c 2005/04/08 18:57:54     1.15
+++ linux/arch/i386/pci/fixup.c 2005/05/26 09:12:37     1.16
@@ -253,7 +253,7 @@
 #define MAX_PCIEROOT   6
 static int quirk_aspm_offset[MAX_PCIEROOT << 3];
 
-#define GET_INDEX(a, b) (((a - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + b)
+#define GET_INDEX(a, b) ((((a) - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + ((b) & 7))
 
 static int quirk_pcie_aspm_read(struct pci_bus *bus, unsigned int devfn, int 
where, int size, u32 *value)
 {
diff -urN linux/arch/ia64/ia32/ia32_ioctl.c linux/arch/ia64/ia32/ia32_ioctl.c
--- linux/arch/ia64/ia32/ia32_ioctl.c   2004/03/11 16:46:42     1.16
+++ linux/arch/ia64/ia32/ia32_ioctl.c   2005/05/26 09:12:37     1.17
@@ -13,7 +13,6 @@
   
 #define        INCLUDES
 #include "compat_ioctl.c"
-#include <asm/ioctl32.h>
 
 #define IOCTL_NR(a)    ((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
 
diff -urN linux/arch/mips/defconfig linux/arch/mips/defconfig
--- linux/arch/mips/defconfig   2005/05/19 12:08:11     1.289
+++ linux/arch/mips/defconfig   2005/05/26 09:12:37     1.290
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:27 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:50:43 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/atlas_defconfig 
linux/arch/mips/configs/atlas_defconfig
--- linux/arch/mips/configs/atlas_defconfig     2005/05/19 12:08:11     1.53
+++ linux/arch/mips/configs/atlas_defconfig     2005/05/26 09:12:37     1.54
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:28 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:50:46 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/capcella_defconfig 
linux/arch/mips/configs/capcella_defconfig
--- linux/arch/mips/configs/capcella_defconfig  2005/05/19 12:08:11     1.53
+++ linux/arch/mips/configs/capcella_defconfig  2005/05/26 09:12:37     1.54
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:28 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:50:49 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/cobalt_defconfig 
linux/arch/mips/configs/cobalt_defconfig
--- linux/arch/mips/configs/cobalt_defconfig    2005/05/19 12:08:11     1.50
+++ linux/arch/mips/configs/cobalt_defconfig    2005/05/26 09:12:37     1.51
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:29 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:50:50 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/db1000_defconfig 
linux/arch/mips/configs/db1000_defconfig
--- linux/arch/mips/configs/db1000_defconfig    2005/05/19 12:08:11     1.56
+++ linux/arch/mips/configs/db1000_defconfig    2005/05/26 09:12:37     1.57
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:30 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:50:53 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/db1100_defconfig 
linux/arch/mips/configs/db1100_defconfig
--- linux/arch/mips/configs/db1100_defconfig    2005/05/19 12:08:11     1.55
+++ linux/arch/mips/configs/db1100_defconfig    2005/05/26 09:12:37     1.56
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:31 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:50:55 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/db1500_defconfig 
linux/arch/mips/configs/db1500_defconfig
--- linux/arch/mips/configs/db1500_defconfig    2005/05/19 12:08:11     1.58
+++ linux/arch/mips/configs/db1500_defconfig    2005/05/26 09:12:37     1.59
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:31 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:50:57 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/db1550_defconfig 
linux/arch/mips/configs/db1550_defconfig
--- linux/arch/mips/configs/db1550_defconfig    2005/05/19 12:08:11     1.33
+++ linux/arch/mips/configs/db1550_defconfig    2005/05/26 09:12:37     1.34
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:32 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:00 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/ddb5476_defconfig 
linux/arch/mips/configs/ddb5476_defconfig
--- linux/arch/mips/configs/ddb5476_defconfig   2005/05/19 12:08:11     1.50
+++ linux/arch/mips/configs/ddb5476_defconfig   2005/05/26 09:12:37     1.51
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:33 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:02 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/ddb5477_defconfig 
linux/arch/mips/configs/ddb5477_defconfig
--- linux/arch/mips/configs/ddb5477_defconfig   2005/05/19 12:08:11     1.50
+++ linux/arch/mips/configs/ddb5477_defconfig   2005/05/26 09:12:37     1.51
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:34 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:04 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/decstation_defconfig 
linux/arch/mips/configs/decstation_defconfig
--- linux/arch/mips/configs/decstation_defconfig        2005/05/19 12:08:11     
1.51
+++ linux/arch/mips/configs/decstation_defconfig        2005/05/26 09:12:37     
1.52
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:34 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:06 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/e55_defconfig 
linux/arch/mips/configs/e55_defconfig
--- linux/arch/mips/configs/e55_defconfig       2005/05/19 12:08:11     1.52
+++ linux/arch/mips/configs/e55_defconfig       2005/05/26 09:12:37     1.53
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:35 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:08 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/ev64120_defconfig 
linux/arch/mips/configs/ev64120_defconfig
--- linux/arch/mips/configs/ev64120_defconfig   2005/05/19 12:08:11     1.49
+++ linux/arch/mips/configs/ev64120_defconfig   2005/05/26 09:12:37     1.50
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:36 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:10 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/ev96100_defconfig 
linux/arch/mips/configs/ev96100_defconfig
--- linux/arch/mips/configs/ev96100_defconfig   2005/05/19 12:08:11     1.50
+++ linux/arch/mips/configs/ev96100_defconfig   2005/05/26 09:12:37     1.51
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:37 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:12 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/ip22_defconfig 
linux/arch/mips/configs/ip22_defconfig
--- linux/arch/mips/configs/ip22_defconfig      2005/05/19 12:08:11     1.59
+++ linux/arch/mips/configs/ip22_defconfig      2005/05/26 09:12:37     1.60
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:37 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:14 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/ip27_defconfig 
linux/arch/mips/configs/ip27_defconfig
--- linux/arch/mips/configs/ip27_defconfig      2005/05/19 12:08:11     1.63
+++ linux/arch/mips/configs/ip27_defconfig      2005/05/26 09:12:37     1.64
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:38 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:17 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/ip32_defconfig 
linux/arch/mips/configs/ip32_defconfig
--- linux/arch/mips/configs/ip32_defconfig      2005/05/19 12:08:11     1.53
+++ linux/arch/mips/configs/ip32_defconfig      2005/05/26 09:12:37     1.54
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:39 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:19 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/it8172_defconfig 
linux/arch/mips/configs/it8172_defconfig
--- linux/arch/mips/configs/it8172_defconfig    2005/05/19 12:08:11     1.49
+++ linux/arch/mips/configs/it8172_defconfig    2005/05/26 09:12:37     1.50
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:40 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:21 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/ivr_defconfig 
linux/arch/mips/configs/ivr_defconfig
--- linux/arch/mips/configs/ivr_defconfig       2005/05/19 12:08:11     1.49
+++ linux/arch/mips/configs/ivr_defconfig       2005/05/26 09:12:37     1.50
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:40 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:23 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/jaguar-atx_defconfig 
linux/arch/mips/configs/jaguar-atx_defconfig
--- linux/arch/mips/configs/jaguar-atx_defconfig        2005/05/19 12:08:11     
1.54
+++ linux/arch/mips/configs/jaguar-atx_defconfig        2005/05/26 09:12:37     
1.55
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:41 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:26 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/jmr3927_defconfig 
linux/arch/mips/configs/jmr3927_defconfig
--- linux/arch/mips/configs/jmr3927_defconfig   2005/05/19 12:08:11     1.50
+++ linux/arch/mips/configs/jmr3927_defconfig   2005/05/26 09:12:37     1.51
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:42 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:28 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/lasat200_defconfig 
linux/arch/mips/configs/lasat200_defconfig
--- linux/arch/mips/configs/lasat200_defconfig  2005/05/19 12:08:11     1.50
+++ linux/arch/mips/configs/lasat200_defconfig  2005/05/26 09:12:37     1.51
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:43 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:30 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/malta_defconfig 
linux/arch/mips/configs/malta_defconfig
--- linux/arch/mips/configs/malta_defconfig     2005/05/19 12:08:11     1.52
+++ linux/arch/mips/configs/malta_defconfig     2005/05/26 09:12:37     1.53
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:44 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:33 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/mpc30x_defconfig 
linux/arch/mips/configs/mpc30x_defconfig
--- linux/arch/mips/configs/mpc30x_defconfig    2005/05/19 12:08:11     1.54
+++ linux/arch/mips/configs/mpc30x_defconfig    2005/05/26 09:12:37     1.55
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:44 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:35 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/ocelot_3_defconfig 
linux/arch/mips/configs/ocelot_3_defconfig
--- linux/arch/mips/configs/ocelot_3_defconfig  2005/05/19 12:08:11     1.22
+++ linux/arch/mips/configs/ocelot_3_defconfig  2005/05/26 09:12:37     1.23
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:45 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:37 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/ocelot_c_defconfig 
linux/arch/mips/configs/ocelot_c_defconfig
--- linux/arch/mips/configs/ocelot_c_defconfig  2005/05/19 12:08:11     1.48
+++ linux/arch/mips/configs/ocelot_c_defconfig  2005/05/26 09:12:37     1.49
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:46 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:39 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/ocelot_defconfig 
linux/arch/mips/configs/ocelot_defconfig
--- linux/arch/mips/configs/ocelot_defconfig    2005/05/19 12:08:11     1.50
+++ linux/arch/mips/configs/ocelot_defconfig    2005/05/26 09:12:37     1.51
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:46 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:41 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/ocelot_g_defconfig 
linux/arch/mips/configs/ocelot_g_defconfig
--- linux/arch/mips/configs/ocelot_g_defconfig  2005/05/19 12:08:11     1.43
+++ linux/arch/mips/configs/ocelot_g_defconfig  2005/05/26 09:12:37     1.44
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:47 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:43 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/osprey_defconfig 
linux/arch/mips/configs/osprey_defconfig
--- linux/arch/mips/configs/osprey_defconfig    2005/05/19 12:08:11     1.49
+++ linux/arch/mips/configs/osprey_defconfig    2005/05/26 09:12:37     1.50
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:47 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:45 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/pb1100_defconfig 
linux/arch/mips/configs/pb1100_defconfig
--- linux/arch/mips/configs/pb1100_defconfig    2005/05/19 12:08:11     1.52
+++ linux/arch/mips/configs/pb1100_defconfig    2005/05/26 09:12:37     1.53
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:48 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:48 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/pb1500_defconfig 
linux/arch/mips/configs/pb1500_defconfig
--- linux/arch/mips/configs/pb1500_defconfig    2005/05/19 12:08:11     1.58
+++ linux/arch/mips/configs/pb1500_defconfig    2005/05/26 09:12:37     1.59
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:49 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:50 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/pb1550_defconfig 
linux/arch/mips/configs/pb1550_defconfig
--- linux/arch/mips/configs/pb1550_defconfig    2005/05/19 12:08:11     1.48
+++ linux/arch/mips/configs/pb1550_defconfig    2005/05/26 09:12:37     1.49
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:49 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:53 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/rm200_defconfig 
linux/arch/mips/configs/rm200_defconfig
--- linux/arch/mips/configs/rm200_defconfig     2005/05/19 12:08:11     1.59
+++ linux/arch/mips/configs/rm200_defconfig     2005/05/26 09:12:37     1.60
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:50 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:51:58 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/sb1250-swarm_defconfig 
linux/arch/mips/configs/sb1250-swarm_defconfig
--- linux/arch/mips/configs/sb1250-swarm_defconfig      2005/05/19 12:08:11     
1.56
+++ linux/arch/mips/configs/sb1250-swarm_defconfig      2005/05/26 09:12:37     
1.57
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:50 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:52:00 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/sead_defconfig 
linux/arch/mips/configs/sead_defconfig
--- linux/arch/mips/configs/sead_defconfig      2005/05/19 12:08:11     1.48
+++ linux/arch/mips/configs/sead_defconfig      2005/05/26 09:12:37     1.49
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:51 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:52:02 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/tb0226_defconfig 
linux/arch/mips/configs/tb0226_defconfig
--- linux/arch/mips/configs/tb0226_defconfig    2005/05/19 12:08:11     1.52
+++ linux/arch/mips/configs/tb0226_defconfig    2005/05/26 09:12:37     1.53
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:51 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:52:04 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/tb0229_defconfig 
linux/arch/mips/configs/tb0229_defconfig
--- linux/arch/mips/configs/tb0229_defconfig    2005/05/19 12:08:11     1.55
+++ linux/arch/mips/configs/tb0229_defconfig    2005/05/26 09:12:37     1.56
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:52 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:52:06 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/workpad_defconfig 
linux/arch/mips/configs/workpad_defconfig
--- linux/arch/mips/configs/workpad_defconfig   2005/05/19 12:08:11     1.52
+++ linux/arch/mips/configs/workpad_defconfig   2005/05/26 09:12:37     1.53
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:52 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:52:08 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/mips/configs/yosemite_defconfig 
linux/arch/mips/configs/yosemite_defconfig
--- linux/arch/mips/configs/yosemite_defconfig  2005/05/19 12:08:11     1.54
+++ linux/arch/mips/configs/yosemite_defconfig  2005/05/26 09:12:37     1.55
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc4
-# Wed May 11 17:20:53 2005
+# Linux kernel version: 2.6.12-rc5
+# Wed May 25 18:52:10 2005
 #
 CONFIG_MIPS=y
 
diff -urN linux/arch/ppc/kernel/head_44x.S linux/arch/ppc/kernel/head_44x.S
--- linux/arch/ppc/kernel/head_44x.S    2005/05/19 12:08:13     1.15
+++ linux/arch/ppc/kernel/head_44x.S    2005/05/26 09:12:38     1.16
@@ -330,8 +330,9 @@
        /* If we are faulting a kernel address, we have to use the
         * kernel page tables.
         */
-       andis.  r11, r10, 0x8000
-       beq     3f
+       lis     r11, TASK_SIZE@h
+       cmplw   r10, r11
+       blt+    3f
        lis     r11, swapper_pg_dir@h
        ori     r11, r11, swapper_pg_dir@l
 
@@ -464,8 +465,9 @@
        /* If we are faulting a kernel address, we have to use the
         * kernel page tables.
         */
-       andis.  r11, r10, 0x8000
-       beq     3f
+       lis     r11, TASK_SIZE@h
+       cmplw   r10, r11
+       blt+    3f
        lis     r11, swapper_pg_dir@h
        ori     r11, r11, swapper_pg_dir@l
 
@@ -533,8 +535,9 @@
        /* If we are faulting a kernel address, we have to use the
         * kernel page tables.
         */
-       andis.  r11, r10, 0x8000
-       beq     3f
+       lis     r11, TASK_SIZE@h
+       cmplw   r10, r11
+       blt+    3f
        lis     r11, swapper_pg_dir@h
        ori     r11, r11, swapper_pg_dir@l
 
diff -urN linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- linux/arch/ppc/kernel/setup.c       2005/05/19 12:08:13     1.82
+++ linux/arch/ppc/kernel/setup.c       2005/05/26 09:12:38     1.83
@@ -499,7 +499,7 @@
 {
        struct device_node *prom_stdout;
        char *name;
-       int offset;
+       int offset = 0;
 
        if (of_stdout_device == NULL)
                return -ENODEV;
@@ -753,6 +753,8 @@
        strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
        *cmdline_p = cmd_line;
 
+       parse_early_param();
+
        /* set up the bootmem stuff with available memory */
        do_init_bootmem();
        if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
diff -urN linux/arch/ppc/lib/string.S linux/arch/ppc/lib/string.S
--- linux/arch/ppc/lib/string.S 2005/02/07 02:54:35     1.17
+++ linux/arch/ppc/lib/string.S 2005/05/26 09:12:38     1.18
@@ -446,6 +446,7 @@
 #ifdef CONFIG_8xx
        /* Don't use prefetch on 8xx */
        mtctr   r0
+       li      r0,0
 53:    COPY_16_BYTES_WITHEX(0)
        bdnz    53b
 
@@ -564,7 +565,9 @@
 /* or write fault in cacheline loop */
 105:   li      r9,1
 92:    li      r3,LG_CACHELINE_BYTES
-       b       99f
+       mfctr   r8
+       add     r0,r0,r8
+       b       106f
 /* read fault in final word loop */
 108:   li      r9,0
        b       93f
@@ -585,7 +588,7 @@
  * r5 + (ctr << r3), and r9 is 0 for read or 1 for write.
  */
 99:    mfctr   r0
-       slw     r3,r0,r3
+106:   slw     r3,r0,r3
        add.    r3,r3,r5
        beq     120f                    /* shouldn't happen */
        cmpwi   0,r9,0
diff -urN linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- linux/arch/ppc/mm/init.c    2005/04/08 18:58:00     1.70
+++ linux/arch/ppc/mm/init.c    2005/05/26 09:12:38     1.71
@@ -179,6 +179,7 @@
        if (!have_of)
                FREESEC(openfirmware);
        printk("\n");
+       ppc_md.progress = NULL;
 #undef FREESEC
 }
 
diff -urN linux/arch/ppc/syslib/ipic.c linux/arch/ppc/syslib/ipic.c
--- linux/arch/ppc/syslib/ipic.c        2005/03/18 17:36:58     1.1
+++ linux/arch/ppc/syslib/ipic.c        2005/05/26 09:12:38     1.2
@@ -479,7 +479,7 @@
        temp = 0;
        for (i = 0 ; i < senses_count ; i++) {
                if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
-                       temp |= 1 << (16 - i);
+                       temp |= 1 << (15 - i);
                        if (i != 0)
                                irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 
1].status = 0;
                        else
diff -urN linux/arch/ppc/syslib/mpc83xx_devices.c 
linux/arch/ppc/syslib/mpc83xx_devices.c
--- linux/arch/ppc/syslib/mpc83xx_devices.c     2005/04/08 18:58:01     1.1
+++ linux/arch/ppc/syslib/mpc83xx_devices.c     2005/05/26 09:12:38     1.2
@@ -61,6 +61,7 @@
                .iotype         = UPIO_MEM,
                .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
        },
+       { },
 };
 
 struct platform_device ppc_sys_platform_devices[] = {
diff -urN linux/arch/ppc/syslib/mpc85xx_devices.c 
linux/arch/ppc/syslib/mpc85xx_devices.c
--- linux/arch/ppc/syslib/mpc85xx_devices.c     2005/04/08 18:58:01     1.1
+++ linux/arch/ppc/syslib/mpc85xx_devices.c     2005/05/26 09:12:38     1.2
@@ -61,6 +61,7 @@
                .iotype         = UPIO_MEM,
                .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | 
UPF_SHARE_IRQ,
        },
+       { },
 };
 
 struct platform_device ppc_sys_platform_devices[] = {
diff -urN linux/arch/ppc/syslib/open_pic.c linux/arch/ppc/syslib/open_pic.c
--- linux/arch/ppc/syslib/open_pic.c    2005/04/29 11:15:03     1.22
+++ linux/arch/ppc/syslib/open_pic.c    2005/05/26 09:12:38     1.23
@@ -557,12 +557,10 @@
  */
 void openpic_cause_IPI(u_int ipi, cpumask_t cpumask)
 {
-       cpumask_t phys;
        DECL_THIS_CPU;
 
        CHECK_THIS_CPU;
        check_arg_ipi(ipi);
-       phys = physmask(cpumask);
        openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi),
                      cpus_addr(physmask(cpumask))[0]);
 }
diff -urN linux/arch/ppc64/kernel/pmac_smp.c linux/arch/ppc64/kernel/pmac_smp.c
--- linux/arch/ppc64/kernel/pmac_smp.c  2005/03/18 17:36:59     1.8
+++ linux/arch/ppc64/kernel/pmac_smp.c  2005/05/26 09:12:38     1.9
@@ -68,6 +68,7 @@
 
 static void (*pmac_tb_freeze)(int freeze);
 static struct device_node *pmac_tb_clock_chip_host;
+static u8 pmac_tb_pulsar_addr;
 static DEFINE_SPINLOCK(timebase_lock);
 static unsigned long timebase;
 
@@ -106,12 +107,9 @@
        u8 data;
        int rc;
 
-       /* Strangely, the device-tree says address is 0xd2, but darwin
-        * accesses 0xd0 ...
-        */
        pmac_low_i2c_setmode(pmac_tb_clock_chip_host, 
pmac_low_i2c_mode_combined);
        rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
-                              0xd4 | pmac_low_i2c_read,
+                              pmac_tb_pulsar_addr | pmac_low_i2c_read,
                               0x2e, &data, 1);
        if (rc != 0)
                goto bail;
@@ -120,7 +118,7 @@
 
        pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub);
        rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
-                              0xd4 | pmac_low_i2c_write,
+                              pmac_tb_pulsar_addr | pmac_low_i2c_write,
                               0x2e, &data, 1);
  bail:
        if (rc != 0) {
@@ -185,6 +183,12 @@
        if (ncpus <= 1)
                return 1;
 
+       /* HW sync only on these platforms */
+       if (!machine_is_compatible("PowerMac7,2") &&
+           !machine_is_compatible("PowerMac7,3") &&
+           !machine_is_compatible("RackMac3,1"))
+               goto nohwsync;
+
        /* Look for the clock chip */
        for (cc = NULL; (cc = of_find_node_by_name(cc, "i2c-hwclock")) != 
NULL;) {
                struct device_node *p = of_get_parent(cc);
@@ -198,11 +202,18 @@
                        goto next;
                switch (*reg) {
                case 0xd2:
-                       pmac_tb_freeze = smp_core99_cypress_tb_freeze;
-                       printk(KERN_INFO "Timebase clock is Cypress chip\n");
+                       if (device_is_compatible(cc, "pulsar-legacy-slewing")) {
+                               pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
+                               pmac_tb_pulsar_addr = 0xd2;
+                               printk(KERN_INFO "Timebase clock is Pulsar 
chip\n");
+                       } else if (device_is_compatible(cc, "cy28508")) {
+                               pmac_tb_freeze = smp_core99_cypress_tb_freeze;
+                               printk(KERN_INFO "Timebase clock is Cypress 
chip\n");
+                       }
                        break;
                case 0xd4:
                        pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
+                       pmac_tb_pulsar_addr = 0xd4;
                        printk(KERN_INFO "Timebase clock is Pulsar chip\n");
                        break;
                }
@@ -210,12 +221,15 @@
                        pmac_tb_clock_chip_host = p;
                        smp_ops->give_timebase = smp_core99_give_timebase;
                        smp_ops->take_timebase = smp_core99_take_timebase;
+                       of_node_put(cc);
+                       of_node_put(p);
                        break;
                }
        next:
                of_node_put(p);
        }
 
+ nohwsync:
        mpic_request_ipis();
 
        return ncpus;
diff -urN linux/arch/ppc64/kernel/prom_init.c 
linux/arch/ppc64/kernel/prom_init.c
--- linux/arch/ppc64/kernel/prom_init.c 2005/05/19 12:08:14     1.11
+++ linux/arch/ppc64/kernel/prom_init.c 2005/05/26 09:12:38     1.12
@@ -1750,7 +1750,44 @@
        prom_printf("Device tree struct  0x%x -> 0x%x\n",
                    RELOC(dt_struct_start), RELOC(dt_struct_end));
 
- }
+}
+
+
+static void __init fixup_device_tree(void)
+{
+       unsigned long offset = reloc_offset();
+       phandle u3, i2c, mpic;
+       u32 u3_rev;
+       u32 interrupts[2];
+       u32 parent;
+
+       /* Some G5s have a missing interrupt definition, fix it up here */
+       u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
+       if ((long)u3 <= 0)
+               return;
+       i2c = call_prom("finddevice", 1, 1, 
ADDR("/u3@0,f8000000/i2c@f8001000"));
+       if ((long)i2c <= 0)
+               return;
+       mpic = call_prom("finddevice", 1, 1, 
ADDR("/u3@0,f8000000/mpic@f8040000"));
+       if ((long)mpic <= 0)
+               return;
+
+       /* check if proper rev of u3 */
+       if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) <= 0)
+               return;
+       if (u3_rev != 0x35)
+               return;
+       /* does it need fixup ? */
+       if (prom_getproplen(i2c, "interrupts") > 0)
+               return;
+       /* interrupt on this revision of u3 is number 0 and level */
+       interrupts[0] = 0;
+       interrupts[1] = 1;
+       prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts));
+       parent = (u32)mpic;
+       prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent));
+}
+
 
 static void __init prom_find_boot_cpu(void)
 {
@@ -1920,6 +1957,11 @@
        }
 
        /*
+        * Fixup any known bugs in the device-tree
+        */
+       fixup_device_tree();
+
+       /*
         * Now finally create the flattened device-tree
         */
                prom_printf("copying OF device tree ...\n");
diff -urN linux/arch/sparc64/kernel/pci_iommu.c 
linux/arch/sparc64/kernel/pci_iommu.c
--- linux/arch/sparc64/kernel/pci_iommu.c       2004/11/15 11:49:21     1.17
+++ linux/arch/sparc64/kernel/pci_iommu.c       2005/05/26 09:12:38     1.18
@@ -8,6 +8,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/delay.h>
 
 #include <asm/pbm.h>
 
@@ -379,6 +380,56 @@
        return PCI_DMA_ERROR_CODE;
 }
 
+static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu 
*iommu, u32 vaddr, unsigned long ctx, unsigned long npages)
+{
+       int limit;
+
+       PCI_STC_FLUSHFLAG_INIT(strbuf);
+       if (strbuf->strbuf_ctxflush &&
+           iommu->iommu_ctxflush) {
+               unsigned long matchreg, flushreg;
+
+               flushreg = strbuf->strbuf_ctxflush;
+               matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
+
+               limit = 100000;
+               pci_iommu_write(flushreg, ctx);
+               for(;;) {
+                       if (((long)pci_iommu_read(matchreg)) >= 0L)
+                               break;
+                       limit--;
+                       if (!limit)
+                               break;
+                       udelay(1);
+               }
+               if (!limit)
+                       printk(KERN_WARNING "pci_strbuf_flush: ctx flush "
+                              "timeout vaddr[%08x] ctx[%lx]\n",
+                              vaddr, ctx);
+       } else {
+               unsigned long i;
+
+               for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
+                       pci_iommu_write(strbuf->strbuf_pflush, vaddr);
+       }
+
+       pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
+       (void) pci_iommu_read(iommu->write_complete_reg);
+
+       limit = 100000;
+       while (!PCI_STC_FLUSHFLAG_SET(strbuf)) {
+               limit--;
+               if (!limit)
+                       break;
+               udelay(1);
+               membar("#LoadLoad");
+       }
+       if (!limit)
+               printk(KERN_WARNING "pci_strbuf_flush: flushflag timeout "
+                      "vaddr[%08x] ctx[%lx] npages[%ld]\n",
+                      vaddr, ctx, npages);
+}
+
 /* Unmap a single streaming mode DMA translation. */
 void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, 
int direction)
 {
@@ -386,7 +437,7 @@
        struct pci_iommu *iommu;
        struct pci_strbuf *strbuf;
        iopte_t *base;
-       unsigned long flags, npages, i, ctx;
+       unsigned long flags, npages, ctx;
 
        if (direction == PCI_DMA_NONE)
                BUG();
@@ -414,29 +465,8 @@
                ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
 
        /* Step 1: Kick data out of streaming buffers if necessary. */
-       if (strbuf->strbuf_enabled) {
-               u32 vaddr = bus_addr;
-
-               PCI_STC_FLUSHFLAG_INIT(strbuf);
-               if (strbuf->strbuf_ctxflush &&
-                   iommu->iommu_ctxflush) {
-                       unsigned long matchreg, flushreg;
-
-                       flushreg = strbuf->strbuf_ctxflush;
-                       matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
-                       do {
-                               pci_iommu_write(flushreg, ctx);
-                       } while(((long)pci_iommu_read(matchreg)) < 0L);
-               } else {
-                       for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
-                               pci_iommu_write(strbuf->strbuf_pflush, vaddr);
-               }
-
-               pci_iommu_write(strbuf->strbuf_fsync, 
strbuf->strbuf_flushflag_pa);
-               (void) pci_iommu_read(iommu->write_complete_reg);
-               while (!PCI_STC_FLUSHFLAG_SET(strbuf))
-                       membar("#LoadLoad");
-       }
+       if (strbuf->strbuf_enabled)
+               pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
 
        /* Step 2: Clear out first TSB entry. */
        iopte_make_dummy(iommu, base);
@@ -647,29 +677,8 @@
                ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
 
        /* Step 1: Kick data out of streaming buffers if necessary. */
-       if (strbuf->strbuf_enabled) {
-               u32 vaddr = (u32) bus_addr;
-
-               PCI_STC_FLUSHFLAG_INIT(strbuf);
-               if (strbuf->strbuf_ctxflush &&
-                   iommu->iommu_ctxflush) {
-                       unsigned long matchreg, flushreg;
-
-                       flushreg = strbuf->strbuf_ctxflush;
-                       matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
-                       do {
-                               pci_iommu_write(flushreg, ctx);
-                       } while(((long)pci_iommu_read(matchreg)) < 0L);
-               } else {
-                       for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
-                               pci_iommu_write(strbuf->strbuf_pflush, vaddr);
-               }
-
-               pci_iommu_write(strbuf->strbuf_fsync, 
strbuf->strbuf_flushflag_pa);
-               (void) pci_iommu_read(iommu->write_complete_reg);
-               while (!PCI_STC_FLUSHFLAG_SET(strbuf))
-                       membar("#LoadLoad");
-       }
+       if (strbuf->strbuf_enabled)
+               pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
 
        /* Step 2: Clear out first TSB entry. */
        iopte_make_dummy(iommu, base);
@@ -715,28 +724,7 @@
        }
 
        /* Step 2: Kick data out of streaming buffers. */
-       PCI_STC_FLUSHFLAG_INIT(strbuf);
-       if (iommu->iommu_ctxflush &&
-           strbuf->strbuf_ctxflush) {
-               unsigned long matchreg, flushreg;
-
-               flushreg = strbuf->strbuf_ctxflush;
-               matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
-               do {
-                       pci_iommu_write(flushreg, ctx);
-               } while(((long)pci_iommu_read(matchreg)) < 0L);
-       } else {
-               unsigned long i;
-
-               for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE)
-                       pci_iommu_write(strbuf->strbuf_pflush, bus_addr);
-       }
-
-       /* Step 3: Perform flush synchronization sequence. */
-       pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
-       (void) pci_iommu_read(iommu->write_complete_reg);
-       while (!PCI_STC_FLUSHFLAG_SET(strbuf))
-               membar("#LoadLoad");
+       pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
 
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
@@ -749,7 +737,8 @@
        struct pcidev_cookie *pcp;
        struct pci_iommu *iommu;
        struct pci_strbuf *strbuf;
-       unsigned long flags, ctx;
+       unsigned long flags, ctx, npages, i;
+       u32 bus_addr;
 
        pcp = pdev->sysdata;
        iommu = pcp->pbm->iommu;
@@ -772,36 +761,14 @@
        }
 
        /* Step 2: Kick data out of streaming buffers. */
-       PCI_STC_FLUSHFLAG_INIT(strbuf);
-       if (iommu->iommu_ctxflush &&
-           strbuf->strbuf_ctxflush) {
-               unsigned long matchreg, flushreg;
-
-               flushreg = strbuf->strbuf_ctxflush;
-               matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
-               do {
-                       pci_iommu_write(flushreg, ctx);
-               } while (((long)pci_iommu_read(matchreg)) < 0L);
-       } else {
-               unsigned long i, npages;
-               u32 bus_addr;
-
-               bus_addr = sglist[0].dma_address & IO_PAGE_MASK;
-
-               for(i = 1; i < nelems; i++)
-                       if (!sglist[i].dma_length)
-                               break;
-               i--;
-               npages = (IO_PAGE_ALIGN(sglist[i].dma_address + 
sglist[i].dma_length) - bus_addr) >> IO_PAGE_SHIFT;
-               for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE)
-                       pci_iommu_write(strbuf->strbuf_pflush, bus_addr);
-       }
-
-       /* Step 3: Perform flush synchronization sequence. */
-       pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
-       (void) pci_iommu_read(iommu->write_complete_reg);
-       while (!PCI_STC_FLUSHFLAG_SET(strbuf))
-               membar("#LoadLoad");
+       bus_addr = sglist[0].dma_address & IO_PAGE_MASK;
+       for(i = 1; i < nelems; i++)
+               if (!sglist[i].dma_length)
+                       break;
+       i--;
+       npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length)
+                 - bus_addr) >> IO_PAGE_SHIFT;
+       pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
 
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
diff -urN linux/arch/sparc64/kernel/sbus.c linux/arch/sparc64/kernel/sbus.c
--- linux/arch/sparc64/kernel/sbus.c    2004/08/06 00:33:24     1.21
+++ linux/arch/sparc64/kernel/sbus.c    2005/05/26 09:12:38     1.22
@@ -117,19 +117,34 @@
 
 #define STRBUF_TAG_VALID       0x02UL
 
-static void strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long 
npages)
+static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned 
long npages)
 {
+       unsigned long n;
+       int limit;
+
        iommu->strbuf_flushflag = 0UL;
-       while (npages--)
-               upa_writeq(base + (npages << IO_PAGE_SHIFT),
+       n = npages;
+       while (n--)
+               upa_writeq(base + (n << IO_PAGE_SHIFT),
                           iommu->strbuf_regs + STRBUF_PFLUSH);
 
        /* Whoopee cushion! */
        upa_writeq(__pa(&iommu->strbuf_flushflag),
                   iommu->strbuf_regs + STRBUF_FSYNC);
        upa_readq(iommu->sbus_control_reg);
-       while (iommu->strbuf_flushflag == 0UL)
+
+       limit = 100000;
+       while (iommu->strbuf_flushflag == 0UL) {
+               limit--;
+               if (!limit)
+                       break;
+               udelay(1);
                membar("#LoadLoad");
+       }
+       if (!limit)
+               printk(KERN_WARNING "sbus_strbuf_flush: flushflag timeout "
+                      "vaddr[%08x] npages[%ld]\n",
+                      base, npages);
 }
 
 static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned 
long npages)
@@ -406,7 +421,7 @@
 
        spin_lock_irqsave(&iommu->lock, flags);
        free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT);
-       strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT);
+       sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT);
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
@@ -569,7 +584,7 @@
        iommu = sdev->bus->iommu;
        spin_lock_irqsave(&iommu->lock, flags);
        free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT);
-       strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT);
+       sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT);
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
@@ -581,7 +596,7 @@
        size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK));
 
        spin_lock_irqsave(&iommu->lock, flags);
-       strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT);
+       sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT);
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
@@ -605,7 +620,7 @@
        size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base;
 
        spin_lock_irqsave(&iommu->lock, flags);
-       strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT);
+       sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT);
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
diff -urN linux/arch/um/Kconfig_x86_64 linux/arch/um/Kconfig_x86_64
--- linux/arch/um/Kconfig_x86_64        2005/05/19 12:08:16     1.3
+++ linux/arch/um/Kconfig_x86_64        2005/05/26 09:12:39     1.4
@@ -6,6 +6,10 @@
        bool
        default y
 
+config TOP_ADDR
+       hex
+       default 0x80000000
+
 config 3_LEVEL_PGTABLES
        bool
        default y
diff -urN linux/arch/um/drivers/chan_kern.c linux/arch/um/drivers/chan_kern.c
--- linux/arch/um/drivers/chan_kern.c   2005/05/19 12:08:16     1.11
+++ linux/arch/um/drivers/chan_kern.c   2005/05/26 09:12:39     1.12
@@ -20,9 +20,17 @@
 #include "os.h"
 
 #ifdef CONFIG_NOCONFIG_CHAN
+
+/* The printk's here are wrong because we are complaining that there is no
+ * output device, but printk is printing to that output device.  The user will
+ * never see the error.  printf would be better, except it can't run on a
+ * kernel stack because it will overflow it.
+ * Use printk for now since that will avoid crashing.
+ */
+
 static void *not_configged_init(char *str, int device, struct chan_opts *opts)
 {
-       printf(KERN_ERR "Using a channel type which is configured out of "
+       printk(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
        return(NULL);
 }
@@ -30,27 +38,27 @@
 static int not_configged_open(int input, int output, int primary, void *data,
                              char **dev_out)
 {
-       printf(KERN_ERR "Using a channel type which is configured out of "
+       printk(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
        return(-ENODEV);
 }
 
 static void not_configged_close(int fd, void *data)
 {
-       printf(KERN_ERR "Using a channel type which is configured out of "
+       printk(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
 }
 
 static int not_configged_read(int fd, char *c_out, void *data)
 {
-       printf(KERN_ERR "Using a channel type which is configured out of "
+       printk(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
        return(-EIO);
 }
 
 static int not_configged_write(int fd, const char *buf, int len, void *data)
 {
-       printf(KERN_ERR "Using a channel type which is configured out of "
+       printk(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
        return(-EIO);
 }
@@ -58,7 +66,7 @@
 static int not_configged_console_write(int fd, const char *buf, int len,
                                       void *data)
 {
-       printf(KERN_ERR "Using a channel type which is configured out of "
+       printk(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
        return(-EIO);
 }
@@ -66,7 +74,7 @@
 static int not_configged_window_size(int fd, void *data, unsigned short *rows,
                                     unsigned short *cols)
 {
-       printf(KERN_ERR "Using a channel type which is configured out of "
+       printk(KERN_ERR "Using a channel type which is configured out of "
               "UML\n");
        return(-ENODEV);
 }
diff -urN linux/arch/um/drivers/mcast_kern.c linux/arch/um/drivers/mcast_kern.c
--- linux/arch/um/drivers/mcast_kern.c  2003/06/22 23:09:50     1.5
+++ linux/arch/um/drivers/mcast_kern.c  2005/05/26 09:12:39     1.6
@@ -73,7 +73,6 @@
        struct mcast_init *init = data;
        char *port_str = NULL, *ttl_str = NULL, *remain;
        char *last;
-       int n;
 
        *init = ((struct mcast_init)
                { .addr         = "239.192.168.1",
@@ -89,13 +88,12 @@
        }
        
        if(port_str != NULL){
-               n = simple_strtoul(port_str, &last, 10);
+               init->port = simple_strtoul(port_str, &last, 10);
                if((*last != '\0') || (last == port_str)){
                        printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", 
                               port_str);
                        return(0);
                }
-               init->port = htons(n);
        }
 
        if(ttl_str != NULL){
diff -urN linux/arch/um/drivers/mcast_user.c linux/arch/um/drivers/mcast_user.c
--- linux/arch/um/drivers/mcast_user.c  2004/09/19 12:30:07     1.3
+++ linux/arch/um/drivers/mcast_user.c  2005/05/26 09:12:39     1.4
@@ -38,7 +38,7 @@
        }
        sin->sin_family = AF_INET;
        sin->sin_addr.s_addr = in_aton(addr);
-       sin->sin_port = port;
+       sin->sin_port = htons(port);
        return(sin);
 }
 
@@ -55,28 +55,25 @@
        struct mcast_data *pri = data;
        struct sockaddr_in *sin = pri->mcast_addr;
        struct ip_mreq mreq;
-       int fd, yes = 1;
+       int fd = -EINVAL, yes = 1, err = -EINVAL;;
 
 
-       if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) {
-               fd = -EINVAL;
+       if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0))
                goto out;
-       }
 
        fd = socket(AF_INET, SOCK_DGRAM, 0);
+
        if (fd < 0){
                printk("mcast_open : data socket failed, errno = %d\n", 
                       errno);
-               fd = -ENOMEM;
+               fd = -errno;
                goto out;
        }
 
        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
                printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
                        errno);
-               os_close_file(fd);
-               fd = -EINVAL;
-               goto out;
+               goto out_close;
        }
 
        /* set ttl according to config */
@@ -84,26 +81,20 @@
                       sizeof(pri->ttl)) < 0) {
                printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
                        errno);
-               os_close_file(fd);
-               fd = -EINVAL;
-               goto out;
+               goto out_close;
        }
 
        /* set LOOP, so data does get fed back to local sockets */
        if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
                printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
                        errno);
-               os_close_file(fd);
-               fd = -EINVAL;
-               goto out;
+               goto out_close;
        }
 
        /* bind socket to mcast address */
        if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
                printk("mcast_open : data bind failed, errno = %d\n", errno);
-               os_close_file(fd);
-               fd = -EINVAL;
-               goto out;
+               goto out_close;
        }               
        
        /* subscribe to the multicast group */
@@ -117,12 +108,15 @@
                       "interface on the host.\n");
                printk("eth0 should be configured in order to use the "
                       "multicast transport.\n");
-               os_close_file(fd);
-               fd = -EINVAL;
+                goto out_close;
        }
 
  out:
-       return(fd);
+       return fd;
+
+ out_close:
+        os_close_file(fd);
+        return err;
 }
 
 static void mcast_close(int fd, void *data)
@@ -164,14 +158,3 @@
        .delete_address = NULL,
        .max_packet     = MAX_PACKET - ETH_HEADER_OTHER
 };
-
-/*
- * 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:
- */
diff -urN linux/arch/um/drivers/ubd_kern.c linux/arch/um/drivers/ubd_kern.c
--- linux/arch/um/drivers/ubd_kern.c    2005/05/19 12:08:16     1.22
+++ linux/arch/um/drivers/ubd_kern.c    2005/05/26 09:12:39     1.23
@@ -55,7 +55,7 @@
 #include "mem_kern.h"
 #include "cow.h"
 
-enum ubd_req { UBD_READ, UBD_WRITE, UBD_MMAP };
+enum ubd_req { UBD_READ, UBD_WRITE };
 
 struct io_thread_req {
        enum ubd_req op;
@@ -68,8 +68,6 @@
        unsigned long sector_mask;
        unsigned long long cow_offset;
        unsigned long bitmap_words[2];
-       int map_fd;
-       unsigned long long map_offset;
        int error;
 };
 
@@ -122,10 +120,6 @@
 
 #define MAX_DEV (8)
 
-/* Changed in early boot */
-static int ubd_do_mmap = 0;
-#define UBD_MMAP_BLOCK_SIZE PAGE_SIZE
-
 static struct block_device_operations ubd_blops = {
         .owner         = THIS_MODULE,
         .open          = ubd_open,
@@ -175,12 +169,6 @@
        int no_cow;
        struct cow cow;
        struct platform_device pdev;
-
-       int map_writes;
-       int map_reads;
-       int nomap_writes;
-       int nomap_reads;
-       int write_maps;
 };
 
 #define DEFAULT_COW { \
@@ -200,11 +188,6 @@
        .openflags =            OPEN_FLAGS, \
         .no_cow =               0, \
         .cow =                 DEFAULT_COW, \
-       .map_writes             = 0, \
-       .map_reads              = 0, \
-       .nomap_writes           = 0, \
-       .nomap_reads            = 0, \
-       .write_maps             = 0, \
 }
 
 struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
@@ -314,13 +297,6 @@
                int major;
 
                str++;
-               if(!strcmp(str, "mmap")){
-                       CHOOSE_MODE(printk("mmap not supported by the ubd "
-                                          "driver in tt mode\n"),
-                                   ubd_do_mmap = 1);
-                       return(0);
-               }
-
                if(!strcmp(str, "sync")){
                        global_openflags = of_sync(global_openflags);
                        return(0);
@@ -524,7 +500,7 @@
 {
        struct io_thread_req req;
        struct request *rq = elv_next_request(ubd_queue);
-       int n, err;
+       int n;
 
        do_ubd = NULL;
        intr_count++;
@@ -538,19 +514,6 @@
                return;
        }
         
-       if((req.op != UBD_MMAP) &&
-          ((req.offset != ((__u64) (rq->sector)) << 9) ||
-           (req.length != (rq->current_nr_sectors) << 9)))
-               panic("I/O op mismatch");
-       
-       if(req.map_fd != -1){
-               err = physmem_subst_mapping(req.buffer, req.map_fd,
-                                           req.map_offset, 1);
-               if(err)
-                       printk("ubd_handler - physmem_subst_mapping failed, "
-                              "err = %d\n", -err);
-       }
-
        ubd_finish(rq, req.error);
        reactivate_fd(thread_fd, UBD_IRQ);      
        do_ubd_request(ubd_queue);
@@ -583,14 +546,10 @@
 
 static void ubd_close(struct ubd *dev)
 {
-       if(ubd_do_mmap)
-               physmem_forget_descriptor(dev->fd);
        os_close_file(dev->fd);
        if(dev->cow.file == NULL)
                return;
 
-       if(ubd_do_mmap)
-               physmem_forget_descriptor(dev->cow.fd);
        os_close_file(dev->cow.fd);
        vfree(dev->cow.bitmap);
        dev->cow.bitmap = NULL;
@@ -1010,94 +969,13 @@
                           req->bitmap_words, bitmap_len);
 }
 
-static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset)
-{
-       __u64 sector;
-       unsigned char *bitmap;
-       int bit, i;
-
-       /* mmap must have been requested on the command line */
-       if(!ubd_do_mmap)
-               return(-1);
-
-       /* The buffer must be page aligned */
-       if(((unsigned long) req->buffer % UBD_MMAP_BLOCK_SIZE) != 0)
-               return(-1);
-
-       /* The request must be a page long */
-       if((req->current_nr_sectors << 9) != PAGE_SIZE)
-               return(-1);
-
-       if(dev->cow.file == NULL)
-               return(dev->fd);
-
-       sector = offset >> 9;
-       bitmap = (unsigned char *) dev->cow.bitmap;
-       bit = ubd_test_bit(sector, bitmap);
-
-       for(i = 1; i < req->current_nr_sectors; i++){
-               if(ubd_test_bit(sector + i, bitmap) != bit)
-                       return(-1);
-       }
-
-       if(bit || (rq_data_dir(req) == WRITE))
-               offset += dev->cow.data_offset;
-
-       /* The data on disk must be page aligned */
-       if((offset % UBD_MMAP_BLOCK_SIZE) != 0)
-               return(-1);
-
-       return(bit ? dev->fd : dev->cow.fd);
-}
-
-static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset,
-                               struct request *req,
-                               struct io_thread_req *io_req)
-{
-       int err;
-
-       if(rq_data_dir(req) == WRITE){
-               /* Writes are almost no-ops since the new data is already in the
-                * host page cache
-                */
-               dev->map_writes++;
-               if(dev->cow.file != NULL)
-                       cowify_bitmap(io_req->offset, io_req->length,
-                                     &io_req->sector_mask, &io_req->cow_offset,
-                                     dev->cow.bitmap, dev->cow.bitmap_offset,
-                                     io_req->bitmap_words,
-                                     dev->cow.bitmap_len);
-       }
-       else {
-               int w;
-
-               if((dev->cow.file != NULL) && (fd == dev->cow.fd))
-                       w = 0;
-               else w = dev->openflags.w;
-
-               if((dev->cow.file != NULL) && (fd == dev->fd))
-                       offset += dev->cow.data_offset;
-
-               err = physmem_subst_mapping(req->buffer, fd, offset, w);
-               if(err){
-                       printk("physmem_subst_mapping failed, err = %d\n",
-                              -err);
-                       return(1);
-               }
-               dev->map_reads++;
-       }
-       io_req->op = UBD_MMAP;
-       io_req->buffer = req->buffer;
-       return(0);
-}
-
 /* Called with ubd_io_lock held */
 static int prepare_request(struct request *req, struct io_thread_req *io_req)
 {
        struct gendisk *disk = req->rq_disk;
        struct ubd *dev = disk->private_data;
        __u64 offset;
-       int len, fd;
+       int len;
 
        if(req->rq_status == RQ_INACTIVE) return(1);
 
@@ -1114,34 +992,12 @@
 
        io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
        io_req->fds[1] = dev->fd;
-       io_req->map_fd = -1;
        io_req->cow_offset = -1;
        io_req->offset = offset;
        io_req->length = len;
        io_req->error = 0;
        io_req->sector_mask = 0;
 
-       fd = mmap_fd(req, dev, io_req->offset);
-       if(fd > 0){
-               /* If mmapping is otherwise OK, but the first access to the
-                * page is a write, then it's not mapped in yet.  So we have
-                * to write the data to disk first, then we can map the disk
-                * page in and continue normally from there.
-                */
-               if((rq_data_dir(req) == WRITE) && !is_remapped(req->buffer)){
-                       io_req->map_fd = dev->fd;
-                       io_req->map_offset = io_req->offset +
-                               dev->cow.data_offset;
-                       dev->write_maps++;
-               }
-               else return(prepare_mmap_request(dev, fd, io_req->offset, req,
-                                                io_req));
-       }
-
-       if(rq_data_dir(req) == READ)
-               dev->nomap_reads++;
-       else dev->nomap_writes++;
-
        io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
        io_req->offsets[0] = 0;
        io_req->offsets[1] = dev->cow.data_offset;
@@ -1229,143 +1085,6 @@
        return(-EINVAL);
 }
 
-static int ubd_check_remapped(int fd, unsigned long address, int is_write,
-                             __u64 offset)
-{
-       __u64 bitmap_offset;
-       unsigned long new_bitmap[2];
-       int i, err, n;
-
-       /* If it's not a write access, we can't do anything about it */
-       if(!is_write)
-               return(0);
-
-       /* We have a write */
-       for(i = 0; i < sizeof(ubd_dev) / sizeof(ubd_dev[0]); i++){
-               struct ubd *dev = &ubd_dev[i];
-
-               if((dev->fd != fd) && (dev->cow.fd != fd))
-                       continue;
-
-               /* It's a write to a ubd device */
-
-               /* This should be impossible now */
-               if(!dev->openflags.w){
-                       /* It's a write access on a read-only device - probably
-                        * shouldn't happen.  If the kernel is trying to change
-                        * something with no intention of writing it back out,
-                        * then this message will clue us in that this needs
-                        * fixing
-                        */
-                       printk("Write access to mapped page from readonly ubd "
-                              "device %d\n", i);
-                       return(0);
-               }
-
-               /* It's a write to a writeable ubd device - it must be COWed
-                * because, otherwise, the page would have been mapped in
-                * writeable
-                */
-
-               if(!dev->cow.file)
-                       panic("Write fault on writeable non-COW ubd device %d",
-                             i);
-
-               /* It should also be an access to the backing file since the
-                * COW pages should be mapped in read-write
-                */
-
-               if(fd == dev->fd)
-                       panic("Write fault on a backing page of ubd "
-                             "device %d\n", i);
-
-               /* So, we do the write, copying the backing data to the COW
-                * file...
-                */
-
-               err = os_seek_file(dev->fd, offset + dev->cow.data_offset);
-               if(err < 0)
-                       panic("Couldn't seek to %lld in COW file of ubd "
-                             "device %d, err = %d",
-                             offset + dev->cow.data_offset, i, -err);
-
-               n = os_write_file(dev->fd, (void *) address, PAGE_SIZE);
-               if(n != PAGE_SIZE)
-                       panic("Couldn't copy data to COW file of ubd "
-                             "device %d, err = %d", i, -n);
-
-               /* ... updating the COW bitmap... */
-
-               cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset,
-                             dev->cow.bitmap, dev->cow.bitmap_offset,
-                             new_bitmap, dev->cow.bitmap_len);
-
-               err = os_seek_file(dev->fd, bitmap_offset);
-               if(err < 0)
-                       panic("Couldn't seek to %lld in COW file of ubd "
-                             "device %d, err = %d", bitmap_offset, i, -err);
-
-               n = os_write_file(dev->fd, new_bitmap, sizeof(new_bitmap));
-               if(n != sizeof(new_bitmap))
-                       panic("Couldn't update bitmap  of ubd device %d, "
-                             "err = %d", i, -n);
-
-               /* Maybe we can map the COW page in, and maybe we can't.  If
-                * it is a pre-V3 COW file, we can't, since the alignment will
-                * be wrong.  If it is a V3 or later COW file which has been
-                * moved to a system with a larger page size, then maybe we
-                * can't, depending on the exact location of the page.
-                */
-
-               offset += dev->cow.data_offset;
-
-               /* Remove the remapping, putting the original anonymous page
-                * back.  If the COW file can be mapped in, that is done.
-                * Otherwise, the COW page is read in.
-                */
-
-               if(!physmem_remove_mapping((void *) address))
-                       panic("Address 0x%lx not remapped by ubd device %d",
-                             address, i);
-               if((offset % UBD_MMAP_BLOCK_SIZE) == 0)
-                       physmem_subst_mapping((void *) address, dev->fd,
-                                             offset, 1);
-               else {
-                       err = os_seek_file(dev->fd, offset);
-                       if(err < 0)
-                               panic("Couldn't seek to %lld in COW file of "
-                                     "ubd device %d, err = %d", offset, i,
-                                     -err);
-
-                       n = os_read_file(dev->fd, (void *) address, PAGE_SIZE);
-                       if(n != PAGE_SIZE)
-                               panic("Failed to read page from offset %llx of "
-                                     "COW file of ubd device %d, err = %d",
-                                     offset, i, -n);
-               }
-
-               return(1);
-       }
-
-       /* It's not a write on a ubd device */
-       return(0);
-}
-
-static struct remapper ubd_remapper = {
-       .list   = LIST_HEAD_INIT(ubd_remapper.list),
-       .proc   = ubd_check_remapped,
-};
-
-static int ubd_remapper_setup(void)
-{
-       if(ubd_do_mmap)
-               register_remapper(&ubd_remapper);
-
-       return(0);
-}
-
-__initcall(ubd_remapper_setup);
-
 static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
 {
        struct uml_stat buf1, buf2;
@@ -1568,15 +1287,6 @@
        int err;
        __u64 off;
 
-       if(req->op == UBD_MMAP){
-               /* Touch the page to force the host to do any necessary IO to
-                * get it into memory
-                */
-               n = *((volatile int *) req->buffer);
-               req->error = update_bitmap(req);
-               return;
-       }
-
        nsectors = req->length / req->sectorsize;
        start = 0;
        do {
diff -urN linux/arch/um/include/sysdep-i386/ptrace.h 
linux/arch/um/include/sysdep-i386/ptrace.h
--- linux/arch/um/include/sysdep-i386/ptrace.h  2005/05/19 12:08:17     1.7
+++ linux/arch/um/include/sysdep-i386/ptrace.h  2005/05/26 09:12:39     1.8
@@ -31,7 +31,6 @@
 #ifdef UML_CONFIG_MODE_SKAS
 
 #include "skas_ptregs.h"
-#include "sysdep/faultinfo.h"
 
 #define REGS_IP(r) ((r)[HOST_IP])
 #define REGS_SP(r) ((r)[HOST_SP])
@@ -59,6 +58,7 @@
 #define PTRACE_SYSEMU_SINGLESTEP 32
 #endif
 
+#include "sysdep/faultinfo.h"
 #include "choose-mode.h"
 
 union uml_pt_regs {
diff -urN linux/arch/um/include/sysdep-x86_64/checksum.h 
linux/arch/um/include/sysdep-x86_64/checksum.h
--- linux/arch/um/include/sysdep-x86_64/checksum.h      2005/03/18 17:37:06     
1.2
+++ linux/arch/um/include/sysdep-x86_64/checksum.h      2005/05/26 09:12:39     
1.3
@@ -9,8 +9,6 @@
 #include "linux/in6.h"
 #include "asm/uaccess.h"
 
-extern unsigned int csum_partial_copy_from(const unsigned char *src, unsigned 
char *dst, int len,
-                                          int sum, int *err_ptr);
 extern unsigned csum_partial(const unsigned char *buff, unsigned len,
                              unsigned sum);
 
@@ -31,10 +29,15 @@
 }
 
 static __inline__
-unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned 
char *dst,
-                                        int len, int sum, int *err_ptr)
-{
-       return csum_partial_copy_from(src, dst, len, sum, err_ptr);
+unsigned int csum_partial_copy_from_user(const unsigned char *src,
+                                         unsigned char *dst, int len, int sum,
+                                         int *err_ptr)
+{
+        if(copy_from_user(dst, src, len)){
+                *err_ptr = -EFAULT;
+                return(-1);
+        }
+        return csum_partial(dst, len, sum);
 }
 
 /**
@@ -137,15 +140,6 @@
         return a;
 }
 
-#endif
+extern unsigned short ip_compute_csum(unsigned char * buff, int len);
 
-/*
- * 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:
- */
+#endif
diff -urN linux/arch/um/include/sysdep-x86_64/ptrace.h 
linux/arch/um/include/sysdep-x86_64/ptrace.h
--- linux/arch/um/include/sysdep-x86_64/ptrace.h        2005/05/19 12:08:17     
1.4
+++ linux/arch/um/include/sysdep-x86_64/ptrace.h        2005/05/26 09:12:39     
1.5
@@ -135,6 +135,7 @@
        __CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs))
 #define UPT_SC(r) ((r)->tt.sc)
 #define UPT_SYSCALL_NR(r) __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall)
+#define UPT_SYSCALL_RET(r) UPT_RAX(r)
 
 extern int user_context(unsigned long sp);
 
@@ -196,32 +197,32 @@
 
 
 #define UPT_SET(regs, reg, val) \
-        ({      unsigned long val; \
+        ({      unsigned long __upt_val = val; \
                 switch(reg){ \
-               case R8: UPT_R8(regs) = val; break; \
-               case R9: UPT_R9(regs) = val; break; \
-               case R10: UPT_R10(regs) = val; break; \
-               case R11: UPT_R11(regs) = val; break; \
-               case R12: UPT_R12(regs) = val; break; \
-               case R13: UPT_R13(regs) = val; break; \
-               case R14: UPT_R14(regs) = val; break; \
-               case R15: UPT_R15(regs) = val; break; \
-                case RIP: UPT_IP(regs) = val; break; \
-                case RSP: UPT_SP(regs) = val; break; \
-                case RAX: UPT_RAX(regs) = val; break; \
-                case RBX: UPT_RBX(regs) = val; break; \
-                case RCX: UPT_RCX(regs) = val; break; \
-                case RDX: UPT_RDX(regs) = val; break; \
-                case RSI: UPT_RSI(regs) = val; break; \
-                case RDI: UPT_RDI(regs) = val; break; \
-                case RBP: UPT_RBP(regs) = val; break; \
-                case ORIG_RAX: UPT_ORIG_RAX(regs) = val; break; \
-                case CS: UPT_CS(regs) = val; break; \
-                case DS: UPT_DS(regs) = val; break; \
-                case ES: UPT_ES(regs) = val; break; \
-                case FS: UPT_FS(regs) = val; break; \
-                case GS: UPT_GS(regs) = val; break; \
-                case EFLAGS: UPT_EFLAGS(regs) = val; break; \
+                case R8: UPT_R8(regs) = __upt_val; break; \
+                case R9: UPT_R9(regs) = __upt_val; break; \
+                case R10: UPT_R10(regs) = __upt_val; break; \
+                case R11: UPT_R11(regs) = __upt_val; break; \
+                case R12: UPT_R12(regs) = __upt_val; break; \
+                case R13: UPT_R13(regs) = __upt_val; break; \
+                case R14: UPT_R14(regs) = __upt_val; break; \
+                case R15: UPT_R15(regs) = __upt_val; break; \
+                case RIP: UPT_IP(regs) = __upt_val; break; \
+                case RSP: UPT_SP(regs) = __upt_val; break; \
+                case RAX: UPT_RAX(regs) = __upt_val; break; \
+                case RBX: UPT_RBX(regs) = __upt_val; break; \
+                case RCX: UPT_RCX(regs) = __upt_val; break; \
+                case RDX: UPT_RDX(regs) = __upt_val; break; \
+                case RSI: UPT_RSI(regs) = __upt_val; break; \
+                case RDI: UPT_RDI(regs) = __upt_val; break; \
+                case RBP: UPT_RBP(regs) = __upt_val; break; \
+                case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \
+                case CS: UPT_CS(regs) = __upt_val; break; \
+                case DS: UPT_DS(regs) = __upt_val; break; \
+                case ES: UPT_ES(regs) = __upt_val; break; \
+                case FS: UPT_FS(regs) = __upt_val; break; \
+                case GS: UPT_GS(regs) = __upt_val; break; \
+                case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \
                 default :  \
                         panic("Bad register in UPT_SET : %d\n", reg);  \
                        break; \
@@ -245,14 +246,3 @@
         CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo))
 
 #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:
- */
diff -urN linux/arch/um/kernel/initrd.c linux/arch/um/kernel/initrd.c
--- linux/arch/um/kernel/initrd.c       1970/01/01 00:00:00
+++ linux/arch/um/kernel/initrd.c       2005-05-26 10:12:39.466440000 +0100     
1.1
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/init.h"
+#include "linux/bootmem.h"
+#include "linux/initrd.h"
+#include "asm/types.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "initrd.h"
+#include "init.h"
+#include "os.h"
+
+/* Changed by uml_initrd_setup, which is a setup */
+static char *initrd __initdata = NULL;
+
+static int __init read_initrd(void)
+{
+       void *area;
+       long long size;
+       int err;
+
+       if(initrd == NULL) return 0;
+       err = os_file_size(initrd, &size);
+       if(err) return 0;
+       area = alloc_bootmem(size);
+       if(area == NULL) return 0;
+       if(load_initrd(initrd, area, size) == -1) return 0;
+       initrd_start = (unsigned long) area;
+       initrd_end = initrd_start + size;
+       return 0;
+}
+
+__uml_postsetup(read_initrd);
+
+static int __init uml_initrd_setup(char *line, int *add)
+{
+       initrd = line;
+       return 0;
+}
+
+__uml_setup("initrd=", uml_initrd_setup,
+"initrd=<initrd image>\n"
+"    This is used to boot UML from an initrd image.  The argument is the\n"
+"    name of the file containing the image.\n\n"
+);
+
+int load_initrd(char *filename, void *buf, int size)
+{
+       int fd, n;
+
+       fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
+       if(fd < 0){
+               printk("Opening '%s' failed - err = %d\n", filename, -fd);
+               return(-1);
+       }
+       n = os_read_file(fd, buf, size);
+       if(n != size){
+               printk("Read of %d bytes from '%s' failed, err = %d\n", size,
+                      filename, -n);
+               return(-1);
+       }
+
+       os_close_file(fd);
+       return(0);
+}
+/*
+ * 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:
+ */
diff -urN linux/arch/um/kernel/Makefile linux/arch/um/kernel/Makefile
--- linux/arch/um/kernel/Makefile       2005/05/19 12:08:17     1.19
+++ linux/arch/um/kernel/Makefile       2005/05/26 09:12:39     1.20
@@ -14,7 +14,7 @@
        tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o umid.o \
        user_util.o
 
-obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
+obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
 obj-$(CONFIG_GPROF)    += gprof_syms.o
 obj-$(CONFIG_GCOV)     += gmon_syms.o
 obj-$(CONFIG_TTY_LOG)  += tty_log.o
diff -urN linux/arch/um/kernel/irq_user.c linux/arch/um/kernel/irq_user.c
--- linux/arch/um/kernel/irq_user.c     2005/01/13 14:05:40     1.10
+++ linux/arch/um/kernel/irq_user.c     2005/05/26 09:12:39     1.11
@@ -236,9 +236,15 @@
                                       (*prev)->fd, pollfds[i].fd);
                                goto out;
                        }
-                       memcpy(&pollfds[i], &pollfds[i + 1],
-                              (pollfds_num - i - 1) * sizeof(pollfds[0]));
+
                        pollfds_num--;
+
+                       /* This moves the *whole* array after pollfds[i] (though
+                        * it doesn't spot as such)! */
+
+                       memmove(&pollfds[i], &pollfds[i + 1],
+                              (pollfds_num - i) * sizeof(pollfds[0]));
+
                        if(last_irq_ptr == &old_fd->next) 
                                last_irq_ptr = prev;
                        *prev = (*prev)->next;
diff -urN linux/arch/um/kernel/ksyms.c linux/arch/um/kernel/ksyms.c
--- linux/arch/um/kernel/ksyms.c        2005/05/19 12:08:17     1.9
+++ linux/arch/um/kernel/ksyms.c        2005/05/26 09:12:39     1.10
@@ -57,6 +57,7 @@
 EXPORT_SYMBOL(strncpy_from_user_skas);
 EXPORT_SYMBOL(copy_to_user_skas);
 EXPORT_SYMBOL(copy_from_user_skas);
+EXPORT_SYMBOL(clear_user_skas);
 #endif
 EXPORT_SYMBOL(uml_strdup);
 
diff -urN linux/arch/um/kernel/mem.c linux/arch/um/kernel/mem.c
--- linux/arch/um/kernel/mem.c  2005/03/18 17:37:06     1.17
+++ linux/arch/um/kernel/mem.c  2005/05/26 09:12:39     1.18
@@ -100,12 +100,37 @@
 #endif
 }
 
+/*
+ * Create a page table and place a pointer to it in a middle page
+ * directory entry.
+ */
+static void __init one_page_table_init(pmd_t *pmd)
+{
+       if (pmd_none(*pmd)) {
+               pte_t *pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+               set_pmd(pmd, __pmd(_KERNPG_TABLE +
+                                          (unsigned long) __pa(pte)));
+               if (pte != pte_offset_kernel(pmd, 0))
+                       BUG();
+       }
+}
+
+static void __init one_md_table_init(pud_t *pud)
+{
+#ifdef CONFIG_3_LEVEL_PGTABLES
+       pmd_t *pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+       set_pud(pud, __pud(_KERNPG_TABLE + (unsigned long) __pa(pmd_table)));
+       if (pmd_table != pmd_offset(pud, 0))
+               BUG();
+#endif
+}
+
 static void __init fixrange_init(unsigned long start, unsigned long end, 
                                 pgd_t *pgd_base)
 {
        pgd_t *pgd;
+       pud_t *pud;
        pmd_t *pmd;
-       pte_t *pte;
        int i, j;
        unsigned long vaddr;
 
@@ -115,15 +140,12 @@
        pgd = pgd_base + i;
 
        for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
-               pmd = (pmd_t *)pgd;
+               pud = pud_offset(pgd, vaddr);
+               if (pud_none(*pud))
+                       one_md_table_init(pud);
+               pmd = pmd_offset(pud, vaddr);
                for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
-                       if (pmd_none(*pmd)) {
-                               pte = (pte_t *) 
alloc_bootmem_low_pages(PAGE_SIZE);
-                               set_pmd(pmd, __pmd(_KERNPG_TABLE + 
-                                                  (unsigned long) __pa(pte)));
-                               if (pte != pte_offset_kernel(pmd, 0))
-                                       BUG();
-                       }
+                       one_page_table_init(pmd);
                        vaddr += PMD_SIZE;
                }
                j = 0;
diff -urN linux/arch/um/kernel/ptrace.c linux/arch/um/kernel/ptrace.c
--- linux/arch/um/kernel/ptrace.c       2005/05/19 12:08:17     1.14
+++ linux/arch/um/kernel/ptrace.c       2005/05/26 09:12:39     1.15
@@ -28,9 +28,9 @@
         child->thread.singlestep_syscall = 0;
 
 #ifdef SUBARCH_SET_SINGLESTEPPING
-        SUBARCH_SET_SINGLESTEPPING(child, on)
+        SUBARCH_SET_SINGLESTEPPING(child, on);
 #endif
-                }
+}
 
 /*
  * Called by kernel/ptrace.c when detaching..
@@ -83,7 +83,7 @@
        }
 
 #ifdef SUBACH_PTRACE_SPECIAL
-        SUBARCH_PTRACE_SPECIAL(child,request,addr,data)
+        SUBARCH_PTRACE_SPECIAL(child,request,addr,data);
 #endif
 
        ret = ptrace_check_attach(child, request == PTRACE_KILL);
diff -urN linux/arch/um/kernel/trap_kern.c linux/arch/um/kernel/trap_kern.c
--- linux/arch/um/kernel/trap_kern.c    2005/05/19 12:08:17     1.10
+++ linux/arch/um/kernel/trap_kern.c    2005/05/26 09:12:39     1.11
@@ -57,10 +57,11 @@
        *code_out = SEGV_ACCERR;
        if(is_write && !(vma->vm_flags & VM_WRITE)) 
                goto out;
+
+        if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
+                goto out;
+
        page = address & PAGE_MASK;
-       pgd = pgd_offset(mm, page);
-       pud = pud_offset(pgd, page);
-       pmd = pmd_offset(pud, page);
        do {
  survive:
                switch (handle_mm_fault(mm, vma, address, is_write)){
@@ -106,33 +107,6 @@
        goto out;
 }
 
-LIST_HEAD(physmem_remappers);
-
-void register_remapper(struct remapper *info)
-{
-       list_add(&info->list, &physmem_remappers);
-}
-
-static int check_remapped_addr(unsigned long address, int is_write)
-{
-       struct remapper *remapper;
-       struct list_head *ele;
-       __u64 offset;
-       int fd;
-
-       fd = phys_mapping(__pa(address), &offset);
-       if(fd == -1)
-               return(0);
-
-       list_for_each(ele, &physmem_remappers){
-               remapper = list_entry(ele, struct remapper, list);
-               if((*remapper->proc)(fd, address, is_write, offset))
-                       return(1);
-       }
-
-       return(0);
-}
-
 /*
  * We give a *copy* of the faultinfo in the regs to segv.
  * This must be done, since nesting SEGVs could overwrite
@@ -151,8 +125,6 @@
                 flush_tlb_kernel_vm();
                 return(0);
         }
-       else if(check_remapped_addr(address & PAGE_MASK, is_write))
-               return(0);
        else if(current->mm == NULL)
                panic("Segfault with no mm");
        err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
diff -urN linux/arch/um/kernel/uml.lds.S linux/arch/um/kernel/uml.lds.S
--- linux/arch/um/kernel/uml.lds.S      2005/01/25 04:28:07     1.3
+++ linux/arch/um/kernel/uml.lds.S      2005/05/26 09:12:39     1.4
@@ -73,6 +73,8 @@
 
   .got           : { *(.got.plt) *(.got) }
   .dynamic       : { *(.dynamic) }
+  .tdata         : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss                  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
   /* We want the small data sections together, so single-instruction offsets
      can access them all, and initialized data all before uninitialized, so
      we can shorten the on-disk segment size.  */
diff -urN linux/arch/um/kernel/tt/ksyms.c linux/arch/um/kernel/tt/ksyms.c
--- linux/arch/um/kernel/tt/ksyms.c     2003/06/02 13:54:10     1.1
+++ linux/arch/um/kernel/tt/ksyms.c     2005/05/26 09:12:39     1.2
@@ -12,6 +12,7 @@
 EXPORT_SYMBOL(__do_strncpy_from_user);
 EXPORT_SYMBOL(__do_strnlen_user); 
 EXPORT_SYMBOL(__do_clear_user);
+EXPORT_SYMBOL(clear_user_tt);
 
 EXPORT_SYMBOL(tracing_pid);
 EXPORT_SYMBOL(honeypot);
diff -urN linux/arch/um/sys-i386/Makefile linux/arch/um/sys-i386/Makefile
--- linux/arch/um/sys-i386/Makefile     2005/05/19 12:08:18     1.13
+++ linux/arch/um/sys-i386/Makefile     2005/05/26 09:12:39     1.14
@@ -9,11 +9,11 @@
 
 SYMLINKS = bitops.c semaphore.c highmem.c module.c
 
+include arch/um/scripts/Makefile.rules
+
 bitops.c-dir = lib
 semaphore.c-dir = kernel
 highmem.c-dir = mm
 module.c-dir = kernel
 
 subdir- := util
-
-include arch/um/scripts/Makefile.rules
diff -urN linux/arch/um/sys-i386/delay.c linux/arch/um/sys-i386/delay.c
--- linux/arch/um/sys-i386/delay.c      2005/05/19 12:08:18     1.2
+++ linux/arch/um/sys-i386/delay.c      2005/05/26 09:12:39     1.3
@@ -1,5 +1,7 @@
-#include "linux/delay.h"
-#include "asm/param.h"
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <asm/param.h>
 
 void __delay(unsigned long time)
 {
@@ -20,13 +22,19 @@
        int i, n;
 
        n = (loops_per_jiffy * HZ * usecs) / MILLION;
-       for(i=0;i<n;i++) ;
+        for(i=0;i<n;i++)
+                cpu_relax();
 }
 
+EXPORT_SYMBOL(__udelay);
+
 void __const_udelay(unsigned long usecs)
 {
        int i, n;
 
        n = (loops_per_jiffy * HZ * usecs) / MILLION;
-       for(i=0;i<n;i++) ;
+        for(i=0;i<n;i++)
+                cpu_relax();
 }
+
+EXPORT_SYMBOL(__const_udelay);
diff -urN linux/arch/um/sys-x86_64/Makefile linux/arch/um/sys-x86_64/Makefile
--- linux/arch/um/sys-x86_64/Makefile   2005/05/19 12:08:19     1.3
+++ linux/arch/um/sys-x86_64/Makefile   2005/05/26 09:12:39     1.4
@@ -14,11 +14,11 @@
 
 USER_OBJS := ptrace_user.o sigcontext.o
 
-include arch/um/scripts/Makefile.rules
-
 SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \
        semaphore.c thunk.S module.c
 
+include arch/um/scripts/Makefile.rules
+
 bitops.c-dir = lib
 csum-copy.S-dir = lib
 csum-partial.c-dir = lib
@@ -28,6 +28,4 @@
 thunk.S-dir = lib
 module.c-dir = kernel
 
-CFLAGS_csum-partial.o := -Dcsum_partial=arch_csum_partial
-
 subdir- := util
diff -urN linux/arch/um/sys-x86_64/delay.c linux/arch/um/sys-x86_64/delay.c
--- linux/arch/um/sys-x86_64/delay.c    2005/05/19 12:08:19     1.2
+++ linux/arch/um/sys-x86_64/delay.c    2005/05/26 09:12:39     1.3
@@ -5,40 +5,37 @@
  * Licensed under the GPL
  */
 
-#include "linux/delay.h"
-#include "asm/processor.h"
-#include "asm/param.h"
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <asm/processor.h>
+#include <asm/param.h>
 
 void __delay(unsigned long loops)
 {
        unsigned long i;
 
-       for(i = 0; i < loops; i++) ;
+        for(i = 0; i < loops; i++)
+                cpu_relax();
 }
 
 void __udelay(unsigned long usecs)
 {
-       int i, n;
+       unsigned long i, n;
 
        n = (loops_per_jiffy * HZ * usecs) / MILLION;
-       for(i=0;i<n;i++) ;
+        for(i=0;i<n;i++)
+                cpu_relax();
 }
 
+EXPORT_SYMBOL(__udelay);
+
 void __const_udelay(unsigned long usecs)
 {
-       int i, n;
+       unsigned long i, n;
 
        n = (loops_per_jiffy * HZ * usecs) / MILLION;
-       for(i=0;i<n;i++) ;
+        for(i=0;i<n;i++)
+                cpu_relax();
 }
 
-/*
- * 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:
- */
+EXPORT_SYMBOL(__const_udelay);
diff -urN linux/arch/um/sys-x86_64/ksyms.c linux/arch/um/sys-x86_64/ksyms.c
--- linux/arch/um/sys-x86_64/ksyms.c    2005/05/19 12:08:19     1.1
+++ linux/arch/um/sys-x86_64/ksyms.c    2005/05/26 09:12:39     1.2
@@ -16,5 +16,4 @@
 EXPORT_SYMBOL(__memcpy);
 
 /* Networking helper routines. */
-/*EXPORT_SYMBOL(csum_partial_copy_from);
-EXPORT_SYMBOL(csum_partial_copy_to);*/
+EXPORT_SYMBOL(ip_compute_csum);
diff -urN linux/arch/um/sys-x86_64/ptrace.c linux/arch/um/sys-x86_64/ptrace.c
--- linux/arch/um/sys-x86_64/ptrace.c   2005/05/19 12:08:19     1.2
+++ linux/arch/um/sys-x86_64/ptrace.c   2005/05/26 09:12:39     1.3
@@ -5,10 +5,11 @@
  */
 
 #define __FRAME_OFFSETS
-#include "asm/ptrace.h"
-#include "linux/sched.h"
-#include "linux/errno.h"
-#include "asm/elf.h"
+#include <asm/ptrace.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <asm/elf.h>
 
 /* XXX x86_64 */
 unsigned long not_ss;
diff -urN linux/arch/um/sys-x86_64/syscalls.c 
linux/arch/um/sys-x86_64/syscalls.c
--- linux/arch/um/sys-x86_64/syscalls.c 2005/05/19 12:08:19     1.3
+++ linux/arch/um/sys-x86_64/syscalls.c 2005/05/26 09:12:39     1.4
@@ -15,6 +15,7 @@
 #include "asm/unistd.h"
 #include "asm/prctl.h" /* XXX This should get the constants from libc */
 #include "choose-mode.h"
+#include "kern.h"
 
 asmlinkage long sys_uname64(struct new_utsname __user * name)
 {
diff -urN linux/arch/um/sys-x86_64/user-offsets.c 
linux/arch/um/sys-x86_64/user-offsets.c
--- linux/arch/um/sys-x86_64/user-offsets.c     2005/05/19 12:08:19     1.1
+++ linux/arch/um/sys-x86_64/user-offsets.c     2005/05/26 09:12:39     1.2
@@ -3,6 +3,14 @@
 #include <signal.h>
 #define __FRAME_OFFSETS
 #include <asm/ptrace.h>
+#include <asm/types.h>
+/* For some reason, x86_64 defines u64 and u32 only in <pci/types.h>, which I
+ * refuse to include here, even though they're used throughout the headers.
+ * These are used in asm/user.h, and that include can't be avoided because of
+ * the sizeof(struct user_regs_struct) below.
+ */
+typedef __u64 u64;
+typedef __u32 u32;
 #include <asm/user.h>
 
 #define DEFINE(sym, val) \
diff -urN linux/arch/x86_64/Kconfig linux/arch/x86_64/Kconfig
--- linux/arch/x86_64/Kconfig   2005/05/19 12:08:19     1.43
+++ linux/arch/x86_64/Kconfig   2005/05/26 09:12:39     1.44
@@ -303,6 +303,20 @@
          as it is off-chip.  You can find the HPET spec at
          <http://www.intel.com/labs/platcomp/hpet/hpetspec.htm>.
 
+config X86_PM_TIMER
+       bool "PM timer"
+       default y
+       help
+         Support the ACPI PM timer for time keeping. This is slow,
+         but is useful on some chipsets without HPET on systems with more
+         than one CPU. On a single processor or single socket multi core
+         system it is normally not required.
+         When the PM timer is active 64bit vsyscalls are disabled
+         and should not be enabled (/proc/sys/kernel/vsyscall64 should
+         not be changed).
+         The kernel selects the PM timer only as a last resort, so it is
+         useful to enable just in case.
+
 config HPET_EMULATE_RTC
        bool "Provide RTC interrupt"
        depends on HPET_TIMER && RTC=y
diff -urN linux/arch/x86_64/defconfig linux/arch/x86_64/defconfig
--- linux/arch/x86_64/defconfig 2005/04/08 18:58:07     1.39
+++ linux/arch/x86_64/defconfig 2005/05/26 09:12:39     1.40
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-bk7
-# Sat Mar 12 23:43:44 2005
+# Linux kernel version: 2.6.12-rc4
+# Fri May 13 06:39:11 2005
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -11,8 +11,6 @@
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_X86_CMPXCHG=y
 CONFIG_EARLY_PRINTK=y
-CONFIG_HPET_TIMER=y
-CONFIG_HPET_EMULATE_RTC=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_IOMAP=y
 
@@ -22,6 +20,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -33,7 +32,6 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=18
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
@@ -43,10 +41,11 @@
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
@@ -93,6 +92,9 @@
 CONFIG_NUMA=y
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_NR_CPUS=8
+CONFIG_HPET_TIMER=y
+CONFIG_X86_PM_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
 CONFIG_GART_IOMMU=y
 CONFIG_SWIOTLB=y
 CONFIG_X86_MCE=y
@@ -100,6 +102,7 @@
 CONFIG_SECCOMP=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ISA_DMA_API=y
 
 #
 # Power management options
@@ -129,7 +132,7 @@
 # CONFIG_ACPI_IBM is not set
 CONFIG_ACPI_TOSHIBA=y
 CONFIG_ACPI_BLACKLIST_YEAR=2001
-CONFIG_ACPI_DEBUG=y
+# CONFIG_ACPI_DEBUG is not set
 CONFIG_ACPI_BUS=y
 CONFIG_ACPI_EC=y
 CONFIG_ACPI_POWER=y
@@ -141,6 +144,7 @@
 # CPU Frequency scaling
 #
 CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
 # CONFIG_CPU_FREQ_DEBUG is not set
 CONFIG_CPU_FREQ_STAT=y
 # CONFIG_CPU_FREQ_STAT_DETAILS is not set
@@ -150,7 +154,6 @@
 # CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-CONFIG_CPU_FREQ_TABLE=y
 
 #
 # CPUFreq processor drivers
@@ -164,6 +167,7 @@
 # shared options
 #
 CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y
+# CONFIG_X86_SPEEDSTEP_LIB is not set
 
 #
 # Bus options (PCI etc.)
@@ -172,9 +176,11 @@
 CONFIG_PCI_DIRECT=y
 CONFIG_PCI_MMCONFIG=y
 CONFIG_UNORDERED_IO=y
+# CONFIG_PCIEPORTBUS is not set
 CONFIG_PCI_MSI=y
 # CONFIG_PCI_LEGACY_PROC is not set
 # CONFIG_PCI_NAMES is not set
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -182,10 +188,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -254,7 +256,7 @@
 # IO Schedulers
 #
 CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_AS is not set
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
 # CONFIG_ATA_OVER_ETH is not set
@@ -308,7 +310,8 @@
 CONFIG_BLK_DEV_PIIX=y
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+# CONFIG_PDC202XX_FORCE is not set
 # CONFIG_BLK_DEV_SVWKS is not set
 # CONFIG_BLK_DEV_SIIMAGE is not set
 # CONFIG_BLK_DEV_SIS5513 is not set
@@ -353,7 +356,7 @@
 #
 # SCSI low-level drivers
 #
-CONFIG_BLK_DEV_3W_XXXX_RAID=y
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AACRAID is not set
@@ -384,7 +387,6 @@
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
@@ -392,7 +394,6 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLA2XXX=y
@@ -401,6 +402,7 @@
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -437,7 +439,6 @@
 #
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -502,7 +503,7 @@
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
+CONFIG_TUN=y
 
 #
 # ARCnet devices
@@ -525,8 +526,7 @@
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
-CONFIG_AMD8111_ETH=y
-# CONFIG_AMD8111E_NAPI is not set
+# CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
 CONFIG_FORCEDETH=y
@@ -536,7 +536,7 @@
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
-CONFIG_8139CP=m
+CONFIG_8139CP=y
 CONFIG_8139TOO=y
 # CONFIG_8139TOO_PIO is not set
 # CONFIG_8139TOO_TUNE_TWISTER is not set
@@ -671,6 +671,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -696,6 +697,7 @@
 #
 CONFIG_AGP=y
 CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
 # CONFIG_DRM is not set
 # CONFIG_MWAVE is not set
 CONFIG_RAW_DRIVER=y
@@ -703,7 +705,7 @@
 # CONFIG_HPET_RTC_IRQ is not set
 CONFIG_HPET_MMAP=y
 CONFIG_MAX_RAW_DEVS=256
-CONFIG_HANGCHECK_TIMER=y
+# CONFIG_HANGCHECK_TIMER is not set
 
 #
 # TPM devices
@@ -786,6 +788,8 @@
 #
 # USB support
 #
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -797,8 +801,6 @@
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
@@ -826,7 +828,6 @@
 #
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_RW_DETECT is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
@@ -965,7 +966,7 @@
 # CD-ROM/DVD Filesystems
 #
 CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
+CONFIG_JOLIET=y
 # CONFIG_ZISOFS is not set
 # CONFIG_UDF_FS is not set
 
@@ -1092,9 +1093,10 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_PRINTK_TIME is not set
+CONFIG_LOG_BUF_SHIFT=18
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
diff -urN linux/arch/x86_64/kernel/pmtimer.c linux/arch/x86_64/kernel/pmtimer.c
--- linux/arch/x86_64/kernel/pmtimer.c  1970/01/01 00:00:00
+++ linux/arch/x86_64/kernel/pmtimer.c  2005-05-26 10:12:40.097501000 +0100     
1.1
@@ -0,0 +1,101 @@
+/* Ported over from i386 by AK, original copyright was:
+ *
+ * (C) Dominik Brodowski <linux@brodo.de> 2003
+ *
+ * Driver to use the Power Management Timer (PMTMR) available in some
+ * southbridges as primary timing source for the Linux kernel.
+ *
+ * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c,
+ * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4.
+ *
+ * This file is licensed under the GPL v2.
+ *
+ * Dropped all the hardware bug workarounds for now. Hopefully they
+ * are not needed on 64bit chipsets.
+ */
+
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/cpumask.h>
+#include <asm/io.h>
+#include <asm/proto.h>
+#include <asm/msr.h>
+#include <asm/vsyscall.h>
+
+/* The I/O port the PMTMR resides at.
+ * The location is detected during setup_arch(),
+ * in arch/i386/kernel/acpi/boot.c */
+u32 pmtmr_ioport;
+
+/* value of the Power timer at last timer interrupt */
+static u32 offset_delay;
+static u32 last_pmtmr_tick;
+
+#define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */
+
+static inline u32 cyc2us(u32 cycles)
+{
+       /* The Power Management Timer ticks at 3.579545 ticks per microsecond.
+        * 1 / PM_TIMER_FREQUENCY == 0.27936511 =~ 286/1024 [error: 0.024%]
+        *
+        * Even with HZ = 100, delta is at maximum 35796 ticks, so it can
+        * easily be multiplied with 286 (=0x11E) without having to fear
+        * u32 overflows.
+        */
+       cycles *= 286;
+       return (cycles >> 10);
+}
+
+int pmtimer_mark_offset(void)
+{
+       static int first_run = 1;
+       unsigned long tsc;
+       u32 lost;
+
+       u32 tick = inl(pmtmr_ioport);
+       u32 delta;
+
+       delta = cyc2us((tick - last_pmtmr_tick) & ACPI_PM_MASK);
+
+       last_pmtmr_tick = tick;
+       monotonic_base += delta * NSEC_PER_USEC;
+
+       delta += offset_delay;
+
+       lost = delta / (USEC_PER_SEC / HZ);
+       offset_delay = delta % (USEC_PER_SEC / HZ);
+
+       rdtscll(tsc);
+       vxtime.last_tsc = tsc - offset_delay * cpu_khz;
+
+       /* don't calculate delay for first run,
+          or if we've got less then a tick */
+       if (first_run || (lost < 1)) {
+               first_run = 0;
+               offset_delay = 0;
+       }
+
+       return lost - 1;
+}
+
+unsigned int do_gettimeoffset_pm(void)
+{
+       u32 now, offset, delta = 0;
+
+       offset = last_pmtmr_tick;
+       now = inl(pmtmr_ioport);
+       delta = (now - offset) & ACPI_PM_MASK;
+
+       return offset_delay + cyc2us(delta);
+}
+
+
+static int __init nopmtimer_setup(char *s)
+{
+       pmtmr_ioport = 0;
+       return 0;
+}
+
+__setup("nopmtimer", nopmtimer_setup);
diff -urN linux/arch/x86_64/kernel/Makefile linux/arch/x86_64/kernel/Makefile
--- linux/arch/x86_64/kernel/Makefile   2005/01/13 14:05:43     1.34
+++ linux/arch/x86_64/kernel/Makefile   2005/05/26 09:12:39     1.35
@@ -28,6 +28,7 @@
 obj-$(CONFIG_DUMMY_IOMMU)      += pci-nommu.o pci-dma.o
 obj-$(CONFIG_SWIOTLB)          += swiotlb.o
 obj-$(CONFIG_KPROBES)          += kprobes.o
+obj-$(CONFIG_X86_PM_TIMER)     += pmtimer.o
 
 obj-$(CONFIG_MODULES)          += module.o
 
diff -urN linux/arch/x86_64/kernel/apic.c linux/arch/x86_64/kernel/apic.c
--- linux/arch/x86_64/kernel/apic.c     2005/04/29 11:15:04     1.29
+++ linux/arch/x86_64/kernel/apic.c     2005/05/26 09:12:39     1.30
@@ -33,6 +33,7 @@
 #include <asm/mpspec.h>
 #include <asm/pgalloc.h>
 #include <asm/mach_apic.h>
+#include <asm/nmi.h>
 
 int apic_verbosity;
 
@@ -925,7 +926,7 @@
        unsigned id;
        DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
 
-       bitmap_empty(clustermap, NUM_APIC_CLUSTERS);
+       bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
 
        for (i = 0; i < NR_CPUS; i++) {
                id = bios_cpu_apicid[i];
@@ -1056,7 +1057,7 @@
                nr_ioapics = 0;
 #endif
        setup_boot_APIC_clock();
-
+       check_nmi_watchdog();
        return 0;
 }
 
diff -urN linux/arch/x86_64/kernel/entry.S linux/arch/x86_64/kernel/entry.S
--- linux/arch/x86_64/kernel/entry.S    2005/05/19 12:08:19     1.27
+++ linux/arch/x86_64/kernel/entry.S    2005/05/26 09:12:39     1.28
@@ -220,13 +220,18 @@
        jmp sysret_check
 
        /* Handle a signal */ 
-       /* edx: work flags (arg3) */
 sysret_signal:
        sti
+       testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
+       jz    1f
+
+       /* Really a signal */
+       /* edx: work flags (arg3) */
        leaq do_notify_resume(%rip),%rax
        leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
        xorl %esi,%esi # oldset -> arg2
        call ptregscall_common
+1:     movl $_TIF_NEED_RESCHED,%edi
        jmp sysret_check
        
        /* Do syscall tracing */
@@ -484,6 +489,8 @@
        jmp retint_check
        
 retint_signal:
+       testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
+       jz    retint_swapgs
        sti
        SAVE_REST
        movq $-1,ORIG_RAX(%rsp)                         
@@ -492,8 +499,8 @@
        call do_notify_resume
        RESTORE_REST
        cli
+       movl $_TIF_NEED_RESCHED,%edi
        GET_THREAD_INFO(%rcx)
-       movl $_TIF_WORK_MASK,%edi
        jmp retint_check
 
 #ifdef CONFIG_PREEMPT
diff -urN linux/arch/x86_64/kernel/io_apic.c linux/arch/x86_64/kernel/io_apic.c
--- linux/arch/x86_64/kernel/io_apic.c  2005/05/19 12:08:19     1.34
+++ linux/arch/x86_64/kernel/io_apic.c  2005/05/26 09:12:40     1.35
@@ -42,6 +42,8 @@
 
 int sis_apic_bug; /* not actually supported, dummy for compile */
 
+static int no_timer_check;
+
 static DEFINE_SPINLOCK(ioapic_lock);
 
 /*
@@ -1601,7 +1603,7 @@
                 * Ok, does IRQ0 through the IOAPIC work?
                 */
                unmask_IO_APIC_irq(0);
-               if (timer_irq_works()) {
+               if (!no_timer_check && timer_irq_works()) {
                        nmi_watchdog_default();
                        if (nmi_watchdog == NMI_IO_APIC) {
                                disable_8259A_irq(0);
@@ -1671,6 +1673,13 @@
        panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel 
parameter\n");
 }
 
+static int __init notimercheck(char *s)
+{
+       no_timer_check = 1;
+       return 1;
+}
+__setup("no_timer_check", notimercheck);
+
 /*
  *
  * IRQ's that are handled by the PIC in the MPS IOAPIC case.
@@ -1804,76 +1813,6 @@
 
 #define IO_APIC_MAX_ID         0xFE
 
-int __init io_apic_get_unique_id (int ioapic, int apic_id)
-{
-       union IO_APIC_reg_00 reg_00;
-       static physid_mask_t apic_id_map;
-       unsigned long flags;
-       int i = 0;
-
-       /*
-        * The P4 platform supports up to 256 APIC IDs on two separate APIC 
-        * buses (one for LAPICs, one for IOAPICs), where predecessors only 
-        * supports up to 16 on one shared APIC bus.
-        * 
-        * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full
-        *      advantage of new APIC bus architecture.
-        */
-
-       if (physids_empty(apic_id_map))
-               apic_id_map = phys_cpu_present_map;
-
-       spin_lock_irqsave(&ioapic_lock, flags);
-       reg_00.raw = io_apic_read(ioapic, 0);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
-
-       if (apic_id >= IO_APIC_MAX_ID) {
-               apic_printk(APIC_QUIET, KERN_WARNING "IOAPIC[%d]: Invalid 
apic_id %d, trying "
-                       "%d\n", ioapic, apic_id, reg_00.bits.ID);
-               apic_id = reg_00.bits.ID;
-       }
-
-       /*
-        * Every APIC in a system must have a unique ID or we get lots of nice 
-        * 'stuck on smp_invalidate_needed IPI wait' messages.
-        */
-       if (physid_isset(apic_id, apic_id_map)) {
-
-               for (i = 0; i < IO_APIC_MAX_ID; i++) {
-                       if (!physid_isset(i, apic_id_map))
-                               break;
-               }
-
-               if (i == IO_APIC_MAX_ID)
-                       panic("Max apic_id exceeded!\n");
-
-               apic_printk(APIC_VERBOSE, KERN_WARNING "IOAPIC[%d]: apic_id %d 
already used, "
-                       "trying %d\n", ioapic, apic_id, i);
-
-               apic_id = i;
-       } 
-
-       physid_set(apic_id, apic_id_map);
-
-       if (reg_00.bits.ID != apic_id) {
-               reg_00.bits.ID = apic_id;
-
-               spin_lock_irqsave(&ioapic_lock, flags);
-               io_apic_write(ioapic, 0, reg_00.raw);
-               reg_00.raw = io_apic_read(ioapic, 0);
-               spin_unlock_irqrestore(&ioapic_lock, flags);
-
-               /* Sanity check */
-               if (reg_00.bits.ID != apic_id)
-                       panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic);
-       }
-
-       apic_printk(APIC_VERBOSE,KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", 
ioapic, apic_id);
-
-       return apic_id;
-}
-
-
 int __init io_apic_get_version (int ioapic)
 {
        union IO_APIC_reg_01    reg_01;
diff -urN linux/arch/x86_64/kernel/mpparse.c linux/arch/x86_64/kernel/mpparse.c
--- linux/arch/x86_64/kernel/mpparse.c  2005/03/18 17:37:08     1.28
+++ linux/arch/x86_64/kernel/mpparse.c  2005/05/26 09:12:40     1.29
@@ -107,6 +107,7 @@
 static void __init MP_processor_info (struct mpc_config_processor *m)
 {
        int ver;
+       static int found_bsp=0;
 
        if (!(m->mpc_cpuflag & CPU_ENABLED))
                return;
@@ -126,11 +127,6 @@
                        " Processor ignored.\n", NR_CPUS);
                return;
        }
-       if (num_processors >= maxcpus) {
-               printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
-                       " Processor ignored.\n", maxcpus);
-               return;
-       }
 
        num_processors++;
 
@@ -150,7 +146,19 @@
                ver = 0x10;
        }
        apic_version[m->mpc_apicid] = ver;
-       bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
+       if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+               /*
+                * bios_cpu_apicid is required to have processors listed
+                * in same order as logical cpu numbers. Hence the first
+                * entry is BSP, and so on.
+                */
+               bios_cpu_apicid[0] = m->mpc_apicid;
+               x86_cpu_to_apicid[0] = m->mpc_apicid;
+               found_bsp = 1;
+       } else {
+               bios_cpu_apicid[num_processors - found_bsp] = m->mpc_apicid;
+               x86_cpu_to_apicid[num_processors - found_bsp] = m->mpc_apicid;
+       }
 }
 
 static void __init MP_bus_info (struct mpc_config_bus *m)
@@ -759,7 +767,7 @@
        mp_ioapics[idx].mpc_apicaddr = address;
 
        set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
-       mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id);
+       mp_ioapics[idx].mpc_apicid = id;
        mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
        
        /* 
diff -urN linux/arch/x86_64/kernel/nmi.c linux/arch/x86_64/kernel/nmi.c
--- linux/arch/x86_64/kernel/nmi.c      2005/05/19 12:08:19     1.24
+++ linux/arch/x86_64/kernel/nmi.c      2005/05/26 09:12:40     1.25
@@ -33,6 +33,7 @@
 #include <asm/msr.h>
 #include <asm/proto.h>
 #include <asm/kdebug.h>
+#include <asm/local.h>
 
 /*
  * lapic_nmi_owner tracks the ownership of the lapic NMI hardware:
@@ -59,7 +60,8 @@
 
 unsigned int nmi_watchdog = NMI_DEFAULT;
 static unsigned int nmi_hz = HZ;
-unsigned int nmi_perfctr_msr;  /* the MSR to reset in NMI handler */
+static unsigned int nmi_perfctr_msr;   /* the MSR to reset in NMI handler */
+static unsigned int nmi_p4_cccr_val;
 
 /* Note that these events don't tick when the CPU idles. This means
    the frequency varies with CPU load. */
@@ -71,61 +73,87 @@
 #define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING   0x76
 #define K7_NMI_EVENT           K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
 
-#define P6_EVNTSEL0_ENABLE     (1 << 22)
-#define P6_EVNTSEL_INT         (1 << 20)
-#define P6_EVNTSEL_OS          (1 << 17)
-#define P6_EVNTSEL_USR         (1 << 16)
-#define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79
-#define P6_NMI_EVENT           P6_EVENT_CPU_CLOCKS_NOT_HALTED
+#define MSR_P4_MISC_ENABLE     0x1A0
+#define MSR_P4_MISC_ENABLE_PERF_AVAIL  (1<<7)
+#define MSR_P4_MISC_ENABLE_PEBS_UNAVAIL        (1<<12)
+#define MSR_P4_PERFCTR0                0x300
+#define MSR_P4_CCCR0           0x360
+#define P4_ESCR_EVENT_SELECT(N)        ((N)<<25)
+#define P4_ESCR_OS             (1<<3)
+#define P4_ESCR_USR            (1<<2)
+#define P4_CCCR_OVF_PMI0       (1<<26)
+#define P4_CCCR_OVF_PMI1       (1<<27)
+#define P4_CCCR_THRESHOLD(N)   ((N)<<20)
+#define P4_CCCR_COMPLEMENT     (1<<19)
+#define P4_CCCR_COMPARE                (1<<18)
+#define P4_CCCR_REQUIRED       (3<<16)
+#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
+#define P4_CCCR_ENABLE         (1<<12)
+/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
+   CRU_ESCR0 (with any non-null event selector) through a complemented
+   max threshold. [IA32-Vol3, Section 14.9.9] */
+#define MSR_P4_IQ_COUNTER0     0x30C
+#define P4_NMI_CRU_ESCR0       
(P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR)
+#define P4_NMI_IQ_CCCR0        \
+       (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT|     \
+        P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
+
+static __init inline int nmi_known_cpu(void)
+{
+       switch (boot_cpu_data.x86_vendor) {
+       case X86_VENDOR_AMD:
+               return boot_cpu_data.x86 == 15;
+       case X86_VENDOR_INTEL:
+               return boot_cpu_data.x86 == 15;
+       }
+       return 0;
+}
 
 /* Run after command line and cpu_init init, but before all other checks */
 void __init nmi_watchdog_default(void)
 {
        if (nmi_watchdog != NMI_DEFAULT)
                return;
-
-       /* For some reason the IO APIC watchdog doesn't work on the AMD
-          8111 chipset. For now switch to local APIC mode using
-          perfctr0 there.  On Intel CPUs we don't have code to handle
-          the perfctr and the IO-APIC seems to work, so use that.  */
-
-       if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
-               nmi_watchdog = NMI_LOCAL_APIC; 
-               printk(KERN_INFO 
-              "Using local APIC NMI watchdog using perfctr0\n");
-       } else {
-               printk(KERN_INFO "Using IO APIC NMI watchdog\n");
+       if (nmi_known_cpu())
+               nmi_watchdog = NMI_LOCAL_APIC;
+       else
                nmi_watchdog = NMI_IO_APIC;
-       }
 }
 
-/* Why is there no CPUID flag for this? */
-static __init int cpu_has_lapic(void)
+#ifdef CONFIG_SMP
+/* The performance counters used by NMI_LOCAL_APIC don't trigger when
+ * the CPU is idle. To make sure the NMI watchdog really ticks on all
+ * CPUs during the test make them busy.
+ */
+static __init void nmi_cpu_busy(void *data)
 {
-       switch (boot_cpu_data.x86_vendor) { 
-       case X86_VENDOR_INTEL:
-       case X86_VENDOR_AMD: 
-               return boot_cpu_data.x86 >= 6; 
-       /* .... add more cpus here or find a different way to figure this out. 
*/       
-       default:
-               return 0;
-       }       
+       volatile int *endflag = data;
+       local_irq_enable();
+       /* Intentionally don't use cpu_relax here. This is
+          to make sure that the performance counter really ticks,
+          even if there is a simulator or similar that catches the
+          pause instruction. On a real HT machine this is fine because
+          all other CPUs are busy with "useless" delay loops and don't
+          care if they get somewhat less cycles. */
+       while (*endflag == 0)
+               barrier();
 }
+#endif
 
-static int __init check_nmi_watchdog (void)
+int __init check_nmi_watchdog (void)
 {
-       int counts[NR_CPUS];
+       volatile int endflag = 0;
+       int *counts;
        int cpu;
 
-       if (nmi_watchdog == NMI_NONE)
-               return 0;
+       counts = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL);
+       if (!counts)
+               return -1;
 
-       if (nmi_watchdog == NMI_LOCAL_APIC && !cpu_has_lapic())  {
-               nmi_watchdog = NMI_NONE;
-               return -1; 
-       }       
+       printk(KERN_INFO "testing NMI watchdog ... ");
 
-       printk(KERN_INFO "Testing NMI watchdog ... ");
+       if (nmi_watchdog == NMI_LOCAL_APIC)
+               smp_call_function(nmi_cpu_busy, (void *)&endflag, 0, 0);
 
        for (cpu = 0; cpu < NR_CPUS; cpu++)
                counts[cpu] = cpu_pda[cpu].__nmi_count; 
@@ -133,15 +161,22 @@
        mdelay((10*1000)/nmi_hz); // wait 10 ticks
 
        for (cpu = 0; cpu < NR_CPUS; cpu++) {
+               if (!cpu_online(cpu))
+                       continue;
                if (cpu_pda[cpu].__nmi_count - counts[cpu] <= 5) {
-                       printk("CPU#%d: NMI appears to be stuck (%d)!\n", 
+                       endflag = 1;
+                       printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n",
                               cpu,
+                              counts[cpu],
                               cpu_pda[cpu].__nmi_count);
                        nmi_active = 0;
                        lapic_nmi_owner &= ~LAPIC_NMI_WATCHDOG;
+                       nmi_perfctr_msr = 0;
+                       kfree(counts);
                        return -1;
                }
        }
+       endflag = 1;
        printk("OK.\n");
 
        /* now that we know it works we can reduce NMI frequency to
@@ -149,10 +184,9 @@
        if (nmi_watchdog == NMI_LOCAL_APIC)
                nmi_hz = 1;
 
+       kfree(counts);
        return 0;
 }
-/* Have this called later during boot so counters are updating */
-late_initcall(check_nmi_watchdog);
 
 int __init setup_nmi_watchdog(char *str)
 {
@@ -170,7 +204,7 @@
 
        if (nmi >= NMI_INVALID)
                return 0;
-               nmi_watchdog = nmi;
+       nmi_watchdog = nmi;
        return 1;
 }
 
@@ -185,7 +219,10 @@
                wrmsr(MSR_K7_EVNTSEL0, 0, 0);
                break;
        case X86_VENDOR_INTEL:
-               wrmsr(MSR_IA32_EVNTSEL0, 0, 0);
+               if (boot_cpu_data.x86 == 15) {
+                       wrmsr(MSR_P4_IQ_CCCR0, 0, 0);
+                       wrmsr(MSR_P4_CRU_ESCR0, 0, 0);
+               }
                break;
        }
        nmi_active = -1;
@@ -253,7 +290,7 @@
 
 static int nmi_pm_active; /* nmi_active before suspend */
 
-static int lapic_nmi_suspend(struct sys_device *dev, pm_message_t state)
+static int lapic_nmi_suspend(struct sys_device *dev, u32 state)
 {
        nmi_pm_active = nmi_active;
        disable_lapic_nmi_watchdog();
@@ -300,22 +337,27 @@
  * Original code written by Keith Owens.
  */
 
+static void clear_msr_range(unsigned int base, unsigned int n)
+{
+       unsigned int i;
+
+       for(i = 0; i < n; ++i)
+               wrmsr(base+i, 0, 0);
+}
+
 static void setup_k7_watchdog(void)
 {
        int i;
        unsigned int evntsel;
 
-       /* No check, so can start with slow frequency */
-       nmi_hz = 1; 
-
-       /* XXX should check these in EFER */
-
        nmi_perfctr_msr = MSR_K7_PERFCTR0;
 
        for(i = 0; i < 4; ++i) {
                /* Simulator may not support it */
-               if (checking_wrmsrl(MSR_K7_EVNTSEL0+i, 0UL))
+               if (checking_wrmsrl(MSR_K7_EVNTSEL0+i, 0UL)) {
+                       nmi_perfctr_msr = 0;
                        return;
+               }
                wrmsrl(MSR_K7_PERFCTR0+i, 0UL);
        }
 
@@ -325,12 +367,54 @@
                | K7_NMI_EVENT;
 
        wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
-       wrmsrl(MSR_K7_PERFCTR0, -((u64)cpu_khz*1000) / nmi_hz);
+       wrmsr(MSR_K7_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1);
        apic_write(APIC_LVTPC, APIC_DM_NMI);
        evntsel |= K7_EVNTSEL_ENABLE;
        wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
 }
 
+
+static int setup_p4_watchdog(void)
+{
+       unsigned int misc_enable, dummy;
+
+       rdmsr(MSR_P4_MISC_ENABLE, misc_enable, dummy);
+       if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
+               return 0;
+
+       nmi_perfctr_msr = MSR_P4_IQ_COUNTER0;
+       nmi_p4_cccr_val = P4_NMI_IQ_CCCR0;
+#ifdef CONFIG_SMP
+       if (smp_num_siblings == 2)
+               nmi_p4_cccr_val |= P4_CCCR_OVF_PMI1;
+#endif
+
+       if (!(misc_enable & MSR_P4_MISC_ENABLE_PEBS_UNAVAIL))
+               clear_msr_range(0x3F1, 2);
+       /* MSR 0x3F0 seems to have a default value of 0xFC00, but current
+          docs doesn't fully define it, so leave it alone for now. */
+       if (boot_cpu_data.x86_model >= 0x3) {
+               /* MSR_P4_IQ_ESCR0/1 (0x3ba/0x3bb) removed */
+               clear_msr_range(0x3A0, 26);
+               clear_msr_range(0x3BC, 3);
+       } else {
+               clear_msr_range(0x3A0, 31);
+       }
+       clear_msr_range(0x3C0, 6);
+       clear_msr_range(0x3C8, 6);
+       clear_msr_range(0x3E0, 2);
+       clear_msr_range(MSR_P4_CCCR0, 18);
+       clear_msr_range(MSR_P4_PERFCTR0, 18);
+
+       wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
+       wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
+       Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
+       wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
+       wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
+       return 1;
+}
+
 void setup_apic_nmi_watchdog(void)
 {
        switch (boot_cpu_data.x86_vendor) {
@@ -341,6 +425,13 @@
                        return;
                setup_k7_watchdog();
                break;
+       case X86_VENDOR_INTEL:
+               if (boot_cpu_data.x86 != 15)
+                       return;
+               if (!setup_p4_watchdog())
+                       return;
+               break;
+
        default:
                return;
        }
@@ -355,56 +446,67 @@
  *
  * as these watchdog NMI IRQs are generated on every CPU, we only
  * have to check the current processor.
- *
- * since NMIs don't listen to _any_ locks, we have to be extremely
- * careful not to rely on unsafe variables. The printk might lock
- * up though, so we have to break up any console locks first ...
- * [when there will be more tty-related locks, break them up
- *  here too!]
  */
 
-static unsigned int
-       last_irq_sums [NR_CPUS],
-       alert_counter [NR_CPUS];
+static DEFINE_PER_CPU(unsigned, last_irq_sum);
+static DEFINE_PER_CPU(local_t, alert_counter);
+static DEFINE_PER_CPU(int, nmi_touch);
 
 void touch_nmi_watchdog (void)
 {
        int i;
 
        /*
-        * Just reset the alert counters, (other CPUs might be
-        * spinning on locks we hold):
+        * Tell other CPUs to reset their alert counters. We cannot
+        * do it ourselves because the alert count increase is not
+        * atomic.
         */
        for (i = 0; i < NR_CPUS; i++)
-               alert_counter[i] = 0;
+               per_cpu(nmi_touch, i) = 1;
 }
 
 void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)
 {
-       int sum, cpu;
+       int sum;
+       int touched = 0;
 
-       cpu = safe_smp_processor_id();
        sum = read_pda(apic_timer_irqs);
-       if (last_irq_sums[cpu] == sum) {
+       if (__get_cpu_var(nmi_touch)) {
+               __get_cpu_var(nmi_touch) = 0;
+               touched = 1;
+       }
+       if (!touched && __get_cpu_var(last_irq_sum) == sum) {
                /*
                 * Ayiee, looks like this CPU is stuck ...
                 * wait a few IRQs (5 seconds) before doing the oops ...
                 */
-               alert_counter[cpu]++;
-               if (alert_counter[cpu] == 5*nmi_hz) {
+               local_inc(&__get_cpu_var(alert_counter));
+               if (local_read(&__get_cpu_var(alert_counter)) == 5*nmi_hz) {
                        if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
                                                        == NOTIFY_STOP) {
-                               alert_counter[cpu] = 0; 
+                               local_set(&__get_cpu_var(alert_counter), 0);
                                return;
                        } 
                        die_nmi("NMI Watchdog detected LOCKUP on CPU%d", regs);
                }
        } else {
-               last_irq_sums[cpu] = sum;
-               alert_counter[cpu] = 0;
+               __get_cpu_var(last_irq_sum) = sum;
+               local_set(&__get_cpu_var(alert_counter), 0);
        }
-       if (nmi_perfctr_msr)
+       if (nmi_perfctr_msr) {
+               if (nmi_perfctr_msr == MSR_P4_IQ_COUNTER0) {
+                       /*
+                        * P4 quirks:
+                        * - An overflown perfctr will assert its interrupt
+                        *   until the OVF flag in its CCCR is cleared.
+                        * - LVTPC is masked on interrupt and must be
+                        *   unmasked by the LVTPC handler.
+                        */
+                       wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
+                       apic_write(APIC_LVTPC, APIC_DM_NMI);
+               }
                wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
+       }
 }
 
 static int dummy_nmi_callback(struct pt_regs * regs, int cpu)
diff -urN linux/arch/x86_64/kernel/ptrace.c linux/arch/x86_64/kernel/ptrace.c
--- linux/arch/x86_64/kernel/ptrace.c   2005/05/19 12:08:19     1.23
+++ linux/arch/x86_64/kernel/ptrace.c   2005/05/26 09:12:40     1.24
@@ -257,13 +257,13 @@
                        value &= 0xffff;
                        return 0;
                case offsetof(struct user_regs_struct,fs_base):
-                       if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
-                               return -EIO; 
+                       if (value >= TASK_SIZE)
+                               return -EIO;
                        child->thread.fs = value;
                        return 0;
                case offsetof(struct user_regs_struct,gs_base):
-                       if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
-                               return -EIO; 
+                       if (value >= TASK_SIZE)
+                               return -EIO;
                        child->thread.gs = value;
                        return 0;
                case offsetof(struct user_regs_struct, eflags):
@@ -277,6 +277,11 @@
                                return -EIO;
                        value &= 0xffff;
                        break;
+               case offsetof(struct user_regs_struct, rip):
+                       /* Check if the new RIP address is canonical */
+                       if (value >= TASK_SIZE)
+                               return -EIO;
+                       break;
        }
        put_stack_long(child, regno - sizeof(struct pt_regs), value);
        return 0;
@@ -375,7 +380,7 @@
                        break;
 
                switch (addr) { 
-               case 0 ... sizeof(struct user_regs_struct):
+               case 0 ... sizeof(struct user_regs_struct) - sizeof(long):
                        tmp = getreg(child, addr);
                        break;
                case offsetof(struct user, u_debugreg[0]):
@@ -420,7 +425,7 @@
                        break;
 
                switch (addr) { 
-               case 0 ... sizeof(struct user_regs_struct): 
+               case 0 ... sizeof(struct user_regs_struct) - sizeof(long):
                        ret = putreg(child, addr, data);
                        break;
                /* Disallows to set a breakpoint into the vsyscall */
diff -urN linux/arch/x86_64/kernel/setup.c linux/arch/x86_64/kernel/setup.c
--- linux/arch/x86_64/kernel/setup.c    2005/05/19 12:08:19     1.44
+++ linux/arch/x86_64/kernel/setup.c    2005/05/26 09:12:40     1.45
@@ -719,7 +719,6 @@
        }
 }
 
-#ifdef CONFIG_SMP
 /*
  * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
  * Assumes number of cores is a power of two.
@@ -727,17 +726,26 @@
 static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
-       int cpu = c->x86_apicid;
+       int cpu = smp_processor_id();
        int node = 0;
+       unsigned bits;
        if (c->x86_num_cores == 1)
                return;
-       cpu_core_id[cpu] = cpu >> hweight32(c->x86_num_cores - 1);
+
+       bits = 0;
+       while ((1 << bits) < c->x86_num_cores)
+               bits++;
+
+       /* Low order bits define the core id (index of core in socket) */
+       cpu_core_id[cpu] = phys_proc_id[cpu] & ((1 << bits)-1);
+       /* Convert the APIC ID into the socket ID */
+       phys_proc_id[cpu] >>= bits;
 
 #ifdef CONFIG_NUMA
        /* When an ACPI SRAT table is available use the mappings from SRAT
           instead. */
        if (acpi_numa <= 0) {
-               node = cpu_core_id[cpu];
+               node = phys_proc_id[cpu];
                if (!node_online(node))
                        node = first_node(node_online_map);
                cpu_to_node[cpu] = node;
@@ -745,15 +753,11 @@
                node = cpu_to_node[cpu];
        }
 #endif
+
        printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
                        cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
 #endif
 }
-#else
-static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
-{
-}
-#endif
 
 static int __init init_amd(struct cpuinfo_x86 *c)
 {
@@ -925,7 +929,6 @@
        c->x86_clflush_size = 64;
        c->x86_cache_alignment = c->x86_clflush_size;
        c->x86_num_cores = 1;
-       c->x86_apicid = c == &boot_cpu_data ? 0 : c - cpu_data;
        c->extended_cpuid_level = 0;
        memset(&c->x86_capability, 0, sizeof c->x86_capability);
 
@@ -954,11 +957,14 @@
                } 
                if (c->x86_capability[0] & (1<<19)) 
                        c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
-               c->x86_apicid = misc >> 24;
        } else {
                /* Have CPUID level 0 only - unheard of */
                c->x86 = 4;
        }
+
+#ifdef CONFIG_SMP
+       phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
+#endif
 }
 
 /*
@@ -1088,7 +1094,7 @@
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
                /* Other (Linux-defined) */
-               "cxmmx", NULL, "cyrix_arr", "centaur_mcr", "k8c+",
+               "cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL,
                "constant_tsc", NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
diff -urN linux/arch/x86_64/kernel/signal.c linux/arch/x86_64/kernel/signal.c
--- linux/arch/x86_64/kernel/signal.c   2005/05/19 12:08:19     1.30
+++ linux/arch/x86_64/kernel/signal.c   2005/05/26 09:12:40     1.31
@@ -452,7 +452,9 @@
                        regs->rip -= 2;
                }
                if (regs->rax == (unsigned long)-ERESTART_RESTARTBLOCK) {
-                       regs->rax = __NR_restart_syscall;
+                       regs->rax = test_thread_flag(TIF_IA32) ?
+                                       __NR_ia32_restart_syscall :
+                                       __NR_restart_syscall;
                        regs->rip -= 2;
                }
        }
diff -urN linux/arch/x86_64/kernel/smpboot.c linux/arch/x86_64/kernel/smpboot.c
--- linux/arch/x86_64/kernel/smpboot.c  2005/04/29 11:15:05     1.37
+++ linux/arch/x86_64/kernel/smpboot.c  2005/05/26 09:12:40     1.38
@@ -56,6 +56,7 @@
 #include <asm/kdebug.h>
 #include <asm/tlbflush.h>
 #include <asm/proto.h>
+#include <asm/nmi.h>
 
 /* Change for real CPU hotplug. Note other files need to be fixed
    first too. */
@@ -93,6 +94,7 @@
 
 cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
 cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
+EXPORT_SYMBOL(cpu_core_map);
 
 /*
  * Trampoline 80x86 program as an array.
@@ -125,96 +127,210 @@
 
        *c = boot_cpu_data;
        identify_cpu(c);
+       print_cpu_info(c);
 }
 
 /*
- * Synchronize TSCs of CPUs
+ * New Funky TSC sync algorithm borrowed from IA64.
+ * Main advantage is that it doesn't reset the TSCs fully and
+ * in general looks more robust and it works better than my earlier
+ * attempts. I believe it was written by David Mosberger. Some minor
+ * adjustments for x86-64 by me -AK
  *
- * This new algorithm is less accurate than the old "zero TSCs"
- * one, but we cannot zero TSCs anymore in the new hotplug CPU
- * model.
+ * Original comment reproduced below.
+ *
+ * Synchronize TSC of the current (slave) CPU with the TSC of the
+ * MASTER CPU (normally the time-keeper CPU).  We use a closed loop to
+ * eliminate the possibility of unaccounted-for errors (such as
+ * getting a machine check in the middle of a calibration step).  The
+ * basic idea is for the slave to ask the master what itc value it has
+ * and to read its own itc before and after the master responds.  Each
+ * iteration gives us three timestamps:
+ *
+ *     slave           master
+ *
+ *     t0 ---\
+ *             ---\
+ *                --->
+ *                     tm
+ *                /---
+ *            /---
+ *     t1 <---
+ *
+ *
+ * The goal is to adjust the slave's TSC such that tm falls exactly
+ * half-way between t0 and t1.  If we achieve this, the clocks are
+ * synchronized provided the interconnect between the slave and the
+ * master is symmetric.  Even if the interconnect were asymmetric, we
+ * would still know that the synchronization error is smaller than the
+ * roundtrip latency (t0 - t1).
+ *
+ * When the interconnect is quiet and symmetric, this lets us
+ * synchronize the TSC to within one or two cycles.  However, we can
+ * only *guarantee* that the synchronization is accurate to within a
+ * round-trip time, which is typically in the range of several hundred
+ * cycles (e.g., ~500 cycles).  In practice, this means that the TSCs
+ * are usually almost perfectly synchronized, but we shouldn't assume
+ * that the accuracy is much better than half a micro second or so.
+ *
+ * [there are other errors like the latency of RDTSC and of the
+ * WRMSR. These can also account to hundreds of cycles. So it's
+ * probably worse. It claims 153 cycles error on a dual Opteron,
+ * but I suspect the numbers are actually somewhat worse -AK]
  */
 
-static atomic_t __cpuinitdata tsc_flag;
+#define MASTER 0
+#define SLAVE  (SMP_CACHE_BYTES/8)
+
+/* Intentionally don't use cpu_relax() while TSC synchronization
+   because we don't want to go into funky power save modi or cause
+   hypervisors to schedule us away.  Going to sleep would likely affect
+   latency and low latency is the primary objective here. -AK */
+#define no_cpu_relax() barrier()
+
 static __cpuinitdata DEFINE_SPINLOCK(tsc_sync_lock);
-static unsigned long long __cpuinitdata bp_tsc, ap_tsc;
+static volatile __cpuinitdata unsigned long go[SLAVE + 1];
+static int notscsync __cpuinitdata;
 
-#define NR_LOOPS 5
+#undef DEBUG_TSC_SYNC
 
-static void __cpuinit sync_tsc_bp_init(int init)
-{
-       if (init)
-               _raw_spin_lock(&tsc_sync_lock);
-       else
-               _raw_spin_unlock(&tsc_sync_lock);
-       atomic_set(&tsc_flag, 0);
-}
+#define NUM_ROUNDS     64      /* magic value */
+#define NUM_ITERS      5       /* likewise */
 
-/*
- * Synchronize TSC on AP with BP.
- */
-static void __cpuinit __sync_tsc_ap(void)
+/* Callback on boot CPU */
+static __cpuinit void sync_master(void *arg)
 {
-       if (!cpu_has_tsc)
+       unsigned long flags, i;
+
+       if (smp_processor_id() != boot_cpu_id)
                return;
-       Dprintk("AP %d syncing TSC\n", smp_processor_id());
 
-       while (atomic_read(&tsc_flag) != 0)
-               cpu_relax();
-       atomic_inc(&tsc_flag);
-       mb();
-       _raw_spin_lock(&tsc_sync_lock);
-       wrmsrl(MSR_IA32_TSC, bp_tsc);
-       _raw_spin_unlock(&tsc_sync_lock);
-       rdtscll(ap_tsc);
-       mb();
-       atomic_inc(&tsc_flag);
-       mb();
+       go[MASTER] = 0;
+
+       local_irq_save(flags);
+       {
+               for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) {
+                       while (!go[MASTER])
+                               no_cpu_relax();
+                       go[MASTER] = 0;
+                       rdtscll(go[SLAVE]);
+               }
+       }
+       local_irq_restore(flags);
 }
 
-static void __cpuinit sync_tsc_ap(void)
+/*
+ * Return the number of cycles by which our tsc differs from the tsc
+ * on the master (time-keeper) CPU.  A positive number indicates our
+ * tsc is ahead of the master, negative that it is behind.
+ */
+static inline long
+get_delta(long *rt, long *master)
 {
+       unsigned long best_t0 = 0, best_t1 = ~0UL, best_tm = 0;
+       unsigned long tcenter, t0, t1, tm;
        int i;
-       for (i = 0; i < NR_LOOPS; i++)
-               __sync_tsc_ap();
+
+       for (i = 0; i < NUM_ITERS; ++i) {
+               rdtscll(t0);
+               go[MASTER] = 1;
+               while (!(tm = go[SLAVE]))
+                       no_cpu_relax();
+               go[SLAVE] = 0;
+               rdtscll(t1);
+
+               if (t1 - t0 < best_t1 - best_t0)
+                       best_t0 = t0, best_t1 = t1, best_tm = tm;
+       }
+
+       *rt = best_t1 - best_t0;
+       *master = best_tm - best_t0;
+
+       /* average best_t0 and best_t1 without overflow: */
+       tcenter = (best_t0/2 + best_t1/2);
+       if (best_t0 % 2 + best_t1 % 2 == 2)
+               ++tcenter;
+       return tcenter - best_tm;
+}
+
+static __cpuinit void sync_tsc(void)
+{
+       int i, done = 0;
+       long delta, adj, adjust_latency = 0;
+       unsigned long flags, rt, master_time_stamp, bound;
+#if DEBUG_TSC_SYNC
+       static struct syncdebug {
+               long rt;        /* roundtrip time */
+               long master;    /* master's timestamp */
+               long diff;      /* difference between midpoint and master's 
timestamp */
+               long lat;       /* estimate of tsc adjustment latency */
+       } t[NUM_ROUNDS] __cpuinitdata;
+#endif
+
+       go[MASTER] = 1;
+
+       smp_call_function(sync_master, NULL, 1, 0);
+
+       while (go[MASTER])      /* wait for master to be ready */
+               no_cpu_relax();
+
+       spin_lock_irqsave(&tsc_sync_lock, flags);
+       {
+               for (i = 0; i < NUM_ROUNDS; ++i) {
+                       delta = get_delta(&rt, &master_time_stamp);
+                       if (delta == 0) {
+                               done = 1;       /* let's lock on to this... */
+                               bound = rt;
+                       }
+
+                       if (!done) {
+                               unsigned long t;
+                               if (i > 0) {
+                                       adjust_latency += -delta;
+                                       adj = -delta + adjust_latency/4;
+                               } else
+                                       adj = -delta;
+
+                               rdtscll(t);
+                               wrmsrl(MSR_IA32_TSC, t + adj);
+                       }
+#if DEBUG_TSC_SYNC
+                       t[i].rt = rt;
+                       t[i].master = master_time_stamp;
+                       t[i].diff = delta;
+                       t[i].lat = adjust_latency/4;
+#endif
+               }
+       }
+       spin_unlock_irqrestore(&tsc_sync_lock, flags);
+
+#if DEBUG_TSC_SYNC
+       for (i = 0; i < NUM_ROUNDS; ++i)
+               printk("rt=%5ld master=%5ld diff=%5ld adjlat=%5ld\n",
+                      t[i].rt, t[i].master, t[i].diff, t[i].lat);
+#endif
+
+       printk(KERN_INFO
+              "CPU %d: synchronized TSC with CPU %u (last diff %ld cycles, "
+              "maxerr %lu cycles)\n",
+              smp_processor_id(), boot_cpu_id, delta, rt);
 }
 
-/*
- * Synchronize TSC from BP to AP.
- */
-static void __cpuinit __sync_tsc_bp(int cpu)
+static void __cpuinit tsc_sync_wait(void)
 {
-       if (!cpu_has_tsc)
+       if (notscsync || !cpu_has_tsc)
                return;
-
-       /* Wait for AP */
-       while (atomic_read(&tsc_flag) == 0)
-               cpu_relax();
-       /* Save BPs TSC */
-       sync_core();
-       rdtscll(bp_tsc);
-       /* Don't do the sync core here to avoid too much latency. */
-       mb();
-       /* Start the AP */
-       _raw_spin_unlock(&tsc_sync_lock);
-       /* Wait for AP again */
-       while (atomic_read(&tsc_flag) < 2)
-               cpu_relax();
-       rdtscl(bp_tsc);
-       barrier();
+       printk(KERN_INFO "CPU %d: Syncing TSC to CPU %u.\n", smp_processor_id(),
+                       boot_cpu_id);
+       sync_tsc();
 }
 
-static void __cpuinit sync_tsc_bp(int cpu)
+static __init int notscsync_setup(char *s)
 {
-       int i;
-       for (i = 0; i < NR_LOOPS - 1; i++) {
-               __sync_tsc_bp(cpu);
-               sync_tsc_bp_init(1);
-       }
-       __sync_tsc_bp(cpu);
-       printk(KERN_INFO "Synced TSC of CPU %d difference %Ld\n",
-              cpu, ap_tsc - bp_tsc);
+       notscsync = 1;
+       return 0;
 }
+__setup("notscsync", notscsync_setup);
 
 static atomic_t init_deasserted __cpuinitdata;
 
@@ -315,11 +431,6 @@
        cpu_init();
        smp_callin();
 
-       /*
-        * Synchronize the TSC with the BP
-        */
-       sync_tsc_ap();
-
        /* otherwise gcc will move up the smp_processor_id before the cpu_init 
*/
        barrier();
 
@@ -334,7 +445,6 @@
                enable_8259A_irq(0);
        }
 
-
        enable_APIC_timer();
 
        /*
@@ -343,6 +453,11 @@
        cpu_set(smp_processor_id(), cpu_online_map);
        mb();
 
+       /* Wait for TSC sync to not schedule things before.
+          We still process interrupts, which could see an inconsistent
+          time in that window unfortunately. */
+       tsc_sync_wait();
+
        cpu_idle();
 }
 
@@ -531,7 +646,6 @@
                printk("failed fork for CPU %d\n", cpu);
                return PTR_ERR(idle);
        }
-       x86_cpu_to_apicid[cpu] = apicid;
 
        cpu_pda[cpu].pcurrent = idle;
 
@@ -600,8 +714,6 @@
 
                if (cpu_isset(cpu, cpu_callin_map)) {
                        /* number CPUs logically, starting from 1 (BSP is 0) */
-                       Dprintk("OK.\n");
-                       print_cpu_info(&cpu_data[cpu]);
                        Dprintk("CPU has booted.\n");
                } else {
                        boot_error = 1;
@@ -842,7 +954,6 @@
                      GET_APIC_ID(apic_read(APIC_ID)), boot_cpu_id);
                /* Or can we switch back to PIC here? */
        }
-       x86_cpu_to_apicid[0] = boot_cpu_id;
 
        /*
         * Now start the IO-APICs
@@ -889,18 +1000,14 @@
                printk("__cpu_up: bad cpu %d\n", cpu);
                return -EINVAL;
        }
-       sync_tsc_bp_init(1);
 
        /* Boot it! */
        err = do_boot_cpu(cpu, apicid);
        if (err < 0) {
-               sync_tsc_bp_init(0);
                Dprintk("do_boot_cpu failed %d\n", err);
                return err;
        }
 
-       sync_tsc_bp(cpu);
-
        /* Unleash the CPU! */
        Dprintk("waiting for cpu %d\n", cpu);
 
@@ -923,4 +1030,6 @@
 
        detect_siblings();
        time_init_gtod();
+
+       check_nmi_watchdog();
 }
diff -urN linux/arch/x86_64/kernel/time.c linux/arch/x86_64/kernel/time.c
--- linux/arch/x86_64/kernel/time.c     2005/04/29 11:15:05     1.36
+++ linux/arch/x86_64/kernel/time.c     2005/05/26 09:12:40     1.37
@@ -26,6 +26,8 @@
 #include <linux/sysdev.h>
 #include <linux/bcd.h>
 #include <linux/kallsyms.h>
+#include <linux/acpi.h>
+#include <acpi/achware.h>      /* for PM timer frequency */
 #include <asm/8253pit.h>
 #include <asm/pgtable.h>
 #include <asm/vsyscall.h>
@@ -396,6 +398,10 @@
                        (offset - vxtime.last)*(NSEC_PER_SEC/HZ) / hpet_tick;
 
                vxtime.last = offset;
+#ifdef CONFIG_X86_PM_TIMER
+       } else if (vxtime.mode == VXTIME_PMTMR) {
+               lost = pmtimer_mark_offset();
+#endif
        } else {
                offset = (((tsc - vxtime.last_tsc) *
                           vxtime.tsc_quot) >> 32) - (USEC_PER_SEC / HZ);
@@ -898,6 +904,13 @@
                        hpet_period;
                cpu_khz = hpet_calibrate_tsc();
                timename = "HPET";
+#ifdef CONFIG_X86_PM_TIMER
+       } else if (pmtmr_ioport) {
+               vxtime_hz = PM_TIMER_FREQUENCY;
+               timename = "PM";
+               pit_init();
+               cpu_khz = pit_calibrate_tsc();
+#endif
        } else {
                pit_init();
                cpu_khz = pit_calibrate_tsc();
@@ -923,35 +936,50 @@
 }
 
 /*
+ * Make an educated guess if the TSC is trustworthy and synchronized
+ * over all CPUs.
+ */
+static __init int unsynchronized_tsc(void)
+{
+#ifdef CONFIG_SMP
+       if (oem_force_hpet_timer())
+               return 1;
+       /* Intel systems are normally all synchronized. Exceptions
+          are handled in the OEM check above. */
+       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+               return 0;
+       /* All in a single socket - should be synchronized */
+       if (cpus_weight(cpu_core_map[0]) == num_online_cpus())
+               return 0;
+#endif
+       /* Assume multi socket systems are not synchronized */
+       return num_online_cpus() > 1;
+}
+
+/*
  * Decide after all CPUs are booted what mode gettimeofday should use.
  */
 void __init time_init_gtod(void)
 {
        char *timetype;
 
-       /*
-        * AMD systems with more than one CPU don't have fully synchronized
-        * TSCs. Always use HPET gettimeofday for these, although it is slower.
-        * Intel SMP systems usually have synchronized TSCs, so use always
-        * the TSC.
-        *
-        * Exceptions:
-        * IBM Summit2 checked by oem_force_hpet_timer().
-        * AMD dual core may also not need HPET. Check me.
-        *
-        * Can be turned off with "notsc".
-        */
-       if (num_online_cpus() > 1 &&
-           boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
-               notsc = 1;
-       /* Some systems will want to disable TSC and use HPET. */
-       if (oem_force_hpet_timer())
+       if (unsynchronized_tsc())
                notsc = 1;
        if (vxtime.hpet_address && notsc) {
                timetype = "HPET";
                vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
                vxtime.mode = VXTIME_HPET;
                do_gettimeoffset = do_gettimeoffset_hpet;
+#ifdef CONFIG_X86_PM_TIMER
+       /* Using PM for gettimeofday is quite slow, but we have no other
+          choice because the TSC is too unreliable on some systems. */
+       } else if (pmtmr_ioport && !vxtime.hpet_address && notsc) {
+               timetype = "PM";
+               do_gettimeoffset = do_gettimeoffset_pm;
+               vxtime.mode = VXTIME_PMTMR;
+               sysctl_vsyscall = 0;
+               printk(KERN_INFO "Disabling vsyscall due to use of PM timer\n");
+#endif
        } else {
                timetype = vxtime.hpet_address ? "HPET/TSC" : "PIT/TSC";
                vxtime.mode = VXTIME_TSC;
diff -urN linux/arch/x86_64/kernel/vsyscall.c 
linux/arch/x86_64/kernel/vsyscall.c
--- linux/arch/x86_64/kernel/vsyscall.c 2005/04/08 18:58:07     1.17
+++ linux/arch/x86_64/kernel/vsyscall.c 2005/05/26 09:12:40     1.18
@@ -65,7 +65,7 @@
                usec = (__xtime.tv_nsec / 1000) +
                        (__jiffies - __wall_jiffies) * (1000000 / HZ);
 
-               if (__vxtime.mode == VXTIME_TSC) {
+               if (__vxtime.mode != VXTIME_HPET) {
                        sync_core();
                        rdtscll(t);
                        if (t < __vxtime.last_tsc)
@@ -217,8 +217,9 @@
        BUG_ON((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime));
        BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)));
        map_vsyscall();
-       sysctl_vsyscall = 1;
+#ifdef CONFIG_SYSCTL
        register_sysctl_table(kernel_root_table2, 0);
+#endif
        return 0;
 }
 
diff -urN linux/arch/x86_64/mm/fault.c linux/arch/x86_64/mm/fault.c
--- linux/arch/x86_64/mm/fault.c        2005/04/29 11:15:05     1.28
+++ linux/arch/x86_64/mm/fault.c        2005/05/26 09:12:40     1.29
@@ -234,6 +234,8 @@
 
 /*
  * Handle a fault on the vmalloc or module mapping area
+ *
+ * This assumes no large pages in there.
  */
 static int vmalloc_fault(unsigned long address)
 {
@@ -272,7 +274,10 @@
        if (!pte_present(*pte_ref))
                return -1;
        pte = pte_offset_kernel(pmd, address);
-       if (!pte_present(*pte) || pte_page(*pte) != pte_page(*pte_ref))
+       /* Don't use pte_page here, because the mappings can point
+          outside mem_map, and the NUMA hash lookup cannot handle
+          that. */
+       if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref))
                BUG();
        __flush_tlb_all();
        return 0;
@@ -346,7 +351,9 @@
         * protection error (error_code & 1) == 0.
         */
        if (unlikely(address >= TASK_SIZE)) {
-               if (!(error_code & 5)) {
+               if (!(error_code & 5) &&
+                     ((address >= VMALLOC_START && address < VMALLOC_END) ||
+                      (address >= MODULES_VADDR && address < MODULES_END))) {
                        if (vmalloc_fault(address) < 0)
                                goto bad_area_nosemaphore;
                        return;
diff -urN linux/arch/x86_64/mm/ioremap.c linux/arch/x86_64/mm/ioremap.c
--- linux/arch/x86_64/mm/ioremap.c      2005/04/08 18:58:08     1.20
+++ linux/arch/x86_64/mm/ioremap.c      2005/05/26 09:12:40     1.21
@@ -133,7 +133,7 @@
                                        unsigned long flags)
 {
        int err = 0;
-       if (flags && phys_addr + size - 1 < (end_pfn_map << PAGE_SHIFT)) {
+       if (phys_addr + size - 1 < (end_pfn_map << PAGE_SHIFT)) {
                unsigned long npages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
                unsigned long vaddr = (unsigned long) __va(phys_addr);
 
@@ -214,7 +214,7 @@
                remove_vm_area((void *)(PAGE_MASK & (unsigned long) addr));
                return NULL;
        }
-       if (ioremap_change_attr(phys_addr, size, flags) < 0) {
+       if (flags && ioremap_change_attr(phys_addr, size, flags) < 0) {
                area->flags &= 0xffffff;
                vunmap(addr);
                return NULL;
@@ -251,7 +251,7 @@
 
 void iounmap(volatile void __iomem *addr)
 {
-       struct vm_struct *p, **pprev;
+       struct vm_struct *p;
 
        if (addr <= high_memory) 
                return; 
@@ -260,24 +260,11 @@
                return;
 
        write_lock(&vmlist_lock);
-       for (p = vmlist, pprev = &vmlist; p != NULL; pprev = &p->next, p = 
*pprev)
-               if (p->addr == (void *)(PAGE_MASK & (unsigned long)addr))
-                       break;
-       if (!p) { 
-               printk("__iounmap: bad address %p\n", addr);
-               goto out_unlock;
-       }
-       *pprev = p->next;
-       unmap_vm_area(p);
-       if ((p->flags >> 20) &&
-               p->phys_addr + p->size - 1 < virt_to_phys(high_memory)) {
-               /* p->size includes the guard page, but cpa doesn't like that */
-               change_page_attr(virt_to_page(__va(p->phys_addr)),
-                                p->size >> PAGE_SHIFT,
-                                PAGE_KERNEL);
-               global_flush_tlb();
-       } 
-out_unlock:
+       p = __remove_vm_area((void *)((unsigned long)addr & PAGE_MASK));
+       if (!p)
+               printk("iounmap: bad address %p\n", addr);
+       else if (p->flags >> 20)
+               ioremap_change_attr(p->phys_addr, p->size, 0);
        write_unlock(&vmlist_lock);
        kfree(p); 
 }
diff -urN linux/crypto/crypto_null.c linux/crypto/crypto_null.c
--- linux/crypto/crypto_null.c  2004/04/28 13:54:54     1.4
+++ linux/crypto/crypto_null.c  2005/05/26 09:12:40     1.5
@@ -21,6 +21,7 @@
 #include <linux/mm.h>
 #include <asm/scatterlist.h>
 #include <linux/crypto.h>
+#include <linux/string.h>
 
 #define NULL_KEY_SIZE          0
 #define NULL_BLOCK_SIZE                1
@@ -28,11 +29,13 @@
 
 static int null_compress(void *ctx, const u8 *src, unsigned int slen,
                          u8 *dst, unsigned int *dlen)
-{ return 0; }
-
-static int null_decompress(void *ctx, const u8 *src, unsigned int slen,
-                           u8 *dst, unsigned int *dlen)
-{ return 0; }
+{
+       if (slen > *dlen)
+               return -EINVAL;
+       memcpy(dst, src, slen);
+       *dlen = slen;
+       return 0;
+}
 
 static void null_init(void *ctx)
 { }
@@ -47,11 +50,10 @@
                        unsigned int keylen, u32 *flags)
 { return 0; }
 
-static void null_encrypt(void *ctx, u8 *dst, const u8 *src)
-{ }
-
-static void null_decrypt(void *ctx, u8 *dst, const u8 *src)
-{ }
+static void null_crypt(void *ctx, u8 *dst, const u8 *src)
+{
+       memcpy(dst, src, NULL_BLOCK_SIZE);
+}
 
 static struct crypto_alg compress_null = {
        .cra_name               =       "compress_null",
@@ -62,7 +64,7 @@
        .cra_list               =       LIST_HEAD_INIT(compress_null.cra_list),
        .cra_u                  =       { .compress = {
        .coa_compress           =       null_compress,
-       .coa_decompress         =       null_decompress } }
+       .coa_decompress         =       null_compress } }
 };
 
 static struct crypto_alg digest_null = {
@@ -90,8 +92,8 @@
        .cia_min_keysize        =       NULL_KEY_SIZE,
        .cia_max_keysize        =       NULL_KEY_SIZE,
        .cia_setkey             =       null_setkey,
-       .cia_encrypt            =       null_encrypt,
-       .cia_decrypt            =       null_decrypt } }
+       .cia_encrypt            =       null_crypt,
+       .cia_decrypt            =       null_crypt } }
 };
 
 MODULE_ALIAS("compress_null");
diff -urN linux/crypto/internal.h linux/crypto/internal.h
--- linux/crypto/internal.h     2004/09/19 12:30:08     1.10
+++ linux/crypto/internal.h     2005/05/26 09:12:40     1.11
@@ -38,7 +38,7 @@
 
 static inline void crypto_yield(struct crypto_tfm *tfm)
 {
-       if (!in_softirq())
+       if (!in_atomic())
                cond_resched();
 }
 
diff -urN linux/drivers/base/Makefile linux/drivers/base/Makefile
--- linux/drivers/base/Makefile 2005/02/07 02:54:43     1.20
+++ linux/drivers/base/Makefile 2005/05/26 09:12:40     1.21
@@ -1,6 +1,6 @@
 # Makefile for the Linux device tree
 
-obj-y                  := core.o sys.o interface.o bus.o \
+obj-y                  := core.o sys.o bus.o \
                           driver.o class.o class_simple.o platform.o \
                           cpu.o firmware.o init.o map.o dmapool.o \
                           attribute_container.o transport_class.o
diff -urN linux/drivers/base/bus.c linux/drivers/base/bus.c
--- linux/drivers/base/bus.c    2005/05/19 12:08:20     1.35
+++ linux/drivers/base/bus.c    2005/05/26 09:12:40     1.36
@@ -390,7 +390,6 @@
                sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
                sysfs_remove_link(&dev->kobj, "driver");
                list_del_init(&dev->driver_list);
-               device_detach_shutdown(dev);
                if (drv->remove)
                        drv->remove(dev);
                dev->driver = NULL;
diff -urN linux/drivers/base/core.c linux/drivers/base/core.c
--- linux/drivers/base/core.c   2005/05/19 12:08:20     1.42
+++ linux/drivers/base/core.c   2005/05/26 09:12:40     1.43
@@ -31,8 +31,6 @@
 #define to_dev(obj) container_of(obj, struct device, kobj)
 #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
 
-extern struct attribute * dev_default_attrs[];
-
 static ssize_t
 dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
 {
@@ -89,7 +87,6 @@
 static struct kobj_type ktype_device = {
        .release        = device_release,
        .sysfs_ops      = &dev_sysfs_ops,
-       .default_attrs  = dev_default_attrs,
 };
 
 
@@ -248,6 +245,7 @@
 
        if ((error = kobject_add(&dev->kobj)))
                goto Error;
+       kobject_hotplug(&dev->kobj, KOBJ_ADD);
        if ((error = device_pm_add(dev)))
                goto PMError;
        if ((error = bus_add_device(dev)))
@@ -260,14 +258,13 @@
        /* notify platform of device entry */
        if (platform_notify)
                platform_notify(dev);
-
-       kobject_hotplug(&dev->kobj, KOBJ_ADD);
  Done:
        put_device(dev);
        return error;
  BusError:
        device_pm_remove(dev);
  PMError:
+       kobject_hotplug(&dev->kobj, KOBJ_REMOVE);
        kobject_del(&dev->kobj);
  Error:
        if (parent)
diff -urN linux/drivers/base/interface.c linux/drivers/base/interface.c
--- linux/drivers/base/Attic/interface.c        2005-05-26 10:12:40.663169000 
+0100     1.14
+++ linux/drivers/base/Attic/interface.c        1970/01/01 00:00:00+0100
@@ -1,51 +0,0 @@
-/*
- * drivers/base/interface.c - common driverfs interface that's exported to
- *     the world for all devices.
- *
- * Copyright (c) 2002-3 Patrick Mochel
- * Copyright (c) 2002-3 Open Source Development Labs
- *
- * This file is released under the GPLv2
- *
- */
-
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-
-/**
- *     detach_state - control the default power state for the device.
- *
- *     This is the state the device enters when it's driver module is
- *     unloaded. The value is an unsigned integer, in the range of 0-4.
- *     '0' indicates 'On', so no action will be taken when the driver is
- *     unloaded. This is the default behavior.
- *     '4' indicates 'Off', meaning the driver core will call the driver's
- *     shutdown method to quiesce the device.
- *     1-3 indicate a low-power state for the device to enter via the
- *     driver's suspend method.
- */
-
-static ssize_t detach_show(struct device * dev, char * buf)
-{
-       return sprintf(buf, "%u\n", dev->detach_state);
-}
-
-static ssize_t detach_store(struct device * dev, const char * buf, size_t n)
-{
-       u32 state;
-       state = simple_strtoul(buf, NULL, 10);
-       if (state > 4)
-               return -EINVAL;
-       dev->detach_state = state;
-       return n;
-}
-
-static DEVICE_ATTR(detach_state, 0644, detach_show, detach_store);
-
-
-struct attribute * dev_default_attrs[] = {
-       &dev_attr_detach_state.attr,
-       NULL,
-};
diff -urN linux/drivers/base/power/power.h linux/drivers/base/power/power.h
--- linux/drivers/base/power/power.h    2005/01/13 14:05:50     1.5
+++ linux/drivers/base/power/power.h    2005/05/26 09:12:40     1.6
@@ -1,18 +1,7 @@
-
-
-enum {
-       DEVICE_PM_ON,
-       DEVICE_PM1,
-       DEVICE_PM2,
-       DEVICE_PM3,
-       DEVICE_PM_OFF,
-};
-
 /*
  * shutdown.c
  */
 
-extern int device_detach_shutdown(struct device *);
 extern void device_shutdown(void);
 
 
diff -urN linux/drivers/base/power/resume.c linux/drivers/base/power/resume.c
--- linux/drivers/base/power/resume.c   2004/11/15 11:49:24     1.6
+++ linux/drivers/base/power/resume.c   2005/05/26 09:12:40     1.7
@@ -22,8 +22,17 @@
 
 int resume_device(struct device * dev)
 {
-       if (dev->bus && dev->bus->resume)
+       if (dev->power.pm_parent
+                       && dev->power.pm_parent->power.power_state) {
+               dev_err(dev, "PM: resume from %d, parent %s still %d\n",
+                       dev->power.power_state,
+                       dev->power.pm_parent->bus_id,
+                       dev->power.pm_parent->power.power_state);
+       }
+       if (dev->bus && dev->bus->resume) {
+               dev_dbg(dev,"resuming\n");
                return dev->bus->resume(dev);
+       }
        return 0;
 }
 
diff -urN linux/drivers/base/power/shutdown.c 
linux/drivers/base/power/shutdown.c
--- linux/drivers/base/power/shutdown.c 2004/06/26 15:15:13     1.5
+++ linux/drivers/base/power/shutdown.c 2005/05/26 09:12:40     1.6
@@ -19,20 +19,6 @@
 extern struct subsystem devices_subsys;
 
 
-int device_detach_shutdown(struct device * dev)
-{
-       if (!dev->detach_state)
-               return 0;
-
-       if (dev->detach_state == DEVICE_PM_OFF) {
-               if (dev->driver && dev->driver->shutdown)
-                       dev->driver->shutdown(dev);
-               return 0;
-       }
-       return dpm_runtime_suspend(dev, dev->detach_state);
-}
-
-
 /**
  * We handle system devices differently - we suspend and shut them
  * down last and resume them first. That way, we don't do anything stupid like
@@ -52,13 +38,12 @@
        struct device * dev;
 
        down_write(&devices_subsys.rwsem);
-       list_for_each_entry_reverse(dev, &devices_subsys.kset.list, kobj.entry) 
{
-               pr_debug("shutting down %s: ", dev->bus_id);
+       list_for_each_entry_reverse(dev, &devices_subsys.kset.list,
+                               kobj.entry) {
                if (dev->driver && dev->driver->shutdown) {
-                       pr_debug("Ok\n");
+                       dev_dbg(dev, "shutdown\n");
                        dev->driver->shutdown(dev);
-               } else
-                       pr_debug("Ignored.\n");
+               }
        }
        up_write(&devices_subsys.rwsem);
 
diff -urN linux/drivers/base/power/suspend.c linux/drivers/base/power/suspend.c
--- linux/drivers/base/power/suspend.c  2005/04/08 18:58:10     1.8
+++ linux/drivers/base/power/suspend.c  2005/05/26 09:12:40     1.9
@@ -39,12 +39,25 @@
 {
        int error = 0;
 
-       dev_dbg(dev, "suspending\n");
+       if (dev->power.power_state) {
+               dev_dbg(dev, "PM: suspend %d-->%d\n",
+                       dev->power.power_state, state);
+       }
+       if (dev->power.pm_parent
+                       && dev->power.pm_parent->power.power_state) {
+               dev_err(dev,
+                       "PM: suspend %d->%d, parent %s already %d\n",
+                       dev->power.power_state, state,
+                       dev->power.pm_parent->bus_id,
+                       dev->power.pm_parent->power.power_state);
+       }
 
        dev->power.prev_state = dev->power.power_state;
 
-       if (dev->bus && dev->bus->suspend && !dev->power.power_state)
+       if (dev->bus && dev->bus->suspend && !dev->power.power_state) {
+               dev_dbg(dev, "suspending\n");
                error = dev->bus->suspend(dev, state);
+       }
 
        return error;
 }
diff -urN linux/drivers/block/ioctl.c linux/drivers/block/ioctl.c
--- linux/drivers/block/ioctl.c 2005/01/25 04:28:11     1.11
+++ linux/drivers/block/ioctl.c 2005/05/26 09:12:40     1.12
@@ -237,3 +237,5 @@
        }
        return ret;
 }
+
+EXPORT_SYMBOL_GPL(blkdev_ioctl);
diff -urN linux/drivers/block/pktcdvd.c linux/drivers/block/pktcdvd.c
--- linux/drivers/block/pktcdvd.c       2005/04/08 18:58:10     1.5
+++ linux/drivers/block/pktcdvd.c       2005/05/26 09:12:40     1.6
@@ -914,8 +914,10 @@
                bio = node->bio;
                zone = ZONE(bio->bi_sector, pd);
                list_for_each_entry(p, &pd->cdrw.pkt_active_list, list) {
-                       if (p->sector == zone)
+                       if (p->sector == zone) {
+                               bio = NULL;
                                goto try_next_bio;
+                       }
                }
                break;
 try_next_bio:
@@ -2019,7 +2021,13 @@
        BUG_ON(pd->refcnt < 0);
 
        pd->refcnt++;
-       if (pd->refcnt == 1) {
+       if (pd->refcnt > 1) {
+               if ((file->f_mode & FMODE_WRITE) &&
+                   !test_bit(PACKET_WRITABLE, &pd->flags)) {
+                       ret = -EBUSY;
+                       goto out_dec;
+               }
+       } else {
                if (pkt_open_dev(pd, file->f_mode & FMODE_WRITE)) {
                        ret = -EIO;
                        goto out_dec;
@@ -2406,7 +2414,7 @@
        case CDROM_LAST_WRITTEN:
        case CDROM_SEND_PACKET:
        case SCSI_IOCTL_SEND_COMMAND:
-               return ioctl_by_bdev(pd->bdev, cmd, arg);
+               return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg);
 
        case CDROMEJECT:
                /*
@@ -2414,7 +2422,7 @@
                 * have to unlock it or else the eject command fails.
                 */
                pkt_lock_door(pd, 0);
-               return ioctl_by_bdev(pd->bdev, cmd, arg);
+               return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg);
 
        default:
                printk("pktcdvd: Unknown ioctl for %s (%x)\n", pd->name, cmd);
diff -urN linux/drivers/char/raw.c linux/drivers/char/raw.c
--- linux/drivers/char/raw.c    2004/07/20 20:21:18     1.42
+++ linux/drivers/char/raw.c    2005/05/26 09:12:40     1.43
@@ -122,7 +122,7 @@
 {
        struct block_device *bdev = filp->private_data;
 
-       return ioctl_by_bdev(bdev, command, arg);
+       return blkdev_ioctl(bdev->bd_inode, NULL, command, arg);
 }
 
 static void bind_device(struct raw_config_request *rq)
diff -urN linux/drivers/char/ipmi/ipmi_devintf.c 
linux/drivers/char/ipmi/ipmi_devintf.c
--- linux/drivers/char/ipmi/ipmi_devintf.c      2004/08/24 15:10:09     1.12
+++ linux/drivers/char/ipmi/ipmi_devintf.c      2005/05/26 09:12:40     1.13
@@ -44,6 +44,7 @@
 #include <linux/ipmi.h>
 #include <asm/semaphore.h>
 #include <linux/init.h>
+#include <linux/device.h>
 
 #define IPMI_DEVINTF_VERSION "v33"
 
@@ -519,15 +520,21 @@
                 " interface.  Other values will set the major device number"
                 " to that value.");
 
+static struct class *ipmi_class;
+
 static void ipmi_new_smi(int if_num)
 {
-       devfs_mk_cdev(MKDEV(ipmi_major, if_num),
-                     S_IFCHR | S_IRUSR | S_IWUSR,
+       dev_t dev = MKDEV(ipmi_major, if_num);
+
+       devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
                      "ipmidev/%d", if_num);
+
+       class_simple_device_add(ipmi_class, dev, NULL, "ipmi%d", if_num);
 }
 
 static void ipmi_smi_gone(int if_num)
 {
+       class_simple_device_remove(ipmi_class, MKDEV(ipmi_major, if_num));
        devfs_remove("ipmidev/%d", if_num);
 }
 
@@ -548,8 +555,15 @@
        printk(KERN_INFO "ipmi device interface version "
               IPMI_DEVINTF_VERSION "\n");
 
+       ipmi_class = class_simple_create(THIS_MODULE, "ipmi");
+       if (IS_ERR(ipmi_class)) {
+               printk(KERN_ERR "ipmi: can't register device class\n");
+               return PTR_ERR(ipmi_class);
+       }
+
        rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops);
        if (rv < 0) {
+               class_simple_destroy(ipmi_class);
                printk(KERN_ERR "ipmi: can't get major %d\n", ipmi_major);
                return rv;
        }
@@ -563,6 +577,7 @@
        rv = ipmi_smi_watcher_register(&smi_watcher);
        if (rv) {
                unregister_chrdev(ipmi_major, DEVICE_NAME);
+               class_simple_destroy(ipmi_class);
                printk(KERN_WARNING "ipmi: can't register smi watcher\n");
                return rv;
        }
@@ -573,6 +588,7 @@
 
 static __exit void cleanup_ipmi(void)
 {
+       class_simple_destroy(ipmi_class);
        ipmi_smi_watcher_unregister(&smi_watcher);
        devfs_remove(DEVICE_NAME);
        unregister_chrdev(ipmi_major, DEVICE_NAME);
diff -urN linux/drivers/char/watchdog/i8xx_tco.c 
linux/drivers/char/watchdog/i8xx_tco.c
--- linux/drivers/char/watchdog/i8xx_tco.c      2005/02/07 02:54:45     1.6
+++ linux/drivers/char/watchdog/i8xx_tco.c      2005/05/26 09:12:41     1.7
@@ -382,6 +382,7 @@
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2,      PCI_ANY_ID, 
PCI_ANY_ID, },
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0,      PCI_ANY_ID, 
PCI_ANY_ID, },
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1,      PCI_ANY_ID, 
PCI_ANY_ID, },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,       PCI_ANY_ID, 
PCI_ANY_ID, },
        { 0, },                 /* End of list */
 };
 MODULE_DEVICE_TABLE (pci, i8xx_tco_pci_tbl);
diff -urN linux/drivers/i2c/busses/i2c-keywest.c 
linux/drivers/i2c/busses/i2c-keywest.c
--- linux/drivers/i2c/busses/i2c-keywest.c      2005/03/18 17:37:17     1.8
+++ linux/drivers/i2c/busses/i2c-keywest.c      2005/05/26 09:12:41     1.9
@@ -516,6 +516,11 @@
        u32 *psteps, *prate;
        int rc;
 
+       if (np->n_intrs < 1 || np->n_addrs < 1) {
+               printk(KERN_ERR "%s: Missing interrupt or address !\n",
+                      np->full_name);
+               return -ENODEV;
+       }
        if (pmac_low_i2c_lock(np))
                return -ENODEV;
 
diff -urN linux/drivers/ide/ide-proc.c linux/drivers/ide/ide-proc.c
--- linux/drivers/ide/ide-proc.c        2005/04/08 18:58:14     1.42
+++ linux/drivers/ide/ide-proc.c        2005/05/26 09:12:41     1.43
@@ -516,6 +516,6 @@
 
 void proc_ide_destroy(void)
 {
-       remove_proc_entry("ide/drivers", proc_ide_root);
+       remove_proc_entry("drivers", proc_ide_root);
        remove_proc_entry("ide", NULL);
 }
diff -urN linux/drivers/ieee1394/Kconfig linux/drivers/ieee1394/Kconfig
--- linux/drivers/ieee1394/Kconfig      2005/03/18 17:37:18     1.10
+++ linux/drivers/ieee1394/Kconfig      2005/05/26 09:12:41     1.11
@@ -84,11 +84,6 @@
          To compile this driver as a module, say M here: the
          module will be called pcilynx.
 
-# Non-maintained pcilynx options
-# if [ "$CONFIG_IEEE1394_PCILYNX" != "n" ]; then
-#     bool '    Use PCILynx local RAM' CONFIG_IEEE1394_PCILYNX_LOCALRAM
-#     bool '    Support for non-IEEE1394 local ports' 
CONFIG_IEEE1394_PCILYNX_PORTS
-# fi
 config IEEE1394_OHCI1394
        tristate "OHCI-1394 support"
        depends on PCI && IEEE1394
diff -urN linux/drivers/ieee1394/ieee1394_core.c 
linux/drivers/ieee1394/ieee1394_core.c
--- linux/drivers/ieee1394/ieee1394_core.c      2005/03/18 17:37:19     1.43
+++ linux/drivers/ieee1394/ieee1394_core.c      2005/05/26 09:12:41     1.44
@@ -520,7 +520,7 @@
 
        if (!packet->no_waiter || packet->expect_response) {
                atomic_inc(&packet->refcnt);
-               packet->sendtime = jiffies;
+               packet->sendtime = jiffies + 10 * HZ;
                skb_queue_tail(&host->pending_packet_queue, packet->skb);
        }
 
@@ -1248,7 +1248,6 @@
 EXPORT_SYMBOL(hpsb_make_isopacket);
 EXPORT_SYMBOL(hpsb_read);
 EXPORT_SYMBOL(hpsb_write);
-EXPORT_SYMBOL(hpsb_lock);
 EXPORT_SYMBOL(hpsb_packet_success);
 
 /** highlevel.c **/
diff -urN linux/drivers/ieee1394/ieee1394_transactions.c 
linux/drivers/ieee1394/ieee1394_transactions.c
--- linux/drivers/ieee1394/ieee1394_transactions.c      2005/03/18 17:37:19     
1.26
+++ linux/drivers/ieee1394/ieee1394_transactions.c      2005/05/26 09:12:41     
1.27
@@ -535,6 +535,7 @@
         return retval;
 }
 
+#if 0
 
 int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
              u64 addr, int extcode, quadlet_t *data, quadlet_t arg)
@@ -599,3 +600,5 @@
 
        return retval;
 }
+
+#endif  /*  0  */
diff -urN linux/drivers/ieee1394/ieee1394_transactions.h 
linux/drivers/ieee1394/ieee1394_transactions.h
--- linux/drivers/ieee1394/ieee1394_transactions.h      2003/09/09 16:41:00     
1.9
+++ linux/drivers/ieee1394/ieee1394_transactions.h      2005/05/26 09:12:41     
1.10
@@ -53,12 +53,5 @@
              u64 addr, quadlet_t *buffer, size_t length);
 int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
               u64 addr, quadlet_t *buffer, size_t length);
-int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
-             u64 addr, int extcode, quadlet_t *data, quadlet_t arg);
-int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation,
-               u64 addr, int extcode, octlet_t *data, octlet_t arg);
-int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int 
generation,
-                   quadlet_t *buffer, size_t length, u32 specifier_id,
-                   unsigned int version);
 
 #endif /* _IEEE1394_TRANSACTIONS_H */
diff -urN linux/drivers/ieee1394/nodemgr.c linux/drivers/ieee1394/nodemgr.c
--- linux/drivers/ieee1394/nodemgr.c    2005/04/08 18:58:14     1.36
+++ linux/drivers/ieee1394/nodemgr.c    2005/05/26 09:12:41     1.37
@@ -1005,8 +1005,7 @@
        return ud;
 
 unit_directory_error:
-       if (ud != NULL)
-               kfree(ud);
+       kfree(ud);
        return NULL;
 }
 
diff -urN linux/drivers/ieee1394/ohci1394.c linux/drivers/ieee1394/ohci1394.c
--- linux/drivers/ieee1394/ohci1394.c   2005/05/19 12:08:23     1.46
+++ linux/drivers/ieee1394/ohci1394.c   2005/05/26 09:12:41     1.47
@@ -2931,7 +2931,7 @@
                kfree(d->prg_cpu);
                kfree(d->prg_bus);
        }
-       if (d->spb) kfree(d->spb);
+       kfree(d->spb);
 
        /* Mark this context as freed. */
        d->ohci = NULL;
diff -urN linux/drivers/ieee1394/ohci1394.h linux/drivers/ieee1394/ohci1394.h
--- linux/drivers/ieee1394/ohci1394.h   2004/09/19 12:30:10     1.25
+++ linux/drivers/ieee1394/ohci1394.h   2005/05/26 09:12:41     1.26
@@ -236,6 +236,9 @@
 
 static inline int cross_bound(unsigned long addr, unsigned int size)
 {
+       if (size == 0)
+               return 0;
+
        if (size > PAGE_SIZE)
                return 1;
 
diff -urN linux/drivers/ieee1394/pcilynx.c linux/drivers/ieee1394/pcilynx.c
--- linux/drivers/ieee1394/pcilynx.c    2005/04/08 18:58:14     1.40
+++ linux/drivers/ieee1394/pcilynx.c    2005/05/26 09:12:41     1.41
@@ -43,6 +43,7 @@
 #include <linux/fs.h>
 #include <linux/poll.h>
 #include <linux/kdev_t.h>
+#include <linux/dma-mapping.h>
 #include <asm/byteorder.h>
 #include <asm/atomic.h>
 #include <asm/io.h>
@@ -834,327 +835,6 @@
  * IEEE-1394 functionality section END *
  ***************************************/
 
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
-/* VFS functions for local bus / aux device access.  Access to those
- * is implemented as a character device instead of block devices
- * because buffers are not wanted for this.  Therefore llseek (from
- * VFS) can be used for these char devices with obvious effects.
- */
-static int mem_open(struct inode*, struct file*);
-static int mem_release(struct inode*, struct file*);
-static unsigned int aux_poll(struct file*, struct poll_table_struct*);
-static loff_t mem_llseek(struct file*, loff_t, int);
-static ssize_t mem_read (struct file*, char*, size_t, loff_t*);
-static ssize_t mem_write(struct file*, const char*, size_t, loff_t*);
-
-
-static struct file_operations aux_ops = {
-       .owner =        THIS_MODULE,
-        .read =         mem_read,
-        .write =        mem_write,
-        .poll =         aux_poll,
-        .llseek =       mem_llseek,
-        .open =         mem_open,
-        .release =      mem_release,
-};
-
-
-static void aux_setup_pcls(struct ti_lynx *lynx)
-{
-        struct ti_pcl pcl;
-
-        pcl.next = PCL_NEXT_INVALID;
-        pcl.user_data = pcl_bus(lynx, lynx->dmem_pcl);
-        put_pcl(lynx, lynx->dmem_pcl, &pcl);
-}
-
-static int mem_open(struct inode *inode, struct file *file)
-{
-        int cid = iminor(inode);
-        enum { t_rom, t_aux, t_ram } type;
-        struct memdata *md;
-
-        if (cid < PCILYNX_MINOR_AUX_START) {
-                /* just for completeness */
-                return -ENXIO;
-        } else if (cid < PCILYNX_MINOR_ROM_START) {
-                cid -= PCILYNX_MINOR_AUX_START;
-                if (cid >= num_of_cards || !cards[cid].aux_port)
-                        return -ENXIO;
-                type = t_aux;
-        } else if (cid < PCILYNX_MINOR_RAM_START) {
-                cid -= PCILYNX_MINOR_ROM_START;
-                if (cid >= num_of_cards || !cards[cid].local_rom)
-                        return -ENXIO;
-                type = t_rom;
-        } else {
-                /* WARNING: Know what you are doing when opening RAM.
-                 * It is currently used inside the driver! */
-                cid -= PCILYNX_MINOR_RAM_START;
-                if (cid >= num_of_cards || !cards[cid].local_ram)
-                        return -ENXIO;
-                type = t_ram;
-        }
-
-        md = (struct memdata *)kmalloc(sizeof(struct memdata), SLAB_KERNEL);
-        if (md == NULL)
-                return -ENOMEM;
-
-        md->lynx = &cards[cid];
-        md->cid = cid;
-
-        switch (type) {
-        case t_rom:
-                md->type = rom;
-                break;
-        case t_ram:
-                md->type = ram;
-                break;
-        case t_aux:
-                atomic_set(&md->aux_intr_last_seen,
-                           atomic_read(&cards[cid].aux_intr_seen));
-                md->type = aux;
-                break;
-        }
-
-        file->private_data = md;
-
-        return 0;
-}
-
-static int mem_release(struct inode *inode, struct file *file)
-{
-        kfree(file->private_data);
-        return 0;
-}
-
-static unsigned int aux_poll(struct file *file, poll_table *pt)
-{
-        struct memdata *md = (struct memdata *)file->private_data;
-        int cid = md->cid;
-        unsigned int mask;
-
-        /* reading and writing is always allowed */
-        mask = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM;
-
-        if (md->type == aux) {
-                poll_wait(file, &cards[cid].aux_intr_wait, pt);
-
-                if (atomic_read(&md->aux_intr_last_seen)
-                    != atomic_read(&cards[cid].aux_intr_seen)) {
-                        mask |= POLLPRI;
-                        atomic_inc(&md->aux_intr_last_seen);
-                }
-        }
-
-        return mask;
-}
-
-loff_t mem_llseek(struct file *file, loff_t offs, int orig)
-{
-        loff_t newoffs;
-
-        switch (orig) {
-        case 0:
-                newoffs = offs;
-                break;
-        case 1:
-                newoffs = offs + file->f_pos;
-                break;
-        case 2:
-                newoffs = PCILYNX_MAX_MEMORY + 1 + offs;
-                break;
-        default:
-                return -EINVAL;
-        }
-
-        if (newoffs < 0 || newoffs > PCILYNX_MAX_MEMORY + 1) return -EINVAL;
-
-        file->f_pos = newoffs;
-        return newoffs;
-}
-
-/*
- * do not DMA if count is too small because this will have a serious impact
- * on performance - the value 2400 was found by experiment and may not work
- * everywhere as good as here - use mem_mindma option for modules to change
- */
-static short mem_mindma = 2400;
-module_param(mem_mindma, short, 0444);
-MODULE_PARM_DESC(mem_mindma, "Minimum amount of data required to use DMA");
-
-static ssize_t mem_dmaread(struct memdata *md, u32 physbuf, ssize_t count,
-                           int offset)
-{
-        pcltmp_t pcltmp;
-        struct ti_pcl *pcl;
-        size_t retval;
-        int i;
-        DECLARE_WAITQUEUE(wait, current);
-
-        count &= ~3;
-        count = min(count, 53196);
-        retval = count;
-
-        if (reg_read(md->lynx, DMA_CHAN_CTRL(CHANNEL_LOCALBUS))
-            & DMA_CHAN_CTRL_BUSY) {
-                PRINT(KERN_WARNING, md->lynx->id, "DMA ALREADY ACTIVE!");
-        }
-
-        reg_write(md->lynx, LBUS_ADDR, md->type | offset);
-
-        pcl = edit_pcl(md->lynx, md->lynx->dmem_pcl, &pcltmp);
-        pcl->buffer[0].control = PCL_CMD_LBUS_TO_PCI | min(count, 4092);
-        pcl->buffer[0].pointer = physbuf;
-        count -= 4092;
-
-        i = 0;
-        while (count > 0) {
-                i++;
-                pcl->buffer[i].control = min(count, 4092);
-                pcl->buffer[i].pointer = physbuf + i * 4092;
-                count -= 4092;
-        }
-        pcl->buffer[i].control |= PCL_LAST_BUFF;
-        commit_pcl(md->lynx, md->lynx->dmem_pcl, &pcltmp);
-
-        set_current_state(TASK_INTERRUPTIBLE);
-        add_wait_queue(&md->lynx->mem_dma_intr_wait, &wait);
-        run_sub_pcl(md->lynx, md->lynx->dmem_pcl, 2, CHANNEL_LOCALBUS);
-
-        schedule();
-        while (reg_read(md->lynx, DMA_CHAN_CTRL(CHANNEL_LOCALBUS))
-               & DMA_CHAN_CTRL_BUSY) {
-                if (signal_pending(current)) {
-                        retval = -EINTR;
-                        break;
-                }
-                schedule();
-        }
-
-        reg_write(md->lynx, DMA_CHAN_CTRL(CHANNEL_LOCALBUS), 0);
-        remove_wait_queue(&md->lynx->mem_dma_intr_wait, &wait);
-
-        if (reg_read(md->lynx, DMA_CHAN_CTRL(CHANNEL_LOCALBUS))
-            & DMA_CHAN_CTRL_BUSY) {
-                PRINT(KERN_ERR, md->lynx->id, "DMA STILL ACTIVE!");
-        }
-
-        return retval;
-}
-
-static ssize_t mem_read(struct file *file, char *buffer, size_t count,
-                        loff_t *offset)
-{
-        struct memdata *md = (struct memdata *)file->private_data;
-        ssize_t bcount;
-        size_t alignfix;
-       loff_t off = *offset; /* avoid useless 64bit-arithmetic */
-        ssize_t retval;
-        void *membase;
-
-        if ((off + count) > PCILYNX_MAX_MEMORY+1) {
-                count = PCILYNX_MAX_MEMORY+1 - off;
-        }
-        if (count == 0 || off > PCILYNX_MAX_MEMORY) {
-                return -ENOSPC;
-        }
-
-        switch (md->type) {
-        case rom:
-                membase = md->lynx->local_rom;
-                break;
-        case ram:
-                membase = md->lynx->local_ram;
-                break;
-        case aux:
-                membase = md->lynx->aux_port;
-                break;
-        default:
-                panic("pcilynx%d: unsupported md->type %d in %s",
-                      md->lynx->id, md->type, __FUNCTION__);
-        }
-
-        down(&md->lynx->mem_dma_mutex);
-
-        if (count < mem_mindma) {
-                memcpy_fromio(md->lynx->mem_dma_buffer, membase+off, count);
-                goto out;
-        }
-
-        bcount = count;
-        alignfix = 4 - (off % 4);
-        if (alignfix != 4) {
-                if (bcount < alignfix) {
-                        alignfix = bcount;
-                }
-                memcpy_fromio(md->lynx->mem_dma_buffer, membase+off,
-                              alignfix);
-                if (bcount == alignfix) {
-                        goto out;
-                }
-                bcount -= alignfix;
-                off += alignfix;
-        }
-
-        while (bcount >= 4) {
-                retval = mem_dmaread(md, md->lynx->mem_dma_buffer_dma
-                                     + count - bcount, bcount, off);
-                if (retval < 0) return retval;
-
-                bcount -= retval;
-                off += retval;
-        }
-
-        if (bcount) {
-                memcpy_fromio(md->lynx->mem_dma_buffer + count - bcount,
-                              membase+off, bcount);
-        }
-
- out:
-        retval = copy_to_user(buffer, md->lynx->mem_dma_buffer, count);
-        up(&md->lynx->mem_dma_mutex);
-
-       if (retval) return -EFAULT;
-        *offset += count;
-        return count;
-}
-
-
-static ssize_t mem_write(struct file *file, const char *buffer, size_t count,
-                         loff_t *offset)
-{
-        struct memdata *md = (struct memdata *)file->private_data;
-
-        if (((*offset) + count) > PCILYNX_MAX_MEMORY+1) {
-                count = PCILYNX_MAX_MEMORY+1 - *offset;
-        }
-        if (count == 0 || *offset > PCILYNX_MAX_MEMORY) {
-                return -ENOSPC;
-        }
-
-        /* FIXME: dereferencing pointers to PCI mem doesn't work everywhere */
-        switch (md->type) {
-        case aux:
-               if (copy_from_user(md->lynx->aux_port+(*offset), buffer, count))
-                       return -EFAULT;
-                break;
-        case ram:
-               if (copy_from_user(md->lynx->local_ram+(*offset), buffer, 
count))
-                       return -EFAULT;
-                break;
-        case rom:
-                /* the ROM may be writeable */
-               if (copy_from_user(md->lynx->local_rom+(*offset), buffer, 
count))
-                       return -EFAULT;
-                break;
-        }
-
-        file->f_pos += count;
-        return count;
-}
-#endif /* CONFIG_IEEE1394_PCILYNX_PORTS */
-
 
 /********************************************************
  * Global stuff (interrupt handler, init/shutdown code) *
@@ -1181,18 +861,6 @@
         reg_write(lynx, LINK_INT_STATUS, linkint);
         reg_write(lynx, PCI_INT_STATUS, intmask);
 
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
-        if (intmask & PCI_INT_AUX_INT) {
-                atomic_inc(&lynx->aux_intr_seen);
-                wake_up_interruptible(&lynx->aux_intr_wait);
-        }
-
-        if (intmask & PCI_INT_DMA_HLT(CHANNEL_LOCALBUS)) {
-                wake_up_interruptible(&lynx->mem_dma_intr_wait);
-        }
-#endif
-
-
         if (intmask & PCI_INT_1394) {
                 if (linkint & LINK_INT_PHY_TIMEOUT) {
                         PRINT(KERN_INFO, lynx->id, "PHY timeout occurred");
@@ -1484,15 +1152,9 @@
                 pci_free_consistent(lynx->dev, PAGE_SIZE, lynx->rcv_page,
                                     lynx->rcv_page_dma);
         case have_aux_buf:
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
-                pci_free_consistent(lynx->dev, 65536, lynx->mem_dma_buffer,
-                                    lynx->mem_dma_buffer_dma);
-#endif
         case have_pcl_mem:
-#ifndef CONFIG_IEEE1394_PCILYNX_LOCALRAM
                 pci_free_consistent(lynx->dev, LOCALRAM_SIZE, lynx->pcl_mem,
                                     lynx->pcl_mem_dma);
-#endif
         case clear:
                 /* do nothing - already freed */
                 ;
@@ -1524,7 +1186,7 @@
 
         error = -ENXIO;
 
-        if (pci_set_dma_mask(dev, 0xffffffff))
+        if (pci_set_dma_mask(dev, DMA_32BIT_MASK))
                 FAIL("DMA address limits not supported for PCILynx hardware");
         if (pci_enable_device(dev))
                 FAIL("failed to enable PCILynx hardware");
@@ -1546,7 +1208,6 @@
         spin_lock_init(&lynx->lock);
         spin_lock_init(&lynx->phy_reg_lock);
 
-#ifndef CONFIG_IEEE1394_PCILYNX_LOCALRAM
         lynx->pcl_mem = pci_alloc_consistent(dev, LOCALRAM_SIZE,
                                              &lynx->pcl_mem_dma);
 
@@ -1558,16 +1219,6 @@
         } else {
                 FAIL("failed to allocate PCL memory area");
         }
-#endif
-
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
-        lynx->mem_dma_buffer = pci_alloc_consistent(dev, 65536,
-                                                    &lynx->mem_dma_buffer_dma);
-        if (lynx->mem_dma_buffer == NULL) {
-                FAIL("failed to allocate DMA buffer for aux");
-        }
-        lynx->state = have_aux_buf;
-#endif
 
         lynx->rcv_page = pci_alloc_consistent(dev, PAGE_SIZE,
                                               &lynx->rcv_page_dma);
@@ -1597,13 +1248,6 @@
                 FAIL("failed to remap registers - card not accessible");
         }
 
-#ifdef CONFIG_IEEE1394_PCILYNX_LOCALRAM
-        if (lynx->local_ram == NULL) {
-                FAIL("failed to remap local RAM which is required for "
-                     "operation");
-        }
-#endif
-
         reg_set_bits(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET);
         /* Fix buggy cards with autoboot pin not tied low: */
         reg_write(lynx, DMA0_CHAN_CTRL, 0);
@@ -1624,13 +1268,6 @@
 
         /* alloc_pcl return values are not checked, it is expected that the
          * provided PCL space is sufficient for the initial allocations */
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
-        if (lynx->aux_port != NULL) {
-                lynx->dmem_pcl = alloc_pcl(lynx);
-                aux_setup_pcls(lynx);
-                sema_init(&lynx->mem_dma_mutex, 1);
-        }
-#endif
         lynx->rcv_pcl = alloc_pcl(lynx);
         lynx->rcv_pcl_start = alloc_pcl(lynx);
         lynx->async.pcl = alloc_pcl(lynx);
@@ -1647,12 +1284,6 @@
 
         reg_write(lynx, PCI_INT_ENABLE, PCI_INT_DMA_ALL);
 
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
-        reg_set_bits(lynx, PCI_INT_ENABLE, PCI_INT_AUX_INT);
-        init_waitqueue_head(&lynx->mem_dma_intr_wait);
-        init_waitqueue_head(&lynx->aux_intr_wait);
-#endif
-
        tasklet_init(&lynx->iso_rcv.tq, (void (*)(unsigned long))iso_rcv_bh,
                     (unsigned long)lynx);
 
@@ -1944,37 +1575,18 @@
 {
         int ret;
 
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
-        if (register_chrdev(PCILYNX_MAJOR, PCILYNX_DRIVER_NAME, &aux_ops)) {
-                PRINT_G(KERN_ERR, "allocation of char major number %d failed",
-                        PCILYNX_MAJOR);
-                return -EBUSY;
-        }
-#endif
-
         ret = pci_register_driver(&lynx_pci_driver);
         if (ret < 0) {
                 PRINT_G(KERN_ERR, "PCI module init failed");
-                goto free_char_dev;
+                return ret;
         }
 
         return 0;
-
- free_char_dev:
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
-        unregister_chrdev(PCILYNX_MAJOR, PCILYNX_DRIVER_NAME);
-#endif
-
-        return ret;
 }
 
 static void __exit pcilynx_cleanup(void)
 {
         pci_unregister_driver(&lynx_pci_driver);
-
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
-        unregister_chrdev(PCILYNX_MAJOR, PCILYNX_DRIVER_NAME);
-#endif
 }
 
 
diff -urN linux/drivers/ieee1394/pcilynx.h linux/drivers/ieee1394/pcilynx.h
--- linux/drivers/ieee1394/pcilynx.h    2004/12/04 18:16:03     1.15
+++ linux/drivers/ieee1394/pcilynx.h    2005/05/26 09:12:41     1.16
@@ -55,16 +55,6 @@
         void __iomem *aux_port;
        quadlet_t bus_info_block[5];
 
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
-        atomic_t aux_intr_seen;
-        wait_queue_head_t aux_intr_wait;
-
-        void *mem_dma_buffer;
-        dma_addr_t mem_dma_buffer_dma;
-        struct semaphore mem_dma_mutex;
-        wait_queue_head_t mem_dma_intr_wait;
-#endif
-
         /*
          * use local RAM of LOCALRAM_SIZE bytes for PCLs, which allows for
          * LOCALRAM_SIZE * 8 PCLs (each sized 128 bytes);
@@ -72,11 +62,9 @@
          */
         u8 pcl_bmap[LOCALRAM_SIZE / 1024];
 
-#ifndef CONFIG_IEEE1394_PCILYNX_LOCALRAM
        /* point to PCLs memory area if needed */
        void *pcl_mem;
         dma_addr_t pcl_mem_dma;
-#endif
 
         /* PCLs for local mem / aux transfers */
         pcl_t dmem_pcl;
@@ -378,39 +366,6 @@
 #define pcloffs(MEMBER) (offsetof(struct ti_pcl, MEMBER))
 
 
-#ifdef CONFIG_IEEE1394_PCILYNX_LOCALRAM
-
-static inline void put_pcl(const struct ti_lynx *lynx, pcl_t pclid,
-                           const struct ti_pcl *pcl)
-{
-        int i;
-        u32 *in = (u32 *)pcl;
-        u32 *out = (u32 *)(lynx->local_ram + pclid * sizeof(struct ti_pcl));
-
-        for (i = 0; i < 32; i++, out++, in++) {
-                writel(*in, out);
-        }
-}
-
-static inline void get_pcl(const struct ti_lynx *lynx, pcl_t pclid,
-                           struct ti_pcl *pcl)
-{
-        int i;
-        u32 *out = (u32 *)pcl;
-        u32 *in = (u32 *)(lynx->local_ram + pclid * sizeof(struct ti_pcl));
-
-        for (i = 0; i < 32; i++, out++, in++) {
-                *out = readl(in);
-        }
-}
-
-static inline u32 pcl_bus(const struct ti_lynx *lynx, pcl_t pclid)
-{
-        return pci_resource_start(lynx->dev, 1) + pclid * sizeof(struct 
ti_pcl);
-}
-
-#else /* CONFIG_IEEE1394_PCILYNX_LOCALRAM */
-
 static inline void put_pcl(const struct ti_lynx *lynx, pcl_t pclid,
                            const struct ti_pcl *pcl)
 {
@@ -431,10 +386,8 @@
         return lynx->pcl_mem_dma + pclid * sizeof(struct ti_pcl);
 }
 
-#endif /* CONFIG_IEEE1394_PCILYNX_LOCALRAM */
-
 
-#if defined (CONFIG_IEEE1394_PCILYNX_LOCALRAM) || defined (__BIG_ENDIAN)
+#if defined (__BIG_ENDIAN)
 typedef struct ti_pcl pcltmp_t;
 
 static inline struct ti_pcl *edit_pcl(const struct ti_lynx *lynx, pcl_t pclid,
diff -urN linux/drivers/ieee1394/video1394.c linux/drivers/ieee1394/video1394.c
--- linux/drivers/ieee1394/video1394.c  2005/04/08 18:58:14     1.44
+++ linux/drivers/ieee1394/video1394.c  2005/05/26 09:12:41     1.45
@@ -35,6 +35,11 @@
  *
  */
 
+/* Markus Tavenrath <speedygoo@speedygoo.de> :
+   - fixed checks for valid buffer-numbers in video1394_icotl
+   - changed the ways the dma prg's are used, now it's possible to use
+     even a single dma buffer
+*/
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
@@ -112,6 +117,7 @@
        struct it_dma_prg **it_prg;
 
        unsigned int *buffer_status;
+       unsigned int *buffer_prg_assignment;
         struct timeval *buffer_time; /* time when the buffer was received */
        unsigned int *last_used_cmd; /* For ISO Transmit with
                                        variable sized packets only ! */
@@ -180,23 +186,14 @@
                kfree(d->prg_reg);
        }
 
-       if (d->ir_prg)
-               kfree(d->ir_prg);
-
-       if (d->it_prg)
-               kfree(d->it_prg);
-
-       if (d->buffer_status)
-               kfree(d->buffer_status);
-       if (d->buffer_time)
-               kfree(d->buffer_time);
-       if (d->last_used_cmd)
-               kfree(d->last_used_cmd);
-       if (d->next_buffer)
-               kfree(d->next_buffer);
-
+       kfree(d->ir_prg);
+       kfree(d->it_prg);
+       kfree(d->buffer_status);
+       kfree(d->buffer_prg_assignment);
+       kfree(d->buffer_time);
+       kfree(d->last_used_cmd);
+       kfree(d->next_buffer);
        list_del(&d->link);
-
        kfree(d);
 
        return 0;
@@ -230,7 +227,7 @@
        /* Init the regions for easy cleanup */
        dma_region_init(&d->dma);
 
-       if (dma_region_alloc(&d->dma, d->num_desc * d->buf_size, ohci->dev,
+       if (dma_region_alloc(&d->dma, (d->num_desc - 1) * d->buf_size, 
ohci->dev,
                             PCI_DMA_BIDIRECTIONAL)) {
                PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma 
buffer");
                free_dma_iso_ctx(d);
@@ -342,6 +339,8 @@
 
        d->buffer_status = kmalloc(d->num_desc * sizeof(unsigned int),
                                   GFP_KERNEL);
+       d->buffer_prg_assignment = kmalloc(d->num_desc * sizeof(unsigned int),
+                                  GFP_KERNEL);
        d->buffer_time = kmalloc(d->num_desc * sizeof(struct timeval),
                                   GFP_KERNEL);
        d->last_used_cmd = kmalloc(d->num_desc * sizeof(unsigned int),
@@ -354,6 +353,11 @@
                free_dma_iso_ctx(d);
                return NULL;
        }
+       if (d->buffer_prg_assignment == NULL) {
+               PRINT(KERN_ERR, ohci->host->id, "Failed to allocate 
buffer_prg_assignment");
+               free_dma_iso_ctx(d);
+               return NULL;
+       }
        if (d->buffer_time == NULL) {
                PRINT(KERN_ERR, ohci->host->id, "Failed to allocate 
buffer_time");
                free_dma_iso_ctx(d);
@@ -370,6 +374,7 @@
                return NULL;
        }
        memset(d->buffer_status, 0, d->num_desc * sizeof(unsigned int));
+       memset(d->buffer_prg_assignment, 0, d->num_desc * sizeof(unsigned int));
        memset(d->buffer_time, 0, d->num_desc * sizeof(struct timeval));
        memset(d->last_used_cmd, 0, d->num_desc * sizeof(unsigned int));
        memset(d->next_buffer, -1, d->num_desc * sizeof(int));
@@ -379,7 +384,7 @@
        PRINT(KERN_INFO, ohci->host->id, "Iso %s DMA: %d buffers "
              "of size %d allocated for a frame size %d, each with %d prgs",
              (type == OHCI_ISO_RECEIVE) ? "receive" : "transmit",
-             d->num_desc, d->buf_size, d->frame_size, d->nb_cmd);
+             d->num_desc - 1, d->buf_size, d->frame_size, d->nb_cmd);
 
        return d;
 }
@@ -394,11 +399,36 @@
        d->ir_prg[n][i].status = cpu_to_le32(d->left_size);
 }
 
+static void reprogram_dma_ir_prg(struct dma_iso_ctx *d, int n, int buffer, int 
flags)
+{
+       struct dma_cmd *ir_prg = d->ir_prg[n];
+       unsigned long buf = (unsigned long)d->dma.kvirt + buffer * d->buf_size;
+       int i;
+
+       d->buffer_prg_assignment[n] = buffer;
+
+       ir_prg[0].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, buf -
+                               (unsigned long)d->dma.kvirt));
+       ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
+                               (buf + 4) - (unsigned long)d->dma.kvirt));
+
+       for (i=2;i<d->nb_cmd-1;i++) {
+               ir_prg[i].address = 
cpu_to_le32(dma_region_offset_to_bus(&d->dma,
+                                               (buf+(i-1)*PAGE_SIZE) -
+                                               (unsigned long)d->dma.kvirt));
+       }
+
+       ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
+                                 DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size);
+       ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
+                                 (buf+(i-1)*PAGE_SIZE) - (unsigned 
long)d->dma.kvirt));
+}
+
 static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n, int flags)
 {
        struct dma_cmd *ir_prg = d->ir_prg[n];
        struct dma_prog_region *ir_reg = &d->prg_reg[n];
-       unsigned long buf = (unsigned long)d->dma.kvirt + n * d->buf_size;
+       unsigned long buf = (unsigned long)d->dma.kvirt;
        int i;
 
        /* the first descriptor will read only 4 bytes */
@@ -508,7 +538,7 @@
        for (i = 0; i < d->num_desc; i++) {
                if (d->ir_prg[i][d->nb_cmd-1].status & cpu_to_le32(0xFFFF0000)) 
{
                        reset_ir_status(d, i);
-                       d->buffer_status[i] = VIDEO1394_BUFFER_READY;
+                       d->buffer_status[d->buffer_prg_assignment[i]] = 
VIDEO1394_BUFFER_READY;
                        do_gettimeofday(&d->buffer_time[i]);
                }
        }
@@ -585,7 +615,7 @@
                        int next = d->next_buffer[i];
                        put_timestamp(ohci, d, next);
                        d->it_prg[i][d->last_used_cmd[i]].end.status = 0;
-                       d->buffer_status[i] = VIDEO1394_BUFFER_READY;
+                       d->buffer_status[d->buffer_prg_assignment[i]] = 
VIDEO1394_BUFFER_READY;
                }
        }
 
@@ -595,11 +625,25 @@
                wake_up_interruptible(&d->waitq);
 }
 
+static void reprogram_dma_it_prg(struct dma_iso_ctx  *d, int n, int buffer)
+{
+       struct it_dma_prg *it_prg = d->it_prg[n];
+       unsigned long buf = (unsigned long)d->dma.kvirt + buffer * d->buf_size;
+       int i;
+
+       d->buffer_prg_assignment[n] = buffer;
+       for (i=0;i<d->nb_cmd;i++) {
+         it_prg[i].end.address =
+               cpu_to_le32(dma_region_offset_to_bus(&d->dma,
+                       (buf+i*d->packet_size) - (unsigned long)d->dma.kvirt));
+       }
+}
+
 static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag)
 {
        struct it_dma_prg *it_prg = d->it_prg[n];
        struct dma_prog_region *it_reg = &d->prg_reg[n];
-       unsigned long buf = (unsigned long)d->dma.kvirt + n * d->buf_size;
+       unsigned long buf = (unsigned long)d->dma.kvirt;
        int i;
        d->last_used_cmd[n] = d->nb_cmd - 1;
        for (i=0;i<d->nb_cmd;i++) {
@@ -796,7 +840,7 @@
 
                if (cmd == VIDEO1394_IOC_LISTEN_CHANNEL) {
                        d = alloc_dma_iso_ctx(ohci, OHCI_ISO_RECEIVE,
-                                             v.nb_buffers, v.buf_size,
+                                             v.nb_buffers + 1, v.buf_size,
                                              v.channel, 0);
 
                        if (d == NULL) {
@@ -817,7 +861,7 @@
                }
                else {
                        d = alloc_dma_iso_ctx(ohci, OHCI_ISO_TRANSMIT,
-                                             v.nb_buffers, v.buf_size,
+                                             v.nb_buffers + 1, v.buf_size,
                                              v.channel, v.packet_size);
 
                        if (d == NULL) {
@@ -889,6 +933,7 @@
        {
                struct video1394_wait v;
                struct dma_iso_ctx *d;
+               int next_prg;
 
                if (copy_from_user(&v, argp, sizeof(v)))
                        return -EFAULT;
@@ -896,7 +941,7 @@
                d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
                if (d == NULL) return -EFAULT;
 
-               if ((v.buffer<0) || (v.buffer>d->num_desc)) {
+               if ((v.buffer<0) || (v.buffer>=d->num_desc - 1)) {
                        PRINT(KERN_ERR, ohci->host->id,
                              "Buffer %d out of range",v.buffer);
                        return -EINVAL;
@@ -913,12 +958,14 @@
 
                d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
 
+               next_prg = (d->last_buffer + 1) % d->num_desc;
                if (d->last_buffer>=0)
                        d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress =
-                               
cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0)
+                               
cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg], 0)
                                        & 0xfffffff0) | 0x1);
 
-               d->last_buffer = v.buffer;
+               d->last_buffer = next_prg;
+               reprogram_dma_ir_prg(d, d->last_buffer, v.buffer, d->flags);
 
                d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = 0;
 
@@ -930,7 +977,7 @@
 
                        /* Tell the controller where the first program is */
                        reg_write(ohci, d->cmdPtr,
-                               
dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0) | 0x1);
+                                 
dma_prog_region_offset_to_bus(&d->prg_reg[d->last_buffer], 0) | 0x1);
 
                        /* Run IR context */
                        reg_write(ohci, d->ctrlSet, 0x8000);
@@ -951,7 +998,7 @@
        {
                struct video1394_wait v;
                struct dma_iso_ctx *d;
-               int i;
+               int i = 0;
 
                if (copy_from_user(&v, argp, sizeof(v)))
                        return -EFAULT;
@@ -959,7 +1006,7 @@
                d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
                if (d == NULL) return -EFAULT;
 
-               if ((v.buffer<0) || (v.buffer>d->num_desc)) {
+               if ((v.buffer<0) || (v.buffer>d->num_desc - 1)) {
                        PRINT(KERN_ERR, ohci->host->id,
                              "Buffer %d out of range",v.buffer);
                        return -EINVAL;
@@ -1005,9 +1052,9 @@
                 * Look ahead to see how many more buffers have been received
                 */
                i=0;
-               while (d->buffer_status[(v.buffer+1)%d->num_desc]==
+               while (d->buffer_status[(v.buffer+1)%(d->num_desc - 1)]==
                       VIDEO1394_BUFFER_READY) {
-                       v.buffer=(v.buffer+1)%d->num_desc;
+                       v.buffer=(v.buffer+1)%(d->num_desc - 1);
                        i++;
                }
                spin_unlock_irqrestore(&d->lock, flags);
@@ -1023,6 +1070,7 @@
                struct video1394_wait v;
                unsigned int *psizes = NULL;
                struct dma_iso_ctx *d;
+               int next_prg;
 
                if (copy_from_user(&v, argp, sizeof(v)))
                        return -EFAULT;
@@ -1030,7 +1078,7 @@
                d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
                if (d == NULL) return -EFAULT;
 
-               if ((v.buffer<0) || (v.buffer>d->num_desc)) {
+               if ((v.buffer<0) || (v.buffer>=d->num_desc - 1)) {
                        PRINT(KERN_ERR, ohci->host->id,
                              "Buffer %d out of range",v.buffer);
                        return -EINVAL;
@@ -1056,19 +1104,19 @@
 
                spin_lock_irqsave(&d->lock,flags);
 
+               // last_buffer is last_prg
+               next_prg = (d->last_buffer + 1) % d->num_desc;
                if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) {
                        PRINT(KERN_ERR, ohci->host->id,
                              "Buffer %d is already used",v.buffer);
                        spin_unlock_irqrestore(&d->lock,flags);
-                       if (psizes)
-                               kfree(psizes);
+                       kfree(psizes);
                        return -EBUSY;
                }
 
                if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) {
                        initialize_dma_it_prg_var_packet_queue(
-                               d, v.buffer, psizes,
-                               ohci);
+                               d, next_prg, psizes, ohci);
                }
 
                d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
@@ -1076,16 +1124,17 @@
                if (d->last_buffer >= 0) {
                        d->it_prg[d->last_buffer]
                                [ d->last_used_cmd[d->last_buffer] 
].end.branchAddress =
-                                       
cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer],
+                                       
cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg],
                                                0) & 0xfffffff0) | 0x3);
 
                        d->it_prg[d->last_buffer]
                                [ d->last_used_cmd[d->last_buffer] 
].begin.branchAddress =
-                                       
cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer],
+                                       
cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg],
                                                0) & 0xfffffff0) | 0x3);
-                       d->next_buffer[d->last_buffer] = v.buffer;
+                       d->next_buffer[d->last_buffer] = (v.buffer + 1) % 
(d->num_desc - 1);
                }
-               d->last_buffer = v.buffer;
+               d->last_buffer = next_prg;
+               reprogram_dma_it_prg(d, d->last_buffer, v.buffer);
                d->next_buffer[d->last_buffer] = -1;
 
                
d->it_prg[d->last_buffer][d->last_used_cmd[d->last_buffer]].end.branchAddress = 
0;
@@ -1100,7 +1149,7 @@
 
                        /* Tell the controller where the first program is */
                        reg_write(ohci, d->cmdPtr,
-                               
dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0) | 0x3);
+                               
dma_prog_region_offset_to_bus(&d->prg_reg[next_prg], 0) | 0x3);
 
                        /* Run IT context */
                        reg_write(ohci, d->ctrlSet, 0x8000);
@@ -1116,9 +1165,7 @@
                        }
                }
 
-               if (psizes)
-                       kfree(psizes);
-
+               kfree(psizes);
                return 0;
 
        }
@@ -1133,7 +1180,7 @@
                d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
                if (d == NULL) return -EFAULT;
 
-               if ((v.buffer<0) || (v.buffer>d->num_desc)) {
+               if ((v.buffer<0) || (v.buffer>=d->num_desc-1)) {
                        PRINT(KERN_ERR, ohci->host->id,
                              "Buffer %d out of range",v.buffer);
                        return -EINVAL;
diff -urN linux/drivers/input/keyboard/atkbd.c 
linux/drivers/input/keyboard/atkbd.c
--- linux/drivers/input/keyboard/atkbd.c        2005/05/19 12:08:23     1.26
+++ linux/drivers/input/keyboard/atkbd.c        2005/05/26 09:12:41     1.27
@@ -465,8 +465,10 @@
                        if (atkbd->softrepeat) return 0;
 
                        i = j = 0;
-                       while (i < 32 && period[i] < dev->rep[REP_PERIOD]) i++;
-                       while (j < 4 && delay[j] < dev->rep[REP_DELAY]) j++;
+                       while (i < 31 && period[i] < dev->rep[REP_PERIOD])
+                               i++;
+                       while (j < 3 && delay[j] < dev->rep[REP_DELAY])
+                               j++;
                        dev->rep[REP_PERIOD] = period[i];
                        dev->rep[REP_DELAY] = delay[j];
                        param[0] = i | (j << 5);
diff -urN linux/drivers/input/mouse/alps.c linux/drivers/input/mouse/alps.c
--- linux/drivers/input/mouse/alps.c    2005/03/18 17:37:22     1.3
+++ linux/drivers/input/mouse/alps.c    2005/05/26 09:12:41     1.4
@@ -341,6 +341,8 @@
        unsigned char param[4];
        int version;
 
+       psmouse_reset(psmouse);
+
        if (!(priv->i = alps_get_model(psmouse, &version)))
                return -1;
 
@@ -395,7 +397,7 @@
        }
 
        if (param[0] & 0x04) {
-               printk(KERN_INFO "  Enabling hardware tapping\n");
+               printk(KERN_INFO "alps.c: Enabling hardware tapping\n");
                if (alps_tap_mode(psmouse, 1))
                        printk(KERN_WARNING "alps.c: Failed to enable hardware 
tapping\n");
        }
diff -urN linux/drivers/input/serio/serio.c linux/drivers/input/serio/serio.c
--- linux/drivers/input/serio/serio.c   2005/03/18 17:37:23     1.21
+++ linux/drivers/input/serio/serio.c   2005/05/26 09:12:41     1.22
@@ -388,6 +388,24 @@
        return sprintf(buf, "%02x\n", serio->id.extra);
 }
 
+static DEVICE_ATTR(type, S_IRUGO, serio_show_id_type, NULL);
+static DEVICE_ATTR(proto, S_IRUGO, serio_show_id_proto, NULL);
+static DEVICE_ATTR(id, S_IRUGO, serio_show_id_id, NULL);
+static DEVICE_ATTR(extra, S_IRUGO, serio_show_id_extra, NULL);
+
+static struct attribute *serio_device_id_attrs[] = {
+       &dev_attr_type.attr,
+       &dev_attr_proto.attr,
+       &dev_attr_id.attr,
+       &dev_attr_extra.attr,
+       NULL
+};
+
+static struct attribute_group serio_id_attr_group = {
+       .name   = "id",
+       .attrs  = serio_device_id_attrs,
+};
+
 static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t 
count)
 {
        struct serio *serio = to_serio_port(dev);
@@ -444,10 +462,6 @@
 
 static struct device_attribute serio_device_attrs[] = {
        __ATTR(description, S_IRUGO, serio_show_description, NULL),
-       __ATTR(id_type, S_IRUGO, serio_show_id_type, NULL),
-       __ATTR(id_proto, S_IRUGO, serio_show_id_proto, NULL),
-       __ATTR(id_id, S_IRUGO, serio_show_id_id, NULL),
-       __ATTR(id_extra, S_IRUGO, serio_show_id_extra, NULL),
        __ATTR(drvctl, S_IWUSR, NULL, serio_rebind_driver),
        __ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, 
serio_set_bind_mode),
        __ATTR_NULL
@@ -498,6 +512,7 @@
        if (serio->start)
                serio->start(serio);
        device_add(&serio->dev);
+       sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group);
        serio->registered = 1;
 }
 
@@ -526,6 +541,7 @@
        }
 
        if (serio->registered) {
+               sysfs_remove_group(&serio->dev.kobj, &serio_id_attr_group);
                device_del(&serio->dev);
                list_del_init(&serio->node);
                serio->registered = 0;
@@ -779,7 +795,6 @@
        struct serio *serio = to_serio_port(dev);
 
        if (!serio->drv || !serio->drv->reconnect || 
serio->drv->reconnect(serio)) {
-               serio_disconnect_port(serio);
                /*
                 * Driver re-probing can take a while, so better let kseriod
                 * deal with it.
diff -urN linux/drivers/input/serio/serport.c 
linux/drivers/input/serio/serport.c
--- linux/drivers/input/serio/serport.c 2005/03/18 17:37:23     1.14
+++ linux/drivers/input/serio/serport.c 2005/05/26 09:12:41     1.15
@@ -27,11 +27,15 @@
 MODULE_ALIAS_LDISC(N_MOUSE);
 
 #define SERPORT_BUSY   1
+#define SERPORT_ACTIVE 2
+#define SERPORT_DEAD   3
 
 struct serport {
        struct tty_struct *tty;
        wait_queue_head_t wait;
        struct serio *serio;
+       struct serio_device_id id;
+       spinlock_t lock;
        unsigned long flags;
 };
 
@@ -45,11 +49,29 @@
        return -(serport->tty->driver->write(serport->tty, &data, 1) != 1);
 }
 
+static int serport_serio_open(struct serio *serio)
+{
+       struct serport *serport = serio->port_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&serport->lock, flags);
+       set_bit(SERPORT_ACTIVE, &serport->flags);
+       spin_unlock_irqrestore(&serport->lock, flags);
+
+       return 0;
+}
+
+
 static void serport_serio_close(struct serio *serio)
 {
        struct serport *serport = serio->port_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&serport->lock, flags);
+       clear_bit(SERPORT_ACTIVE, &serport->flags);
+       set_bit(SERPORT_DEAD, &serport->flags);
+       spin_unlock_irqrestore(&serport->lock, flags);
 
-       serport->serio->id.type = 0;
        wake_up_interruptible(&serport->wait);
 }
 
@@ -61,36 +83,21 @@
 static int serport_ldisc_open(struct tty_struct *tty)
 {
        struct serport *serport;
-       struct serio *serio;
-       char name[64];
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       serport = kmalloc(sizeof(struct serport), GFP_KERNEL);
-       serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
-       if (unlikely(!serport || !serio)) {
-               kfree(serport);
-               kfree(serio);
+       serport = kcalloc(1, sizeof(struct serport), GFP_KERNEL);
+       if (!serport)
                return -ENOMEM;
-       }
 
-       memset(serport, 0, sizeof(struct serport));
-       serport->serio = serio;
-       set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
        serport->tty = tty;
-       tty->disc_data = serport;
-
-       memset(serio, 0, sizeof(struct serio));
-       strlcpy(serio->name, "Serial port", sizeof(serio->name));
-       snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty, 
name));
-       serio->id.type = SERIO_RS232;
-       serio->write = serport_serio_write;
-       serio->close = serport_serio_close;
-       serio->port_data = serport;
-
+       spin_lock_init(&serport->lock);
        init_waitqueue_head(&serport->wait);
 
+       tty->disc_data = serport;
+       set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+
        return 0;
 }
 
@@ -100,7 +107,8 @@
 
 static void serport_ldisc_close(struct tty_struct *tty)
 {
-       struct serport *serport = (struct serport*) tty->disc_data;
+       struct serport *serport = (struct serport *) tty->disc_data;
+
        kfree(serport);
 }
 
@@ -116,9 +124,19 @@
 static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char 
*cp, char *fp, int count)
 {
        struct serport *serport = (struct serport*) tty->disc_data;
+       unsigned long flags;
        int i;
+
+       spin_lock_irqsave(&serport->lock, flags);
+
+       if (!test_bit(SERPORT_ACTIVE, &serport->flags))
+               goto out;
+
        for (i = 0; i < count; i++)
                serio_interrupt(serport->serio, cp[i], 0, NULL);
+
+out:
+       spin_unlock_irqrestore(&serport->lock, flags);
 }
 
 /*
@@ -141,16 +159,33 @@
 static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, 
unsigned char __user * buf, size_t nr)
 {
        struct serport *serport = (struct serport*) tty->disc_data;
+       struct serio *serio;
        char name[64];
 
        if (test_and_set_bit(SERPORT_BUSY, &serport->flags))
                return -EBUSY;
 
+       serport->serio = serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL);
+       if (!serio)
+               return -ENOMEM;
+
+       strlcpy(serio->name, "Serial port", sizeof(serio->name));
+       snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty, 
name));
+       serio->id = serport->id;
+       serio->id.type = SERIO_RS232;
+       serio->write = serport_serio_write;
+       serio->open = serport_serio_open;
+       serio->close = serport_serio_close;
+       serio->port_data = serport;
+
        serio_register_port(serport->serio);
        printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));
-       wait_event_interruptible(serport->wait, !serport->serio->id.type);
+
+       wait_event_interruptible(serport->wait, test_bit(SERPORT_DEAD, 
&serport->flags));
        serio_unregister_port(serport->serio);
+       serport->serio = NULL;
 
+       clear_bit(SERPORT_DEAD, &serport->flags);
        clear_bit(SERPORT_BUSY, &serport->flags);
 
        return 0;
@@ -163,16 +198,15 @@
 static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, 
unsigned int cmd, unsigned long arg)
 {
        struct serport *serport = (struct serport*) tty->disc_data;
-       struct serio *serio = serport->serio;
        unsigned long type;
 
        if (cmd == SPIOCSTYPE) {
                if (get_user(type, (unsigned long __user *) arg))
                        return -EFAULT;
 
-               serio->id.proto = type & 0x000000ff;
-               serio->id.id    = (type & 0x0000ff00) >> 8;
-               serio->id.extra = (type & 0x00ff0000) >> 16;
+               serport->id.proto = type & 0x000000ff;
+               serport->id.id    = (type & 0x0000ff00) >> 8;
+               serport->id.extra = (type & 0x00ff0000) >> 16;
 
                return 0;
        }
@@ -182,9 +216,13 @@
 
 static void serport_ldisc_write_wakeup(struct tty_struct * tty)
 {
-       struct serport *sp = (struct serport *) tty->disc_data;
+       struct serport *serport = (struct serport *) tty->disc_data;
+       unsigned long flags;
 
-       serio_drv_write_wakeup(sp->serio);
+       spin_lock_irqsave(&serport->lock, flags);
+       if (test_bit(SERPORT_ACTIVE, &serport->flags))
+               serio_drv_write_wakeup(serport->serio);
+       spin_unlock_irqrestore(&serport->lock, flags);
 }
 
 /*
diff -urN linux/drivers/md/linear.c linux/drivers/md/linear.c
--- linux/drivers/md/linear.c   2005/01/13 14:06:05     1.34
+++ linux/drivers/md/linear.c   2005/05/26 09:12:41     1.35
@@ -269,9 +269,8 @@
                 * split it.
                 */
                struct bio_pair *bp;
-               bp = bio_split(bio, bio_split_pool, 
-                              (bio->bi_sector + (bio->bi_size >> 9) -
-                               (tmp_dev->offset + tmp_dev->size))<<1);
+               bp = bio_split(bio, bio_split_pool,
+                              ((tmp_dev->offset + tmp_dev->size)<<1) - 
bio->bi_sector);
                if (linear_make_request(q, &bp->bio1))
                        generic_make_request(&bp->bio1);
                if (linear_make_request(q, &bp->bio2))
diff -urN linux/drivers/md/multipath.c linux/drivers/md/multipath.c
--- linux/drivers/md/multipath.c        2005/05/19 12:08:23     1.36
+++ linux/drivers/md/multipath.c        2005/05/26 09:12:41     1.37
@@ -462,10 +462,6 @@
        }
        memset(conf->multipaths, 0, sizeof(struct 
multipath_info)*mddev->raid_disks);
 
-       mddev->queue->unplug_fn = multipath_unplug;
-
-       mddev->queue->issue_flush_fn = multipath_issue_flush;
-
        conf->working_disks = 0;
        ITERATE_RDEV(mddev,rdev,tmp) {
                disk_idx = rdev->raid_disk;
@@ -528,6 +524,10 @@
         * Ok, everything is just fine now
         */
        mddev->array_size = mddev->size;
+
+       mddev->queue->unplug_fn = multipath_unplug;
+       mddev->queue->issue_flush_fn = multipath_issue_flush;
+
        return 0;
 
 out_free_conf:
diff -urN linux/drivers/md/raid1.c linux/drivers/md/raid1.c
--- linux/drivers/md/raid1.c    2005/05/19 12:08:23     1.52
+++ linux/drivers/md/raid1.c    2005/05/26 09:12:41     1.53
@@ -1197,10 +1197,6 @@
        if (!conf->r1bio_pool)
                goto out_no_mem;
 
-       mddev->queue->unplug_fn = raid1_unplug;
-
-       mddev->queue->issue_flush_fn = raid1_issue_flush;
-
        ITERATE_RDEV(mddev, rdev, tmp) {
                disk_idx = rdev->raid_disk;
                if (disk_idx >= mddev->raid_disks
@@ -1282,6 +1278,9 @@
         */
        mddev->array_size = mddev->size;
 
+       mddev->queue->unplug_fn = raid1_unplug;
+       mddev->queue->issue_flush_fn = raid1_issue_flush;
+
        return 0;
 
 out_no_mem:
diff -urN linux/drivers/md/raid10.c linux/drivers/md/raid10.c
--- linux/drivers/md/raid10.c   2005/05/19 12:08:23     1.7
+++ linux/drivers/md/raid10.c   2005/05/26 09:12:41     1.8
@@ -1639,9 +1639,6 @@
                        mdname(mddev));
                goto out_free_conf;
        }
-       mddev->queue->unplug_fn = raid10_unplug;
-
-       mddev->queue->issue_flush_fn = raid10_issue_flush;
 
        ITERATE_RDEV(mddev, rdev, tmp) {
                disk_idx = rdev->raid_disk;
@@ -1713,6 +1710,9 @@
        mddev->array_size = size/2;
        mddev->resync_max_sectors = size;
 
+       mddev->queue->unplug_fn = raid10_unplug;
+       mddev->queue->issue_flush_fn = raid10_issue_flush;
+
        /* Calculate max read-ahead size.
         * We need to readahead at least twice a whole stripe....
         * maybe...
diff -urN linux/drivers/md/raid5.c linux/drivers/md/raid5.c
--- linux/drivers/md/raid5.c    2005/05/19 12:08:23     1.57
+++ linux/drivers/md/raid5.c    2005/05/26 09:12:41     1.58
@@ -1620,9 +1620,6 @@
        atomic_set(&conf->active_stripes, 0);
        atomic_set(&conf->preread_active_stripes, 0);
 
-       mddev->queue->unplug_fn = raid5_unplug_device;
-       mddev->queue->issue_flush_fn = raid5_issue_flush;
-
        PRINTK("raid5: run(%s) called.\n", mdname(mddev));
 
        ITERATE_RDEV(mddev,rdev,tmp) {
@@ -1728,6 +1725,10 @@
        }
 
        /* Ok, everything is just fine now */
+
+       mddev->queue->unplug_fn = raid5_unplug_device;
+       mddev->queue->issue_flush_fn = raid5_issue_flush;
+
        mddev->array_size =  mddev->size * (mddev->raid_disks - 1);
        return 0;
 abort:
diff -urN linux/drivers/md/raid6main.c linux/drivers/md/raid6main.c
--- linux/drivers/md/raid6main.c        2005/05/19 12:08:23     1.18
+++ linux/drivers/md/raid6main.c        2005/05/26 09:12:41     1.19
@@ -1779,9 +1779,6 @@
        atomic_set(&conf->active_stripes, 0);
        atomic_set(&conf->preread_active_stripes, 0);
 
-       mddev->queue->unplug_fn = raid6_unplug_device;
-       mddev->queue->issue_flush_fn = raid6_issue_flush;
-
        PRINTK("raid6: run(%s) called.\n", mdname(mddev));
 
        ITERATE_RDEV(mddev,rdev,tmp) {
@@ -1895,6 +1892,9 @@
 
        /* Ok, everything is just fine now */
        mddev->array_size =  mddev->size * (mddev->raid_disks - 2);
+
+       mddev->queue->unplug_fn = raid6_unplug_device;
+       mddev->queue->issue_flush_fn = raid6_issue_flush;
        return 0;
 abort:
        if (conf) {
diff -urN linux/drivers/media/common/saa7146_core.c 
linux/drivers/media/common/saa7146_core.c
--- linux/drivers/media/common/saa7146_core.c   2005/04/08 18:58:16     1.13
+++ linux/drivers/media/common/saa7146_core.c   2005/05/26 09:12:42     1.14
@@ -23,9 +23,9 @@
 LIST_HEAD(saa7146_devices);
 DECLARE_MUTEX(saa7146_devices_lock);
 
-static int saa7146_num = 0;
+static int saa7146_num;
 
-unsigned int saa7146_debug = 0;
+unsigned int saa7146_debug;
 
 module_param(saa7146_debug, int, 0644);
 MODULE_PARM_DESC(saa7146_debug, "debug level (default: 0)");
diff -urN linux/drivers/media/dvb/Kconfig linux/drivers/media/dvb/Kconfig
--- linux/drivers/media/dvb/Kconfig     2005/03/18 17:37:26     1.11
+++ linux/drivers/media/dvb/Kconfig     2005/05/26 09:12:42     1.12
@@ -33,7 +33,7 @@
 source "drivers/media/dvb/cinergyT2/Kconfig"
 
 comment "Supported FlexCopII (B2C2) Adapters"
-       depends on DVB_CORE && PCI
+       depends on DVB_CORE && (PCI || USB)
 source "drivers/media/dvb/b2c2/Kconfig"
 
 comment "Supported BT878 Adapters"
diff -urN linux/drivers/media/dvb/b2c2/flexcop-common.h 
linux/drivers/media/dvb/b2c2/flexcop-common.h
--- linux/drivers/media/dvb/b2c2/flexcop-common.h       1970/01/01 00:00:00
+++ linux/drivers/media/dvb/b2c2/flexcop-common.h       2005-05-26 
10:12:42.265931000 +0100     1.1
@@ -0,0 +1,164 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 
FlexcopII(b)/III
+ *
+ * flexcop-common.h - common header file for device-specific source files also.
+ *
+ * see flexcop.c for copyright information.
+ */
+#ifndef __FLEXCOP_COMMON_H__
+#define __FLEXCOP_COMMON_H__
+
+#include <linux/config.h>
+#include <linux/pci.h>
+
+#include "flexcop-reg.h"
+
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_filter.h"
+#include "dvb_net.h"
+#include "dvb_frontend.h"
+
+#define FC_MAX_FEED 256
+
+#ifndef FC_LOG_PREFIX
+#warning please define a log prefix for your file, using a default one
+#define FC_LOG_PREFIX "b2c2-undef"
+#endif
+
+/* Steal from usb.h */
+#undef err
+#define err(format,  arg...) printk(KERN_ERR     FC_LOG_PREFIX ": " format 
"\n" , ## arg)
+#undef info
+#define info(format, arg...) printk(KERN_INFO    FC_LOG_PREFIX ": " format 
"\n" , ## arg)
+#undef warn
+#define warn(format, arg...) printk(KERN_WARNING FC_LOG_PREFIX ": " format 
"\n" , ## arg)
+
+struct flexcop_dma {
+       struct pci_dev *pdev;
+
+       u8 *cpu_addr0;
+       dma_addr_t dma_addr0;
+       u8 *cpu_addr1;
+       dma_addr_t dma_addr1;
+       u32 size; /* size of each address in bytes */
+};
+
+/* Control structure for data definitions that are common to
+ * the B2C2-based PCI and USB devices.
+ */
+struct flexcop_device {
+       /* general */
+       struct device *dev; /* for firmware_class */
+
+#define FC_STATE_DVB_INIT 0x01
+#define FC_STATE_I2C_INIT 0x02
+#define FC_STATE_FE_INIT  0x04
+       int init_state;
+
+       /* device information */
+       int has_32_hw_pid_filter;
+       flexcop_revision_t rev;
+       flexcop_device_type_t dev_type;
+       flexcop_bus_t bus_type;
+
+       /* dvb stuff */
+       struct dvb_adapter dvb_adapter;
+       struct dvb_frontend *fe;
+       struct dvb_net dvbnet;
+       struct dvb_demux demux;
+       struct dmxdev dmxdev;
+       struct dmx_frontend hw_frontend;
+       struct dmx_frontend mem_frontend;
+       int (*fe_sleep) (struct dvb_frontend *);
+
+       struct i2c_adapter i2c_adap;
+       struct semaphore i2c_sem;
+
+       struct module *owner;
+
+       /* options and status */
+       int extra_feedcount;
+       int feedcount;
+       int pid_filtering;
+       int fullts_streaming_state;
+
+       /* bus specific callbacks */
+       flexcop_ibi_value (*read_ibi_reg)  (struct flexcop_device *, 
flexcop_ibi_register);
+       int               (*write_ibi_reg) (struct flexcop_device *, 
flexcop_ibi_register, flexcop_ibi_value);
+
+
+       int (*i2c_request) (struct flexcop_device*, flexcop_access_op_t, 
flexcop_i2c_port_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
+       int (*stream_control) (struct flexcop_device*, int);
+
+       int (*get_mac_addr) (struct flexcop_device *fc, int extended);
+
+       void *bus_specific;
+};
+
+/* exported prototypes */
+
+/* from flexcop.c */
+void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len);
+void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no);
+
+struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len);
+void flexcop_device_kfree(struct flexcop_device*);
+
+int  flexcop_device_initialize(struct flexcop_device*);
+void flexcop_device_exit(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);
+
+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_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);
+
+/* from flexcop-eeprom.c */
+/* the PCI part uses this call to get the MAC address, the USB part has its 
own */
+int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended);
+
+/* from flexcop-i2c.c */
+/* the PCI part uses this a i2c_request callback, whereas the usb part has its 
own
+ * one. We have it in flexcop-i2c.c, because it is going via the actual
+ * I2C-channel of the flexcop.
+ */
+int flexcop_i2c_request(struct flexcop_device*, flexcop_access_op_t,
+                       flexcop_i2c_port_t, u8 chipaddr, u8 addr, u8 *buf, u16 
len);
+
+/* from flexcop-sram.c */
+int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, 
flexcop_sram_dest_target_t target);
+void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s);
+void flexcop_sram_ctrl(struct flexcop_device *fc, int usb_wan, int sramdma, 
int maximumfill);
+
+/* global prototypes for the flexcop-chip */
+/* from flexcop-fe-tuner.c */
+int flexcop_frontend_init(struct flexcop_device *card);
+void flexcop_frontend_exit(struct flexcop_device *fc);
+
+/* from flexcop-i2c.c */
+int flexcop_i2c_init(struct flexcop_device *fc);
+void flexcop_i2c_exit(struct flexcop_device *fc);
+
+/* from flexcop-sram.c */
+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);
+
+/* from flexcop-hw-filter.c */
+int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed 
*dvbdmxfeed, int onoff);
+void flexcop_hw_filter_init(struct flexcop_device *fc);
+
+void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff);
+
+void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]);
+void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff);
+
+#endif
diff -urN linux/drivers/media/dvb/b2c2/flexcop-dma.c 
linux/drivers/media/dvb/b2c2/flexcop-dma.c
--- linux/drivers/media/dvb/b2c2/flexcop-dma.c  1970/01/01 00:00:00
+++ linux/drivers/media/dvb/b2c2/flexcop-dma.c  2005-05-26 10:12:42.277803000 
+0100     1.1
@@ -0,0 +1,149 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 
FlexcopII(b)/III
+ *
+ * flexcop-dma.c - methods for configuring and controlling the DMA of the 
FlexCop.
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 
size)
+{
+       u8 *tcpu;
+       dma_addr_t tdma;
+
+       if (size % 2) {
+               err("dma buffersize has to be even.");
+               return -EINVAL;
+       }
+
+       if ((tcpu = pci_alloc_consistent(pdev, size, &tdma)) != NULL) {
+               dma->pdev = pdev;
+               dma->cpu_addr0 = tcpu;
+               dma->dma_addr0 = tdma;
+               dma->cpu_addr1 = tcpu + size/2;
+               dma->dma_addr1 = tdma + size/2;
+               dma->size = size/2;
+               return 0;
+       }
+       return -ENOMEM;
+}
+EXPORT_SYMBOL(flexcop_dma_allocate);
+
+void flexcop_dma_free(struct flexcop_dma *dma)
+{
+       pci_free_consistent(dma->pdev, dma->size*2,dma->cpu_addr0, 
dma->dma_addr0);
+       memset(dma,0,sizeof(struct flexcop_dma));
+}
+EXPORT_SYMBOL(flexcop_dma_free);
+
+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_Timer_Enable_sig = onoff;
+
+       if (no & FC_DMA_2)
+               v.ctrl_208.DMA2_Timer_Enable_sig = onoff;
+
+       fc->write_ibi_reg(fc,ctrl_208,v);
+       return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_control_timer_irq);
+
+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);
+
+       if (no & FC_DMA_1)
+               v.ctrl_208.DMA1_IRQ_Enable_sig = onoff;
+
+       if (no & FC_DMA_2)
+               v.ctrl_208.DMA2_IRQ_Enable_sig = onoff;
+
+       fc->write_ibi_reg(fc,ctrl_208,v);
+       return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_control_size_irq);
+
+int flexcop_dma_control_packet_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;
+
+       if (no & FC_DMA_2)
+               v.ctrl_208.DMA2_Size_IRQ_Enable_sig = onoff;
+
+       fc->write_ibi_reg(fc,ctrl_208,v);
+       return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_control_packet_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)
+{
+
+       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);
+
+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;
+       fc->write_ibi_reg(fc,r,v);
+       return 0;
+}
+
+/* 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_dma_remap(fc,dma_idx,0);
+
+       v.dma_0x4_write.dmatimer = cycles >> 1;
+       fc->write_ibi_reg(fc,r,v);
+       return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_config_timer);
+
+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);
+
+       flexcop_dma_remap(fc,dma_idx,1);
+
+       v.dma_0x4_remap.DMA_maxpackets = packets;
+       fc->write_ibi_reg(fc,r,v);
+       return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_config_packet_count);
diff -urN linux/drivers/media/dvb/b2c2/flexcop-eeprom.c 
linux/drivers/media/dvb/b2c2/flexcop-eeprom.c
--- linux/drivers/media/dvb/b2c2/flexcop-eeprom.c       1970/01/01 00:00:00
+++ linux/drivers/media/dvb/b2c2/flexcop-eeprom.c       2005-05-26 
10:12:42.289146000 +0100     1.1
@@ -0,0 +1,153 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 
FlexcopII(b)/III
+ *
+ * flexcop-eeprom.c - eeprom access methods (currently only MAC address 
reading is used)
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+#if 0
+/*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_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 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;
+}
+
+static int flexcop_eeprom_read(struct flexcop_device *fc, u16 addr, u8 *buf, 
u16 len)
+{
+       return fc->i2c_request(fc,FC_READ,FC_I2C_PORT_EEPROM,0x50,addr,buf,len);
+}
+
+#endif
+
+static u8 calc_lrc(u8 *buf, int len)
+{
+       int i;
+       u8 sum = 0;
+       for (i = 0; i < len; i++)
+               sum = sum ^ buf[i];
+       return sum;
+}
+
+static int flexcop_eeprom_request(struct flexcop_device *fc, 
flexcop_access_op_t op, u16 addr, u8 *buf, u16 len, int retries)
+{
+       int i,ret = 0;
+       u8 chipaddr =  0x50 | ((addr >> 8) & 3);
+       for (i = 0; i < retries; i++)
+               if ((ret = 
fc->i2c_request(fc,op,FC_I2C_PORT_EEPROM,chipaddr,addr & 0xff,buf,len)) == 0)
+                       break;
+       return ret;
+}
+
+static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, u8 
*buf, u16 len, int retries)
+{
+       int ret = flexcop_eeprom_request(fc,FC_READ,addr,buf,len,retries);
+       if (ret == 0)
+               if (calc_lrc(buf, len - 1) != buf[len - 1])
+                       ret = -EINVAL;
+       return ret;
+}
+
+/* JJ's comment about extended == 1: it is not presently used anywhere but was
+ * added to the low-level functions for possible support of EUI64
+ */
+int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended)
+{
+       u8 buf[8];
+       int ret = 0;
+
+       if ((ret = flexcop_eeprom_lrc_read(fc,0x3f8,buf,8,4)) == 0) {
+               if (extended != 0) {
+                       err("TODO: extended (EUI64) MAC addresses aren't 
completely supported yet");
+                       ret = -EINVAL;
+/*                     memcpy(fc->dvb_adapter.proposed_mac,buf,3);
+                       mac[3] = 0xfe;
+                       mac[4] = 0xff;
+                       memcpy(&fc->dvb_adapter.proposed_mac[3],&buf[5],3); */
+               } else
+                       memcpy(fc->dvb_adapter.proposed_mac,buf,6);
+       }
+       return ret;
+}
+EXPORT_SYMBOL(flexcop_eeprom_check_mac_addr);
diff -urN linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c 
linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
--- linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c     1970/01/01 00:00:00
+++ linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c     2005-05-26 
10:12:42.300816000 +0100     1.1
@@ -0,0 +1,403 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 
FlexcopII(b)/III
+ *
+ * flexcop-fe-tuner.c - methods for attaching a frontend and controlling 
DiSEqC.
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+#include "stv0299.h"
+#include "mt352.h"
+#include "nxt2002.h"
+#include "stv0297.h"
+#include "mt312.h"
+
+/* lnb control */
+
+static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t 
voltage)
+{
+       struct flexcop_device *fc = fe->dvb->priv;
+       flexcop_ibi_value v;
+       deb_tuner("polarity/voltage = %u\n", voltage);
+
+       v = fc->read_ibi_reg(fc, misc_204);
+       switch (voltage) {
+               case SEC_VOLTAGE_OFF:
+                       v.misc_204.ACPI1_sig = 1;
+                       break;
+               case SEC_VOLTAGE_13:
+                       v.misc_204.ACPI1_sig = 0;
+                       v.misc_204.LNB_L_H_sig = 0;
+                       break;
+               case SEC_VOLTAGE_18:
+                       v.misc_204.ACPI1_sig = 0;
+                       v.misc_204.LNB_L_H_sig = 1;
+                       break;
+               default:
+                       err("unknown SEC_VOLTAGE value");
+                       return -EINVAL;
+       }
+       return fc->write_ibi_reg(fc, misc_204, v);
+}
+
+static int flexcop_sleep(struct dvb_frontend* fe)
+{
+       struct flexcop_device *fc = fe->dvb->priv;
+/*     flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204); */
+
+       if (fc->fe_sleep)
+               return fc->fe_sleep(fe);
+
+/*     v.misc_204.ACPI3_sig = 1;
+       fc->write_ibi_reg(fc,misc_204,v);*/
+
+       return 0;
+}
+
+static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+       /* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc 
}; */
+       struct flexcop_device *fc = fe->dvb->priv;
+       flexcop_ibi_value v;
+       u16 ax;
+       v.raw = 0;
+
+       deb_tuner("tone = %u\n",tone);
+
+       switch (tone) {
+               case SEC_TONE_ON:
+                       ax = 0x01ff;
+                       break;
+               case SEC_TONE_OFF:
+                       ax = 0;
+                       break;
+               default:
+                       err("unknown SEC_TONE value");
+                       return -EINVAL;
+       }
+
+       v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */
+
+       v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax;
+       v.lnb_switch_freq_200.LNB_CTLLowCount_sig  = ax == 0 ? 0x1ff : ax;
+
+       return fc->write_ibi_reg(fc,lnb_switch_freq_200,v);
+}
+
+static void flexcop_diseqc_send_bit(struct dvb_frontend* fe, int data)
+{
+       flexcop_set_tone(fe, SEC_TONE_ON);
+       udelay(data ? 500 : 1000);
+       flexcop_set_tone(fe, SEC_TONE_OFF);
+       udelay(data ? 1000 : 500);
+}
+
+static void flexcop_diseqc_send_byte(struct dvb_frontend* fe, int data)
+{
+       int i, par = 1, d;
+
+       for (i = 7; i >= 0; i--) {
+               d = (data >> i) & 1;
+               par ^= d;
+               flexcop_diseqc_send_bit(fe, d);
+       }
+
+       flexcop_diseqc_send_bit(fe, par);
+}
+
+static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, 
unsigned long burst)
+{
+       int i;
+
+       flexcop_set_tone(fe, SEC_TONE_OFF);
+       mdelay(16);
+
+       for (i = 0; i < len; i++)
+               flexcop_diseqc_send_byte(fe,msg[i]);
+
+       mdelay(16);
+
+       if (burst != -1) {
+               if (burst)
+                       flexcop_diseqc_send_byte(fe, 0xff);
+               else {
+                       flexcop_set_tone(fe, SEC_TONE_ON);
+                       udelay(12500);
+                       flexcop_set_tone(fe, SEC_TONE_OFF);
+               }
+               msleep(20);
+       }
+       return 0;
+}
+
+static int flexcop_diseqc_send_master_cmd(struct dvb_frontend* fe, struct 
dvb_diseqc_master_cmd* cmd)
+{
+       return flexcop_send_diseqc_msg(fe, cmd->msg_len, cmd->msg, 0);
+}
+
+static int flexcop_diseqc_send_burst(struct dvb_frontend* fe, 
fe_sec_mini_cmd_t minicmd)
+{
+       return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd);
+}
+
+/* dvb-s stv0299 */
+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 flexcop_device *fc = 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(&fc->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,
+};
+
+/* dvb-t mt352 */
+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 nxt2002_request_firmware(struct dvb_frontend* fe, const struct 
firmware **fw, char* name)
+{
+       struct flexcop_device *fc = fe->dvb->priv;
+       return request_firmware(fw, name, fc->dev);
+}
+
+static struct nxt2002_config samsung_tbmv_config = {
+       .demod_address = 0x0a,
+       .request_firmware = nxt2002_request_firmware,
+};
+
+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 flexcop_device *fc = 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(&fc->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 struct stv0297_config alps_tdee4_stv0297_config = {
+       .demod_address = 0x1c,
+//     .invert = 1,
+//     .pll_set = alps_tdee4_stv0297_pll_set,
+};
+
+/* try to figure out the frontend, each card/box can have on of the following 
list */
+int flexcop_frontend_init(struct flexcop_device *fc)
+{
+       /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
+       if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) 
!= NULL) {
+               fc->fe->ops->set_voltage = flexcop_set_voltage;
+
+               fc->fe_sleep             = fc->fe->ops->sleep;
+               fc->fe->ops->sleep       = flexcop_sleep;
+
+               fc->dev_type          = FC_SKY;
+               info("found the stv0299 at i2c address: 
0x%02x",samsung_tbmu24112_config.demod_address);
+       } else
+       /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
+       if ((fc->fe = mt352_attach(&samsung_tdtc9251dh0_config, &fc->i2c_adap)) 
!= NULL ) {
+               fc->dev_type          = FC_AIR_DVB;
+               info("found the mt352 at i2c address: 
0x%02x",samsung_tdtc9251dh0_config.demod_address);
+       } else
+       /* try the air atsc (nxt2002) */
+       if ((fc->fe = nxt2002_attach(&samsung_tbmv_config, &fc->i2c_adap)) != 
NULL) {
+               fc->dev_type          = FC_AIR_ATSC;
+               info("found the nxt2002 at i2c address: 
0x%02x",samsung_tbmv_config.demod_address);
+       } else
+       /* try the cable dvb (stv0297) */
+       if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap, 
0xf8)) != NULL) {
+               fc->dev_type                        = FC_CABLE;
+               info("found the stv0297 at i2c address: 
0x%02x",alps_tdee4_stv0297_config.demod_address);
+       } else
+       /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
+       if ((fc->fe = vp310_attach(&skystar23_samsung_tbdu18132_config, 
&fc->i2c_adap)) != NULL) {
+               fc->fe->ops->diseqc_send_master_cmd = 
flexcop_diseqc_send_master_cmd;
+               fc->fe->ops->diseqc_send_burst      = flexcop_diseqc_send_burst;
+               fc->fe->ops->set_tone               = flexcop_set_tone;
+               fc->fe->ops->set_voltage            = flexcop_set_voltage;
+
+               fc->fe_sleep                        = fc->fe->ops->sleep;
+               fc->fe->ops->sleep                  = flexcop_sleep;
+
+               fc->dev_type                        = FC_SKY_OLD;
+               info("found the vp310 (aka mt312) at i2c address: 
0x%02x",skystar23_samsung_tbdu18132_config.demod_address);
+       }
+
+       if (fc->fe == NULL) {
+               err("no frontend driver found for this B2C2/FlexCop adapter");
+               return -ENODEV;
+       } else {
+               if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
+                       err("frontend registration failed!");
+                       if (fc->fe->ops->release != NULL)
+                               fc->fe->ops->release(fc->fe);
+                       fc->fe = NULL;
+                       return -EINVAL;
+               }
+       }
+       fc->init_state |= FC_STATE_FE_INIT;
+       return 0;
+}
+
+void flexcop_frontend_exit(struct flexcop_device *fc)
+{
+       if (fc->init_state & FC_STATE_FE_INIT)
+               dvb_unregister_frontend(fc->fe);
+
+       fc->init_state &= ~FC_STATE_FE_INIT;
+}
diff -urN linux/drivers/media/dvb/b2c2/flexcop-hw-filter.c 
linux/drivers/media/dvb/b2c2/flexcop-hw-filter.c
--- linux/drivers/media/dvb/b2c2/flexcop-hw-filter.c    1970/01/01 00:00:00
+++ linux/drivers/media/dvb/b2c2/flexcop-hw-filter.c    2005-05-26 
10:12:42.314787000 +0100     1.1
@@ -0,0 +1,204 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 
FlexcopII(b)/III
+ *
+ * flexcop-hw-filter.c - pid and mac address filtering and corresponding 
control functions.
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+static void flexcop_rcv_data_ctrl(struct flexcop_device *fc, int onoff)
+{
+       flexcop_set_ibi_value(ctrl_208,Rcv_Data_sig,onoff);
+}
+
+void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff)
+{
+       flexcop_set_ibi_value(ctrl_208,SMC_Enable_sig,onoff);
+}
+
+void flexcop_null_filter_ctrl(struct flexcop_device *fc, int onoff)
+{
+       flexcop_set_ibi_value(ctrl_208,Null_filter_sig,onoff);
+}
+
+void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6])
+{
+       flexcop_ibi_value v418,v41c;
+       v41c = fc->read_ibi_reg(fc,mac_address_41c);
+
+       v418.mac_address_418.MAC1 = mac[0];
+       v418.mac_address_418.MAC2 = mac[1];
+       v418.mac_address_418.MAC3 = mac[2];
+       v418.mac_address_418.MAC6 = mac[3];
+       v41c.mac_address_41c.MAC7 = mac[4];
+       v41c.mac_address_41c.MAC8 = mac[5];
+
+       fc->write_ibi_reg(fc,mac_address_418,v418);
+       fc->write_ibi_reg(fc,mac_address_41c,v41c);
+}
+
+void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff)
+{
+       flexcop_set_ibi_value(ctrl_208,MAC_filter_Mode_sig,onoff);
+}
+
+static void flexcop_pid_group_filter(struct flexcop_device *fc, u16 pid, u16 
mask)
+{
+       /* index_reg_310.extra_index_reg need to 0 or 7 to work */
+       flexcop_ibi_value v30c;
+       v30c.pid_filter_30c_ext_ind_0_7.Group_PID = pid;
+       v30c.pid_filter_30c_ext_ind_0_7.Group_mask = mask;
+       fc->write_ibi_reg(fc,pid_filter_30c,v30c);
+}
+
+static void flexcop_pid_group_filter_ctrl(struct flexcop_device *fc, int onoff)
+{
+       flexcop_set_ibi_value(ctrl_208,Mask_filter_sig,onoff);
+}
+
+/* this fancy define reduces the code size of the quite similar PID 
controlling of
+ * the first 6 PIDs
+ */
+
+#define pid_ctrl(vregname,field,enablefield,trans_field,transval) \
+       flexcop_ibi_value vpid = fc->read_ibi_reg(fc, vregname), \
+                                         v208 = fc->read_ibi_reg(fc, 
ctrl_208); \
+\
+       vpid.vregname.field = onoff ? pid : 0x1fff; \
+       vpid.vregname.trans_field = transval; \
+       v208.ctrl_208.enablefield = onoff; \
+\
+       fc->write_ibi_reg(fc,vregname,vpid); \
+       fc->write_ibi_reg(fc,ctrl_208,v208);
+
+static void flexcop_pid_Stream1_PID_ctrl(struct flexcop_device *fc, u16 pid, 
int onoff)
+{
+       pid_ctrl(pid_filter_300,Stream1_PID,Stream1_filter_sig,Stream1_trans,0);
+}
+
+static void flexcop_pid_Stream2_PID_ctrl(struct flexcop_device *fc, u16 pid, 
int onoff)
+{
+       pid_ctrl(pid_filter_300,Stream2_PID,Stream2_filter_sig,Stream2_trans,0);
+}
+
+static void flexcop_pid_PCR_PID_ctrl(struct flexcop_device *fc, u16 pid, int 
onoff)
+{
+       pid_ctrl(pid_filter_304,PCR_PID,PCR_filter_sig,PCR_trans,0);
+}
+
+static void flexcop_pid_PMT_PID_ctrl(struct flexcop_device *fc, u16 pid, int 
onoff)
+{
+       pid_ctrl(pid_filter_304,PMT_PID,PMT_filter_sig,PMT_trans,0);
+}
+
+static void flexcop_pid_EMM_PID_ctrl(struct flexcop_device *fc, u16 pid, int 
onoff)
+{
+       pid_ctrl(pid_filter_308,EMM_PID,EMM_filter_sig,EMM_trans,0);
+}
+
+static void flexcop_pid_ECM_PID_ctrl(struct flexcop_device *fc, u16 pid, int 
onoff)
+{
+       pid_ctrl(pid_filter_308,ECM_PID,ECM_filter_sig,ECM_trans,0);
+}
+
+static void flexcop_pid_control(struct flexcop_device *fc, int index, u16 
pid,int onoff)
+{
+       if (pid == 0x2000)
+               return;
+
+       deb_ts("setting pid: %5d %04x at index %d '%s'\n",pid,pid,index,onoff ? 
"on" : "off");
+
+       /* We could use bit magic here to reduce source code size.
+        * I decided against it, but to use the real register names */
+       switch (index) {
+               case 0: flexcop_pid_Stream1_PID_ctrl(fc,pid,onoff); break;
+               case 1: flexcop_pid_Stream2_PID_ctrl(fc,pid,onoff); break;
+               case 2: flexcop_pid_PCR_PID_ctrl(fc,pid,onoff); break;
+               case 3: flexcop_pid_PMT_PID_ctrl(fc,pid,onoff); break;
+               case 4: flexcop_pid_EMM_PID_ctrl(fc,pid,onoff); break;
+               case 5: flexcop_pid_ECM_PID_ctrl(fc,pid,onoff); break;
+               default:
+                       if (fc->has_32_hw_pid_filter && index < 38) {
+                               flexcop_ibi_value vpid,vid;
+
+                               /* set the index */
+                               vid = fc->read_ibi_reg(fc,index_reg_310);
+                               vid.index_reg_310.index_reg = index - 6;
+                               fc->write_ibi_reg(fc,index_reg_310, vid);
+
+                               vpid = fc->read_ibi_reg(fc,pid_n_reg_314);
+                               vpid.pid_n_reg_314.PID = onoff ? pid : 0x1fff;
+                               vpid.pid_n_reg_314.PID_enable_bit = onoff;
+                               fc->write_ibi_reg(fc,pid_n_reg_314, vpid);
+                       }
+                       break;
+       }
+}
+
+static int flexcop_toggle_fullts_streaming(struct flexcop_device *fc,int onoff)
+{
+       if (fc->fullts_streaming_state != onoff) {
+               deb_ts("%s full TS transfer\n",onoff ? "enabling" : 
"disabling");
+               flexcop_pid_group_filter(fc, 0, 0x1fe0 * (!onoff));
+               flexcop_pid_group_filter_ctrl(fc,onoff);
+               fc->fullts_streaming_state = onoff;
+       }
+       return 0;
+}
+
+int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed 
*dvbdmxfeed, int onoff)
+{
+       int max_pid_filter = 6 + fc->has_32_hw_pid_filter*32;
+
+       fc->feedcount += onoff ? 1 : -1;
+       if (dvbdmxfeed->index >= max_pid_filter)
+               fc->extra_feedcount += onoff ? 1 : -1;
+
+       /* toggle complete-TS-streaming when:
+        * - pid_filtering is not enabled and it is the first or last feed 
requested
+        * - pid_filtering is enabled,
+        *   - but the number of requested feeds is exceeded
+        *   - or the requested pid is 0x2000 */
+
+       if (!fc->pid_filtering && fc->feedcount == onoff)
+               flexcop_toggle_fullts_streaming(fc,onoff);
+
+       if (fc->pid_filtering) {
+               flexcop_pid_control(fc,dvbdmxfeed->index,dvbdmxfeed->pid,onoff);
+
+               if (fc->extra_feedcount > 0)
+                       flexcop_toggle_fullts_streaming(fc,1);
+               else if (dvbdmxfeed->pid == 0x2000)
+                       flexcop_toggle_fullts_streaming(fc,onoff);
+               else
+                       flexcop_toggle_fullts_streaming(fc,0);
+       }
+
+       /* 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)
+                       fc->stream_control(fc,onoff);
+       }
+
+       return 0;
+}
+
+void flexcop_hw_filter_init(struct flexcop_device *fc)
+{
+       int i;
+       flexcop_ibi_value v;
+       for (i = 0; i < 6 + 32*fc->has_32_hw_pid_filter; i++)
+               flexcop_pid_control(fc,i,0x1fff,0);
+
+       flexcop_pid_group_filter(fc, 0, 0x1fe0);
+       flexcop_pid_group_filter_ctrl(fc,0);
+
+       v = fc->read_ibi_reg(fc,pid_filter_308);
+       v.pid_filter_308.EMM_filter_4 = 1;
+       v.pid_filter_308.EMM_filter_6 = 0;
+       fc->write_ibi_reg(fc,pid_filter_308,v);
+
+       flexcop_null_filter_ctrl(fc, 1);
+}
diff -urN linux/drivers/media/dvb/b2c2/flexcop-i2c.c 
linux/drivers/media/dvb/b2c2/flexcop-i2c.c
--- linux/drivers/media/dvb/b2c2/flexcop-i2c.c  1970/01/01 00:00:00
+++ linux/drivers/media/dvb/b2c2/flexcop-i2c.c  2005-05-26 10:12:42.327041000 
+0100     1.1
@@ -0,0 +1,210 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 
FlexcopII(b)/III
+ *
+ * flexcop-i2c.c - flexcop internal 2Wire bus (I2C) and dvb i2c initialization
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+#define FC_MAX_I2C_RETRIES 100000
+
+static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value 
*r100)
+{
+       int i;
+       flexcop_ibi_value r;
+
+       r100->tw_sm_c_100.working_start = 1;
+       deb_i2c("r100 before: %08x\n",r100->raw);
+
+       fc->write_ibi_reg(fc, tw_sm_c_100, ibi_zero);
+       fc->write_ibi_reg(fc, tw_sm_c_100, *r100); /* initiating i2c operation 
*/
+
+       for (i = 0; i < FC_MAX_I2C_RETRIES; i++) {
+               r = fc->read_ibi_reg(fc, tw_sm_c_100);
+
+               if (!r.tw_sm_c_100.no_base_addr_ack_error) {
+                       if (r.tw_sm_c_100.st_done) {  /* && 
!r.tw_sm_c_100.working_start */
+                               *r100 = r;
+                               deb_i2c("i2c success\n");
+                               return 0;
+                       }
+               } else {
+                       deb_i2c("suffering from an i2c ack_error\n");
+                       return -EREMOTEIO;
+               }
+       }
+       deb_i2c("tried %d times i2c operation, never finished or too many ack 
errors.\n",i);
+       return -EREMOTEIO;
+}
+
+static int flexcop_i2c_read4(struct flexcop_device *fc, flexcop_ibi_value 
r100, u8 *buf)
+{
+       flexcop_ibi_value r104;
+       int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is 
buflen-1 */
+               ret;
+
+       if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) {
+               /* The Cablestar needs a different kind of i2c-transfer (does 
not
+                * support "Repeat Start"):
+                * wait for the ACK failure,
+                * and do a subsequent read with the Bit 30 enabled
+                */
+               r100.tw_sm_c_100.no_base_addr_ack_error = 1;
+               if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) {
+                       deb_i2c("no_base_addr read failed. %d\n",ret);
+                       return ret;
+               }
+       }
+
+       buf[0] = r100.tw_sm_c_100.data1_reg;
+
+       if (len > 0) {
+               r104 = fc->read_ibi_reg(fc,tw_sm_c_104);
+               deb_i2c("read: r100: %08x, r104: %08x\n",r100.raw,r104.raw);
+
+               /* there is at least one more byte, otherwise we wouldn't be 
here */
+               buf[1] = r104.tw_sm_c_104.data2_reg;
+               if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg;
+               if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg;
+       }
+
+       return 0;
+}
+
+static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value 
r100, u8 *buf)
+{
+       flexcop_ibi_value r104;
+       int len = r100.tw_sm_c_100.total_bytes; /* remember total_bytes is 
buflen-1 */
+       r104.raw = 0;
+
+       /* there is at least one byte, otherwise we wouldn't be here */
+       r100.tw_sm_c_100.data1_reg = buf[0];
+
+       r104.tw_sm_c_104.data2_reg = len > 0 ? buf[1] : 0;
+       r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0;
+       r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0;
+
+       deb_i2c("write: r100: %08x, r104: %08x\n",r100.raw,r104.raw);
+
+       /* write the additional i2c data before doing the actual i2c operation 
*/
+       fc->write_ibi_reg(fc,tw_sm_c_104,r104);
+       return flexcop_i2c_operation(fc,&r100);
+}
+
+int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
+               flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len)
+{
+       int ret;
+       u16 bytes_to_transfer;
+       flexcop_ibi_value r100;
+
+       deb_i2c("op = %d\n",op);
+       r100.raw = 0;
+       r100.tw_sm_c_100.chipaddr = chipaddr;
+       r100.tw_sm_c_100.twoWS_rw = op;
+       r100.tw_sm_c_100.twoWS_port_reg = port;
+
+       while (len != 0) {
+               bytes_to_transfer = len > 4 ? 4 : len;
+
+               r100.tw_sm_c_100.total_bytes = bytes_to_transfer - 1;
+               r100.tw_sm_c_100.baseaddr = addr;
+
+               if (op == FC_READ)
+                       ret = flexcop_i2c_read4(fc, r100, buf);
+               else
+                       ret = flexcop_i2c_write4(fc,r100, buf);
+
+               if (ret < 0)
+                       return ret;
+
+               buf  += bytes_to_transfer;
+               addr += bytes_to_transfer;
+               len  -= bytes_to_transfer;
+       };
+
+       return 0;
+}
+/* exported for PCI i2c */
+EXPORT_SYMBOL(flexcop_i2c_request);
+
+/* master xfer callback for demodulator */
+static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg 
msgs[], int num)
+{
+       struct flexcop_device *fc = i2c_get_adapdata(i2c_adap);
+       int i, ret = 0;
+
+       if (down_interruptible(&fc->i2c_sem))
+               return -ERESTARTSYS;
+
+       /* reading */
+       if (num == 2 &&
+               msgs[0].flags == 0 &&
+               msgs[1].flags == I2C_M_RD &&
+               msgs[0].buf != NULL &&
+               msgs[1].buf != NULL) {
+
+               ret = fc->i2c_request(fc, FC_READ, FC_I2C_PORT_DEMOD, 
msgs[0].addr, msgs[0].buf[0], msgs[1].buf, msgs[1].len);
+
+       } else for (i = 0; i < num; i++) { /* writing command */
+               if (msgs[i].flags != 0 || msgs[i].buf == NULL || msgs[i].len < 
2) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_DEMOD, 
msgs[i].addr, msgs[i].buf[0], &msgs[i].buf[1], msgs[i].len - 1);
+       }
+
+       if (ret < 0)
+               err("i2c master_xfer failed");
+       else
+               ret = num;
+
+       up(&fc->i2c_sem);
+
+       return ret;
+}
+
+static u32 flexcop_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm flexcop_algo = {
+       .name                   = "FlexCop I2C algorithm",
+       .id                             = I2C_ALGO_BIT,
+       .master_xfer    = flexcop_master_xfer,
+       .functionality  = flexcop_i2c_func,
+};
+
+int flexcop_i2c_init(struct flexcop_device *fc)
+{
+       int ret;
+
+       sema_init(&fc->i2c_sem,1);
+
+       memset(&fc->i2c_adap, 0, sizeof(struct i2c_adapter));
+       strncpy(fc->i2c_adap.name, "B2C2 FlexCop device",I2C_NAME_SIZE);
+
+       i2c_set_adapdata(&fc->i2c_adap,fc);
+
+       fc->i2c_adap.class          = I2C_CLASS_TV_DIGITAL;
+       fc->i2c_adap.algo       = &flexcop_algo;
+       fc->i2c_adap.algo_data  = NULL;
+       fc->i2c_adap.id         = I2C_ALGO_BIT;
+
+       if ((ret = i2c_add_adapter(&fc->i2c_adap)) < 0)
+               return ret;
+
+       fc->init_state |= FC_STATE_I2C_INIT;
+       return 0;
+}
+
+void flexcop_i2c_exit(struct flexcop_device *fc)
+{
+       if (fc->init_state & FC_STATE_I2C_INIT)
+               i2c_del_adapter(&fc->i2c_adap);
+
+       fc->init_state &= ~FC_STATE_I2C_INIT;
+}
diff -urN linux/drivers/media/dvb/b2c2/flexcop-misc.c 
linux/drivers/media/dvb/b2c2/flexcop-misc.c
--- linux/drivers/media/dvb/b2c2/flexcop-misc.c 1970/01/01 00:00:00
+++ linux/drivers/media/dvb/b2c2/flexcop-misc.c 2005-05-26 10:12:42.338915000 
+0100     1.1
@@ -0,0 +1,66 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 
FlexcopII(b)/III
+ *
+ * flexcop-misc.c - miscellaneous functions.
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+void flexcop_determine_revision(struct flexcop_device *fc)
+{
+       flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204);
+
+       switch (v.misc_204.Rev_N_sig_revision_hi) {
+               case 0x2:
+                       deb_info("found a FlexCopII.\n");
+                       fc->rev = FLEXCOP_II;
+                       break;
+               case 0x3:
+                       deb_info("found a FlexCopIIb.\n");
+                       fc->rev = FLEXCOP_IIB;
+                       break;
+               case 0x0:
+                       deb_info("found a FlexCopIII.\n");
+                       fc->rev = FLEXCOP_III;
+                       break;
+               default:
+                       err("unkown FlexCop Revision: %x. Please report the 
linux-dvb@linuxtv.org.",v.misc_204.Rev_N_sig_revision_hi);
+                       break;
+       }
+
+       if ((fc->has_32_hw_pid_filter = v.misc_204.Rev_N_sig_caps))
+               deb_info("this FlexCop has the additional 32 hardware pid 
filter.\n");
+       else
+               deb_info("this FlexCop has only the 6 basic main hardware pid 
filter.\n");
+       /* bus parts have to decide if hw pid filtering is used or not. */
+}
+
+const char *flexcop_revision_names[] = {
+       "Unkown chip",
+       "FlexCopII",
+       "FlexCopIIb",
+       "FlexCopIII",
+};
+
+const char *flexcop_device_names[] = {
+       "Unkown device",
+       "AirStar 2 DVB-T",
+       "AirStar 2 ATSC",
+       "SkyStar 2 DVB-S",
+       "SkyStar 2 DVB-S (old version)",
+       "CableStar 2 DVB-C",
+};
+
+const char *flexcop_bus_names[] = {
+       "USB",
+       "PCI",
+};
+
+void flexcop_device_name(struct flexcop_device *fc,const char *prefix,const
+               char *suffix)
+{
+       info("%s '%s' at the '%s' bus controlled by a '%s' %s",prefix,
+                       
flexcop_device_names[fc->dev_type],flexcop_bus_names[fc->bus_type],
+                       flexcop_revision_names[fc->rev],suffix);
+}
diff -urN linux/drivers/media/dvb/b2c2/flexcop-pci.c 
linux/drivers/media/dvb/b2c2/flexcop-pci.c
--- linux/drivers/media/dvb/b2c2/flexcop-pci.c  1970/01/01 00:00:00
+++ linux/drivers/media/dvb/b2c2/flexcop-pci.c  2005-05-26 10:12:42.349812000 
+0100     1.1
@@ -0,0 +1,381 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 
FlexcopII(b)/III
+ *
+ * flexcop-pci.c - covers the PCI part including DMA transfers.
+ *
+ * see flexcop.c for copyright information.
+ */
+
+#define FC_LOG_PREFIX "flexcop-pci"
+#include "flexcop-common.h"
+
+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");
+
+#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
+#define dprintk(level,args...) \
+       do { if ((debug & level)) printk(args); } while (0)
+#define DEBSTATUS ""
+#else
+#define dprintk(level,args...)
+#define DEBSTATUS " (debugging is not enabled)"
+#endif
+
+#define deb_info(args...)  dprintk(0x01,args)
+#define deb_reg(args...)   dprintk(0x02,args)
+#define deb_ts(args...)    dprintk(0x04,args)
+#define deb_irq(args...)   dprintk(0x08,args)
+
+static int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debug level (1=info,2=regs,4=TS,8=irqdma 
(|-able))." DEBSTATUS);
+
+#define DRIVER_VERSION "0.1"
+#define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver"
+#define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>"
+
+struct flexcop_pci {
+       struct pci_dev *pdev;
+
+#define FC_PCI_INIT     0x01
+#define FC_PCI_DMA_INIT 0x02
+       int init_state;
+
+       void __iomem *io_mem;
+       u32 irq;
+/* buffersize (at least for DMA1, need to be % 188 == 0,
+ * this logic is required */
+#define FC_DEFAULT_DMA1_BUFSIZE (1280 * 188)
+#define FC_DEFAULT_DMA2_BUFSIZE (10 * 188)
+       struct flexcop_dma dma[2];
+
+       int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */
+       u32 last_dma1_cur_pos; /* position of the pointer last time the 
timer/packet irq occured */
+       int count;
+
+       spinlock_t irq_lock;
+
+       struct flexcop_device *fc_dev;
+};
+
+static int lastwreg,lastwval,lastrreg,lastrval;
+
+static flexcop_ibi_value flexcop_pci_read_ibi_reg (struct flexcop_device *fc, 
flexcop_ibi_register r)
+{
+       struct flexcop_pci *fc_pci = fc->bus_specific;
+       flexcop_ibi_value v;
+       v.raw = readl(fc_pci->io_mem + r);
+
+       if (lastrreg != r || lastrval != v.raw) {
+               lastrreg = r; lastrval = v.raw;
+               deb_reg("new rd: %3x: %08x\n",r,v.raw);
+       }
+
+       return v;
+}
+
+static int flexcop_pci_write_ibi_reg(struct flexcop_device *fc, 
flexcop_ibi_register r, flexcop_ibi_value v)
+{
+       struct flexcop_pci *fc_pci = fc->bus_specific;
+
+       if (lastwreg != r || lastwval != v.raw) {
+               lastwreg = r; lastwval = v.raw;
+               deb_reg("new wr: %3x: %08x\n",r,v.raw);
+       }
+
+       writel(v.raw, fc_pci->io_mem + r);
+       return 0;
+}
+
+/* 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)
+{
+       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);
+       irqreturn_t ret = IRQ_HANDLED;
+
+       spin_lock_irq(&fc_pci->irq_lock);
+
+       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);
+               else
+                       
flexcop_pass_dmx_packets(fc_pci->fc_dev,fc_pci->dma[0].cpu_addr1,fc_pci->dma[0].size
 / 188);
+
+               deb_irq("page change to page: %d\n",!fc_pci->active_dma1_addr);
+               fc_pci->active_dma1_addr = !fc_pci->active_dma1_addr;
+       } else if (v.irq_20c.DMA1_Timer_Status == 1) {
+               /* for the timer IRQ we only can use buffer dmx feeding, 
because we don't have
+                * complete TS packets when reading from the DMA memory */
+               dma_addr_t cur_addr =
+                       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);
+
+               /* buffer end was reached, restarted from the beginning
+                * pass the data from last_cur_pos to the buffer end to the 
demux
+                */
+               if (cur_pos < fc_pci->last_dma1_cur_pos) {
+                       deb_irq(" end was reached: passing %d bytes 
",(fc_pci->dma[0].size*2 - 1) - fc_pci->last_dma1_cur_pos);
+                       flexcop_pass_dmx_data(fc_pci->fc_dev,
+                                       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) {
+                       deb_irq(" passing %d bytes ",cur_pos - 
fc_pci->last_dma1_cur_pos);
+                       flexcop_pass_dmx_data(fc_pci->fc_dev,
+                                       fc_pci->dma[0].cpu_addr0 + 
fc_pci->last_dma1_cur_pos,
+                                       cur_pos - fc_pci->last_dma1_cur_pos);
+               }
+               deb_irq("\n");
+
+               fc_pci->last_dma1_cur_pos = cur_pos;
+       } else
+               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;
+}
+
+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);
+
+               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_packet_count(fc,FC_DMA_1,0xc0);
+               flexcop_dma_control_packet_irq(fc,FC_DMA_1,1); */
+
+               deb_irq("irqs enabled\n");
+       } 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);
+
+//             flexcop_dma_control_packet_irq(fc,FC_DMA_1,0);
+               deb_irq("irqs disabled\n");
+       }
+
+       return 0;
+}
+
+static int flexcop_pci_dma_init(struct flexcop_pci *fc_pci)
+{
+       int ret;
+       if ((ret = 
flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[0],FC_DEFAULT_DMA1_BUFSIZE)) != 
0)
+               return ret;
+
+       if ((ret = 
flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 
0)
+               goto dma1_free;
+
+       flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_MEDIA | 
FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1);
+       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]);
+
+success:
+       return ret;
+}
+
+static void flexcop_pci_dma_exit(struct flexcop_pci *fc_pci)
+{
+       if (fc_pci->init_state & FC_PCI_DMA_INIT) {
+               flexcop_dma_free(&fc_pci->dma[0]);
+               flexcop_dma_free(&fc_pci->dma[1]);
+       }
+       fc_pci->init_state &= ~FC_PCI_DMA_INIT;
+}
+
+static int flexcop_pci_init(struct flexcop_pci *fc_pci)
+{
+       int ret;
+       u8 card_rev;
+
+       pci_read_config_byte(fc_pci->pdev, PCI_CLASS_REVISION, &card_rev);
+       info("card revision %x", card_rev);
+
+       if ((ret = pci_enable_device(fc_pci->pdev)) != 0)
+               return ret;
+
+       pci_set_master(fc_pci->pdev);
+
+       /* enable interrupts */
+       // pci_write_config_dword(pdev, 0x6c, 0x8000);
+
+       if ((ret = pci_request_regions(fc_pci->pdev, DRIVER_NAME)) != 0)
+               goto err_pci_disable_device;
+
+       fc_pci->io_mem = pci_iomap(fc_pci->pdev, 0, 0x800);
+
+       if (!fc_pci->io_mem) {
+               err("cannot map io memory\n");
+               ret = -EIO;
+               goto err_pci_release_regions;
+       }
+
+       pci_set_drvdata(fc_pci->pdev, fc_pci);
+
+       if ((ret = request_irq(fc_pci->pdev->irq, flexcop_pci_irq,
+                                       SA_SHIRQ, DRIVER_NAME, fc_pci)) != 0)
+               goto err_pci_iounmap;
+
+       spin_lock_init(&fc_pci->irq_lock);
+
+       fc_pci->init_state |= FC_PCI_INIT;
+       goto success;
+
+err_pci_iounmap:
+       pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
+       pci_set_drvdata(fc_pci->pdev, NULL);
+err_pci_release_regions:
+       pci_release_regions(fc_pci->pdev);
+err_pci_disable_device:
+       pci_disable_device(fc_pci->pdev);
+
+success:
+       return ret;
+}
+
+static void flexcop_pci_exit(struct flexcop_pci *fc_pci)
+{
+       if (fc_pci->init_state & FC_PCI_INIT) {
+               free_irq(fc_pci->pdev->irq, fc_pci);
+               pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
+               pci_set_drvdata(fc_pci->pdev, NULL);
+               pci_release_regions(fc_pci->pdev);
+               pci_disable_device(fc_pci->pdev);
+       }
+       fc_pci->init_state &= ~FC_PCI_INIT;
+}
+
+
+static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id 
*ent)
+{
+       struct flexcop_device *fc;
+       struct flexcop_pci *fc_pci;
+       int ret = -ENOMEM;
+
+       if ((fc = flexcop_device_kmalloc(sizeof(struct flexcop_pci))) == NULL) {
+               err("out of memory\n");
+               return -ENOMEM;
+       }
+
+/* general flexcop init */
+       fc_pci = fc->bus_specific;
+       fc_pci->fc_dev = fc;
+
+       fc->read_ibi_reg = flexcop_pci_read_ibi_reg;
+       fc->write_ibi_reg = flexcop_pci_write_ibi_reg;
+       fc->i2c_request = flexcop_i2c_request;
+       fc->get_mac_addr = flexcop_eeprom_check_mac_addr;
+
+       fc->stream_control = flexcop_pci_stream_control;
+
+       if (enable_pid_filtering)
+               info("will use the HW PID filter.");
+       else
+               info("will pass the complete TS to the demuxer.");
+
+       fc->pid_filtering = enable_pid_filtering;
+       fc->bus_type = FC_PCI;
+
+       fc->dev = &pdev->dev;
+       fc->owner = THIS_MODULE;
+
+/* bus specific part */
+       fc_pci->pdev = pdev;
+       if ((ret = flexcop_pci_init(fc_pci)) != 0)
+               goto err_kfree;
+
+/* init flexcop */
+       if ((ret = flexcop_device_initialize(fc)) != 0)
+               goto err_pci_exit;
+
+/* init dma */
+       if ((ret = flexcop_pci_dma_init(fc_pci)) != 0)
+               goto err_fc_exit;
+
+       goto success;
+err_fc_exit:
+       flexcop_device_exit(fc);
+err_pci_exit:
+       flexcop_pci_exit(fc_pci);
+err_kfree:
+       flexcop_device_kfree(fc);
+success:
+       return ret;
+}
+
+/* in theory every _exit function should be called exactly two times,
+ * here and in the bail-out-part of the _init-function
+ */
+static void flexcop_pci_remove(struct pci_dev *pdev)
+{
+       struct flexcop_pci *fc_pci = pci_get_drvdata(pdev);
+
+       flexcop_pci_dma_exit(fc_pci);
+       flexcop_device_exit(fc_pci->fc_dev);
+       flexcop_pci_exit(fc_pci);
+       flexcop_device_kfree(fc_pci->fc_dev);
+}
+
+static struct pci_device_id flexcop_pci_tbl[] = {
+       { PCI_DEVICE(0x13d0, 0x2103) },
+/*     { PCI_DEVICE(0x13d0, 0x2200) }, PCI FlexCopIII ? */
+       { },
+};
+
+MODULE_DEVICE_TABLE(pci, flexcop_pci_tbl);
+
+static struct pci_driver flexcop_pci_driver = {
+       .name = "Technisat/B2C2 FlexCop II/IIb/III PCI",
+       .id_table = flexcop_pci_tbl,
+       .probe = flexcop_pci_probe,
+       .remove = flexcop_pci_remove,
+};
+
+static int __init flexcop_pci_module_init(void)
+{
+       return pci_register_driver(&flexcop_pci_driver);
+}
+
+static void __exit flexcop_pci_module_exit(void)
+{
+       pci_unregister_driver(&flexcop_pci_driver);
+}
+
+module_init(flexcop_pci_module_init);
+module_exit(flexcop_pci_module_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_NAME);
+MODULE_LICENSE("GPL");
diff -urN linux/drivers/media/dvb/b2c2/flexcop-reg.h 
linux/drivers/media/dvb/b2c2/flexcop-reg.h
--- linux/drivers/media/dvb/b2c2/flexcop-reg.h  1970/01/01 00:00:00
+++ linux/drivers/media/dvb/b2c2/flexcop-reg.h  2005-05-26 10:12:42.363756000 
+0100     1.1
@@ -0,0 +1,701 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 
FlexcopII(b)/III
+ *
+ * flexcop-reg.h - register abstraction for FlexCopII, FlexCopIIb and 
FlexCopIII
+ *
+ * see flexcop.c for copyright information.
+ */
+#ifndef __FLEXCOP_REG_H__
+#define __FLEXCOP_REG_H__
+
+
+typedef enum {
+       FLEXCOP_UNK = 0,
+       FLEXCOP_II,
+       FLEXCOP_IIB,
+       FLEXCOP_III,
+} flexcop_revision_t;
+
+extern const char *flexcop_revision_names[];
+
+typedef enum {
+       FC_UNK = 0,
+       FC_AIR_DVB,
+       FC_AIR_ATSC,
+       FC_SKY,
+       FC_SKY_OLD,
+       FC_CABLE,
+} flexcop_device_type_t;
+
+typedef enum {
+       FC_USB = 0,
+       FC_PCI,
+} flexcop_bus_t;
+
+extern const char *flexcop_device_names[];
+
+/* FlexCop IBI Registers */
+
+/* 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;
+
+typedef enum {
+       FC_I2C_PORT_DEMOD  = 1,
+       FC_I2C_PORT_EEPROM = 2,
+       FC_I2C_PORT_TUNER  = 3,
+} flexcop_i2c_port_t;
+
+typedef enum {
+       FC_WRITE = 0,
+       FC_READ  = 1,
+} flexcop_access_op_t;
+
+typedef enum {
+       FC_SRAM_DEST_NET   = 1,
+       FC_SRAM_DEST_CAI   = 2,
+       FC_SRAM_DEST_CAO   = 4,
+       FC_SRAM_DEST_MEDIA = 8
+} flexcop_sram_dest_t;
+
+typedef enum {
+       FC_SRAM_DEST_TARGET_WAN_USB = 0,
+       FC_SRAM_DEST_TARGET_DMA1    = 1,
+       FC_SRAM_DEST_TARGET_DMA2    = 2,
+       FC_SRAM_DEST_TARGET_FC3_CA  = 3
+} flexcop_sram_dest_target_t;
+
+typedef enum {
+       FC_SRAM_2_32KB  = 0, /*  64KB */
+       FC_SRAM_1_32KB  = 1, /*  32KB - default fow FCII */
+       FC_SRAM_1_128KB = 2, /* 128KB */
+       FC_SRAM_1_48KB  = 3, /*  48KB - default for FCIII */
+} flexcop_sram_type_t;
+
+typedef enum {
+       FC_WAN_SPEED_4MBITS  = 0,
+       FC_WAN_SPEED_8MBITS  = 1,
+       FC_WAN_SPEED_12MBITS = 2,
+       FC_WAN_SPEED_16MBITS = 3,
+} flexcop_wan_speed_t;
+
+typedef enum {
+       FC_DMA_1 = 1,
+       FC_DMA_2 = 2,
+} flexcop_dma_index_t;
+
+typedef enum {
+       FC_DMA_SUBADDR_0 = 1,
+       FC_DMA_SUBADDR_1 = 2,
+} flexcop_dma_addr_index_t;
+
+/* names of the particular registers */
+typedef enum {
+       dma1_000            = 0x000,
+       dma1_004            = 0x004,
+       dma1_008            = 0x008,
+       dma1_00c            = 0x00c,
+       dma2_010            = 0x010,
+       dma2_014            = 0x014,
+       dma2_018            = 0x018,
+       dma2_01c            = 0x01c,
+
+       tw_sm_c_100         = 0x100,
+       tw_sm_c_104         = 0x104,
+       tw_sm_c_108         = 0x108,
+       tw_sm_c_10c         = 0x10c,
+       tw_sm_c_110         = 0x110,
+
+       lnb_switch_freq_200 = 0x200,
+       misc_204            = 0x204,
+       ctrl_208            = 0x208,
+       irq_20c             = 0x20c,
+       sw_reset_210        = 0x210,
+       misc_214            = 0x214,
+       mbox_v8_to_host_218 = 0x218,
+       mbox_host_to_v8_21c = 0x21c,
+
+       pid_filter_300      = 0x300,
+       pid_filter_304      = 0x304,
+       pid_filter_308      = 0x308,
+       pid_filter_30c      = 0x30c,
+       index_reg_310       = 0x310,
+       pid_n_reg_314       = 0x314,
+       mac_low_reg_318     = 0x318,
+       mac_high_reg_31c    = 0x31c,
+
+       data_tag_400        = 0x400,
+       card_id_408         = 0x408,
+       card_id_40c         = 0x40c,
+       mac_address_418     = 0x418,
+       mac_address_41c     = 0x41c,
+
+       ci_600              = 0x600,
+       pi_604              = 0x604,
+       pi_608              = 0x608,
+       dvb_reg_60c         = 0x60c,
+
+       sram_ctrl_reg_700   = 0x700,
+       net_buf_reg_704     = 0x704,
+       cai_buf_reg_708     = 0x708,
+       cao_buf_reg_70c     = 0x70c,
+       media_buf_reg_710   = 0x710,
+       sram_dest_reg_714   = 0x714,
+       net_buf_reg_718     = 0x718,
+       wan_ctrl_reg_71c    = 0x71c,
+} flexcop_ibi_register;
+
+#define flexcop_set_ibi_value(reg,attr,val) { \
+       flexcop_ibi_value v = fc->read_ibi_reg(fc,reg); \
+       v.reg.attr = val; \
+       fc->write_ibi_reg(fc,reg,v); \
+}
+
+#endif
diff -urN linux/drivers/media/dvb/b2c2/flexcop-sram.c 
linux/drivers/media/dvb/b2c2/flexcop-sram.c
--- linux/drivers/media/dvb/b2c2/flexcop-sram.c 1970/01/01 00:00:00
+++ linux/drivers/media/dvb/b2c2/flexcop-sram.c 2005-05-26 10:12:42.381697000 
+0100     1.1
@@ -0,0 +1,403 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 
FlexcopII(b)/III
+ *
+ * flexcop-sram.c - functions for controlling the SRAM.
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+static void flexcop_sram_set_chip (struct flexcop_device *fc, 
flexcop_sram_type_t type)
+{
+       flexcop_set_ibi_value(wan_ctrl_reg_71c,sram_chip,type);
+}
+
+int flexcop_sram_init(struct flexcop_device *fc)
+{
+       switch (fc->rev) {
+               case FLEXCOP_II:
+               case FLEXCOP_IIB:
+                       flexcop_sram_set_chip(fc,FC_SRAM_1_32KB);
+                       break;
+               case FLEXCOP_III:
+                       flexcop_sram_set_chip(fc,FC_SRAM_1_48KB);
+                       break;
+               default:
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, 
flexcop_sram_dest_target_t target)
+{
+       flexcop_ibi_value v;
+
+       v = fc->read_ibi_reg(fc,sram_dest_reg_714);
+
+       if (fc->rev != FLEXCOP_III && target == FC_SRAM_DEST_TARGET_FC3_CA) {
+               err("SRAM destination target to available on FlexCopII(b)\n");
+               return -EINVAL;
+       }
+
+       deb_sram("sram dest: %x target: %x\n",dest, target);
+
+       if (dest & FC_SRAM_DEST_NET)
+               v.sram_dest_reg_714.NET_Dest = target;
+       if (dest & FC_SRAM_DEST_CAI)
+               v.sram_dest_reg_714.CAI_Dest = target;
+       if (dest & FC_SRAM_DEST_CAO)
+               v.sram_dest_reg_714.CAO_Dest = target;
+       if (dest & FC_SRAM_DEST_MEDIA)
+               v.sram_dest_reg_714.MEDIA_Dest = target;
+
+       fc->write_ibi_reg(fc,sram_dest_reg_714,v);
+       udelay(1000); /* TODO delay really necessary */
+
+       return 0;
+}
+EXPORT_SYMBOL(flexcop_sram_set_dest);
+
+void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s)
+{
+       flexcop_set_ibi_value(wan_ctrl_reg_71c,wan_speed_sig,s);
+}
+EXPORT_SYMBOL(flexcop_wan_set_speed);
+
+void flexcop_sram_ctrl(struct flexcop_device *fc, int usb_wan, int sramdma, 
int maximumfill)
+{
+       flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714);
+       v.sram_dest_reg_714.ctrl_usb_wan = usb_wan;
+       v.sram_dest_reg_714.ctrl_sramdma = sramdma;
+       v.sram_dest_reg_714.ctrl_maximumfill = maximumfill;
+       fc->write_ibi_reg(fc,sram_dest_reg_714,v);
+}
+EXPORT_SYMBOL(flexcop_sram_ctrl);
+
+#if 0
+static void flexcop_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 flexcop_sram_detect(struct flexcop_device *fc)
+{
+       flexcop_ibi_value r208,r71c_0,vr71c_1;
+
+       r208 = fc->read_ibi_reg(fc, ctrl_208);
+       fc->write_ibi_reg(fc, ctrl_208, ibi_zero);
+
+       r71c_0 = fc->read_ibi_reg(fc, wan_ctrl_reg_71c);
+
+       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);
+}
+
+#endif
diff -urN linux/drivers/media/dvb/b2c2/flexcop-usb.c 
linux/drivers/media/dvb/b2c2/flexcop-usb.c
--- linux/drivers/media/dvb/b2c2/flexcop-usb.c  1970/01/01 00:00:00
+++ linux/drivers/media/dvb/b2c2/flexcop-usb.c  2005-05-26 10:12:42.395072000 
+0100     1.1
@@ -0,0 +1,577 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 
FlexcopII(b)/III
+ *
+ * flexcop-usb.c - covers the USB part.
+ *
+ * see flexcop.c for copyright information.
+ */
+
+#define FC_LOG_PREFIX "flexcop_usb"
+#include "flexcop-usb.h"
+#include "flexcop-common.h"
+
+/* Version information */
+#define DRIVER_VERSION "0.1"
+#define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV USB Driver"
+#define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>"
+
+/* debug */
+#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
+#define dprintk(level,args...) \
+           do { if ((debug & level)) { printk(args); } } while (0)
+#define debug_dump(b,l,method) {\
+       int i; \
+       for (i = 0; i < l; i++) method("%02x ", b[i]); \
+       method("\n");\
+}
+
+#define DEBSTATUS ""
+#else
+#define dprintk(level,args...)
+#define debug_dump(b,l,method)
+#define DEBSTATUS " (debugging is not enabled)"
+#endif
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level 
(1=info,ts=2,ctrl=4,i2c=8,v8mem=16 (or-able))." DEBSTATUS);
+#undef DEBSTATUS
+
+#define deb_info(args...) dprintk(0x01,args)
+#define deb_ts(args...)   dprintk(0x02,args)
+#define deb_ctrl(args...) dprintk(0x04,args)
+#define deb_i2c(args...)  dprintk(0x08,args)
+#define deb_v8(args...)   dprintk(0x10,args)
+
+/* JLP 111700: we will include the 1 bit gap between the upper and lower 3 bits
+ * in the IBI address, to make the V8 code simpler.
+ * PCI ADDRESS FORMAT: 0x71C -> 0000 0111 0001 1100 (these are the six bits 
used)
+ *                  in general: 0000 0HHH 000L LL00
+ * IBI ADDRESS FORMAT:                    RHHH BLLL
+ *
+ * where R is the read(1)/write(0) bit, B is the busy bit
+ * and HHH and LLL are the two sets of three bits from the PCI address.
+ */
+#define B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(usPCI) (u8) (((usPCI >> 2) & 0x07) 
+ ((usPCI >> 4) & 0x70))
+#define B2C2_FLEX_INTERNALADDR_TO_PCIOFFSET(ucAddr) (u16) (((ucAddr & 0x07) << 
2) + ((ucAddr & 0x70) << 4))
+
+/*
+ * DKT 020228
+ * - forget about this VENDOR_BUFFER_SIZE, read and write register
+ *   deal with DWORD or 4 bytes, that should be should from now on
+ * - from now on, we don't support anything older than firm 1.00
+ *   I eliminated the write register as a 2 trip of writing hi word and lo word
+ *   and force this to write only 4 bytes at a time.
+ *   NOTE: this should work with all the firmware from 1.00 and newer
+ */
+static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 
wRegOffsPCI, u32 *val, u8 read)
+{
+       struct flexcop_usb *fc_usb = fc->bus_specific;
+       u8 request = read ? B2C2_USB_READ_REG : B2C2_USB_WRITE_REG;
+       u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR;
+       u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) | (read 
? 0x80 : 0);
+
+       int len = usb_control_msg(fc_usb->udev,
+                       read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT,
+                       request,
+                       request_type,  /* 0xc0 read or 0x40 write*/
+                       wAddress,
+                       0,
+                       val,
+                       sizeof(u32),
+                       B2C2_WAIT_FOR_OPERATION_RDW * HZ);
+
+       if (len != sizeof(u32)) {
+               err("error while %s dword from %d (%d).",read ? "reading" : 
"writing",
+                       wAddress,wRegOffsPCI);
+               return -EIO;
+       }
+       return 0;
+}
+
+/*
+ * DKT 010817 - add support for V8 memory read/write and flash update
+ */
+static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
+               flexcop_usb_request_t req, u8 page, u16 wAddress,
+               u8 *pbBuffer,u32 buflen)
+{
+//     u8 dwRequestType;
+       u8 request_type = USB_TYPE_VENDOR;
+       u16 wIndex;
+       int nWaitTime,pipe,len;
+
+       wIndex = page << 8;
+
+       switch (req) {
+               case B2C2_USB_READ_V8_MEM:
+                       nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
+                       request_type |= USB_DIR_IN;
+//                     dwRequestType = (u8) RTYPE_READ_V8_MEMORY;
+                       pipe = B2C2_USB_CTRL_PIPE_IN;
+               break;
+               case B2C2_USB_WRITE_V8_MEM:
+                       wIndex |= pbBuffer[0];
+                       request_type |= USB_DIR_OUT;
+                       nWaitTime = B2C2_WAIT_FOR_OPERATION_V8WRITE;
+//                     dwRequestType = (u8) RTYPE_WRITE_V8_MEMORY;
+                       pipe = B2C2_USB_CTRL_PIPE_OUT;
+               break;
+               case B2C2_USB_FLASH_BLOCK:
+                       request_type |= USB_DIR_OUT;
+                       nWaitTime = B2C2_WAIT_FOR_OPERATION_V8FLASH;
+//                     dwRequestType = (u8) RTYPE_WRITE_V8_FLASH;
+                       pipe = B2C2_USB_CTRL_PIPE_OUT;
+               break;
+               default:
+                       deb_info("unsupported request for v8_mem_req 
%x.\n",req);
+               return -EINVAL;
+       }
+       deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n",request_type,req,
+                       wAddress,wIndex,buflen);
+
+       len = usb_control_msg(fc_usb->udev,pipe,
+                       req,
+                       request_type,
+                       wAddress,
+                       wIndex,
+                       pbBuffer,
+                       buflen,
+                       nWaitTime * HZ);
+
+       debug_dump(pbBuffer,len,deb_v8);
+
+       return len == buflen ? 0 : -EIO;
+}
+
+#define bytes_left_to_read_on_page(paddr,buflen) \
+                       ((V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)) 
> buflen \
+                       ? buflen : (V8_MEMORY_PAGE_SIZE - (paddr & 
V8_MEMORY_PAGE_MASK)))
+
+static int flexcop_usb_memory_req(struct flexcop_usb 
*fc_usb,flexcop_usb_request_t req,
+               flexcop_usb_mem_page_t page_start, u32 addr, int extended, u8 
*buf, u32 len)
+{
+       int i,ret = 0;
+       u16 wMax;
+       u32 pagechunk = 0;
+
+       switch(req) {
+               case B2C2_USB_READ_V8_MEM:  wMax = USB_MEM_READ_MAX; break;
+               case B2C2_USB_WRITE_V8_MEM:     wMax = USB_MEM_WRITE_MAX; break;
+               case B2C2_USB_FLASH_BLOCK:  wMax = USB_FLASH_MAX; break;
+               default:
+                       return -EINVAL;
+               break;
+       }
+       for (i = 0; i < len;) {
+               pagechunk = wMax < bytes_left_to_read_on_page(addr,len) ? wMax 
: bytes_left_to_read_on_page(addr,len);
+               deb_info("%x\n",(addr & V8_MEMORY_PAGE_MASK) | 
(V8_MEMORY_EXTENDED*extended));
+               if ((ret = flexcop_usb_v8_memory_req(fc_usb,req,
+                               page_start + (addr / V8_MEMORY_PAGE_SIZE), /* 
actual page */
+                               (addr & V8_MEMORY_PAGE_MASK) | 
(V8_MEMORY_EXTENDED*extended),
+                               &buf[i],pagechunk)) < 0)
+                       return ret;
+
+               addr += pagechunk;
+               len -= pagechunk;
+       }
+       return 0;
+}
+
+static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended)
+{
+       return flexcop_usb_memory_req(fc->bus_specific,B2C2_USB_READ_V8_MEM,
+                       
V8_MEMORY_PAGE_FLASH,0x1f010,1,fc->dvb_adapter.proposed_mac,6);
+}
+
+#if 0
+static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set,
+               flexcop_usb_utility_function_t func, u8 extra, u16 wIndex,
+               u16 buflen, u8 *pvBuffer)
+{
+       u16 wValue;
+       u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR;
+//     u8 dwRequestType = (u8) RTYPE_GENERIC,
+       int nWaitTime = 2,
+               pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN,
+               len;
+
+       wValue = (func << 8) | extra;
+
+       len = usb_control_msg(fc_usb->udev,pipe,
+                       B2C2_USB_UTILITY,
+                       request_type,
+                       wValue,
+                       wIndex,
+                       pvBuffer,
+                       buflen,
+                       nWaitTime * HZ);
+       return len == buflen ? 0 : -EIO;
+}
+#endif
+
+/* usb i2c stuff */
+static int flexcop_usb_i2c_req(struct flexcop_usb *fc_usb,
+               flexcop_usb_request_t req, flexcop_usb_i2c_function_t func,
+               flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u8 
buflen)
+{
+       u16 wValue, wIndex;
+       int nWaitTime,pipe,len;
+//     u8 dwRequestType;
+       u8 request_type = USB_TYPE_VENDOR;
+
+       switch (func) {
+               case USB_FUNC_I2C_WRITE:
+               case USB_FUNC_I2C_MULTIWRITE:
+               case USB_FUNC_I2C_REPEATWRITE:
+               /* DKT 020208 - add this to support special case of DiSEqC */
+               case USB_FUNC_I2C_CHECKWRITE:
+                       pipe = B2C2_USB_CTRL_PIPE_OUT;
+                       nWaitTime = 2;
+//                     dwRequestType = (u8) RTYPE_GENERIC;
+                       request_type |= USB_DIR_OUT;
+               break;
+               case USB_FUNC_I2C_READ:
+               case USB_FUNC_I2C_REPEATREAD:
+                       pipe = B2C2_USB_CTRL_PIPE_IN;
+                       nWaitTime = 2;
+//                     dwRequestType = (u8) RTYPE_GENERIC;
+                       request_type |= USB_DIR_IN;
+               break;
+               default:
+                       deb_info("unsupported function for i2c_req %x\n",func);
+                       return -EINVAL;
+       }
+       wValue = (func << 8 ) | (port << 4);
+       wIndex = (chipaddr << 8 ) | addr;
+
+       deb_i2c("i2c %2d: %02x %02x %02x %02x %02x 
%02x\n",func,request_type,req,
+                       ((wValue && 0xff) << 8),wValue >> 8,((wIndex && 0xff) 
<< 8),wIndex >> 8);
+
+       len = usb_control_msg(fc_usb->udev,pipe,
+                       req,
+                       request_type,
+                       wValue,
+                       wIndex,
+                       buf,
+                       buflen,
+                       nWaitTime * HZ);
+
+       return len == buflen ? 0 : -EREMOTEIO;
+}
+
+/* actual bus specific access functions, make sure prototype are/will be equal 
to pci */
+static flexcop_ibi_value flexcop_usb_read_ibi_reg(struct flexcop_device *fc, 
flexcop_ibi_register reg)
+{
+       flexcop_ibi_value val;
+       val.raw = 0;
+       flexcop_usb_readwrite_dw(fc,reg, &val.raw, 1);
+       return val;
+}
+
+static int flexcop_usb_write_ibi_reg(struct flexcop_device *fc, 
flexcop_ibi_register reg, flexcop_ibi_value val)
+{
+       return flexcop_usb_readwrite_dw(fc,reg, &val.raw, 0);
+}
+
+static int flexcop_usb_i2c_request(struct flexcop_device *fc, 
flexcop_access_op_t op,
+               flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len)
+{
+       if (op == FC_READ)
+               return 
flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_READ,port,chipaddr,addr,buf,len);
+       else
+               return 
flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_WRITE,port,chipaddr,addr,buf,len);
+}
+
+static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, 
int buffer_length)
+{
+       u8 *b;
+       int l;
+
+       deb_ts("tmp_buffer_length=%d, buffer_length=%d\n", 
fc_usb->tmp_buffer_length, buffer_length);
+
+       if (fc_usb->tmp_buffer_length > 0) {
+               memcpy(fc_usb->tmp_buffer+fc_usb->tmp_buffer_length, buffer, 
buffer_length);
+               fc_usb->tmp_buffer_length += buffer_length;
+               b = fc_usb->tmp_buffer;
+               l = fc_usb->tmp_buffer_length;
+       } else {
+               b=buffer;
+               l=buffer_length;
+       }
+
+       while (l >= 190) {
+               if (*b == 0xff)
+                       switch (*(b+1) & 0x03) {
+                               case 0x01: /* media packet */
+                                       if ( *(b+2) == 0x47 )
+                                               
flexcop_pass_dmx_packets(fc_usb->fc_dev, b+2, 1);
+                                       else
+                                               deb_ts("not ts packet %02x %02x 
%02x %02x \n", *(b+2), *(b+3), *(b+4), *(b+5) );
+
+                                       b += 190;
+                                       l -= 190;
+                               break;
+                               default:
+                                       deb_ts("wrong packet type\n");
+                                       l = 0;
+                               break;
+                       }
+               else {
+                       deb_ts("wrong header\n");
+                       l = 0;
+               }
+       }
+
+       if (l>0)
+               memcpy(fc_usb->tmp_buffer, b, l);
+       fc_usb->tmp_buffer_length = l;
+}
+
+static void flexcop_usb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
+{
+       struct flexcop_usb *fc_usb = urb->context;
+       int i;
+
+       if (urb->actual_length > 0)
+               deb_ts("urb completed, bufsize: %d actlen; 
%d\n",urb->transfer_buffer_length, urb->actual_length);
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               if (urb->iso_frame_desc[i].status < 0) {
+                       err("iso frame descriptor %d has an error: 
%d\n",i,urb->iso_frame_desc[i].status);
+               } else
+                       if (urb->iso_frame_desc[i].actual_length > 0) {
+                               deb_ts("passed %d bytes to the 
demux\n",urb->iso_frame_desc[i].actual_length);
+
+                               flexcop_usb_process_frame(fc_usb,
+                                       urb->transfer_buffer + 
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;
+       }
+
+       usb_submit_urb(urb,GFP_ATOMIC);
+}
+
+static int flexcop_usb_stream_control(struct flexcop_device *fc, int onoff)
+{
+       /* submit/kill iso packets */
+       return 0;
+}
+
+static void flexcop_usb_transfer_exit(struct flexcop_usb *fc_usb)
+{
+       int i;
+       for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++)
+               if (fc_usb->iso_urb[i] != NULL) {
+                       deb_ts("unlinking/killing urb no. %d\n",i);
+                       usb_kill_urb(fc_usb->iso_urb[i]);
+                       usb_free_urb(fc_usb->iso_urb[i]);
+               }
+
+       if (fc_usb->iso_buffer != NULL)
+               pci_free_consistent(NULL,fc_usb->buffer_size, 
fc_usb->iso_buffer, fc_usb->dma_addr);
+}
+
+static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb)
+{
+       u16 frame_size = 
fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize;
+       int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * 
frame_size,i,j,ret;
+       int buffer_offset = 0;
+
+       deb_ts("creating %d iso-urbs with %d frames each of %d bytes size = 
%d.\n",
+                       B2C2_USB_NUM_ISO_URB, B2C2_USB_FRAMES_PER_ISO, 
frame_size,bufsize);
+
+       fc_usb->iso_buffer = 
pci_alloc_consistent(NULL,bufsize,&fc_usb->dma_addr);
+       if (fc_usb->iso_buffer == NULL)
+               return -ENOMEM;
+       memset(fc_usb->iso_buffer, 0, bufsize);
+       fc_usb->buffer_size = bufsize;
+
+       /* creating iso urbs */
+       for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++)
+               if (!(fc_usb->iso_urb[i] = 
usb_alloc_urb(B2C2_USB_FRAMES_PER_ISO,GFP_ATOMIC))) {
+                       ret = -ENOMEM;
+                       goto urb_error;
+               }
+       /* initialising and submitting iso urbs */
+       for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) {
+               int frame_offset = 0;
+               struct urb *urb = fc_usb->iso_urb[i];
+               deb_ts("initializing and submitting urb no. %d (buf_offset: 
%d).\n",i,buffer_offset);
+
+               urb->dev = fc_usb->udev;
+               urb->context = fc_usb;
+               urb->complete = flexcop_usb_urb_complete;
+               urb->pipe = B2C2_USB_DATA_PIPE;
+               urb->transfer_flags = URB_ISO_ASAP;
+               urb->interval = 1;
+               urb->number_of_packets = B2C2_USB_FRAMES_PER_ISO;
+               urb->transfer_buffer_length = frame_size * 
B2C2_USB_FRAMES_PER_ISO;
+               urb->transfer_buffer = fc_usb->iso_buffer + buffer_offset;
+
+               buffer_offset += frame_size * B2C2_USB_FRAMES_PER_ISO;
+               for (j = 0; j < B2C2_USB_FRAMES_PER_ISO; j++) {
+                       deb_ts("urb no: %d, frame: %d, frame_offset: 
%d\n",i,j,frame_offset);
+                       urb->iso_frame_desc[j].offset = frame_offset;
+                       urb->iso_frame_desc[j].length = frame_size;
+                       frame_offset += frame_size;
+               }
+
+               if ((ret = usb_submit_urb(fc_usb->iso_urb[i],GFP_ATOMIC))) {
+                       err("submitting urb %d failed with %d.",i,ret);
+                       goto urb_error;
+               }
+               deb_ts("submitted urb no. %d.\n",i);
+       }
+
+/* SRAM */
+
+       flexcop_sram_set_dest(fc_usb->fc_dev,FC_SRAM_DEST_MEDIA | 
FC_SRAM_DEST_NET |
+                       FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, 
FC_SRAM_DEST_TARGET_WAN_USB);
+       flexcop_wan_set_speed(fc_usb->fc_dev,FC_WAN_SPEED_8MBITS);
+       flexcop_sram_ctrl(fc_usb->fc_dev,1,1,1);
+
+       ret = 0;
+       goto success;
+urb_error:
+       flexcop_usb_transfer_exit(fc_usb);
+success:
+       return ret;
+}
+
+static int flexcop_usb_init(struct flexcop_usb *fc_usb)
+{
+       /* use the alternate setting with the larges buffer */
+       usb_set_interface(fc_usb->udev,0,1);
+       switch (fc_usb->udev->speed) {
+               case USB_SPEED_LOW:
+                       err("cannot handle USB speed because it is to sLOW.");
+                       return -ENODEV;
+                       break;
+               case USB_SPEED_FULL:
+                       info("running at FULL speed.");
+                       break;
+               case USB_SPEED_HIGH:
+                       info("running at HIGH speed.");
+                       break;
+               case USB_SPEED_UNKNOWN: /* fall through */
+               default:
+                       err("cannot handle USB speed because it is unkown.");
+                       return -ENODEV;
+       }
+       usb_set_intfdata(fc_usb->uintf, fc_usb);
+       return 0;
+}
+
+static void flexcop_usb_exit(struct flexcop_usb *fc_usb)
+{
+       usb_set_intfdata(fc_usb->uintf, NULL);
+}
+
+static int flexcop_usb_probe(struct usb_interface *intf,
+               const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct flexcop_usb *fc_usb = NULL;
+       struct flexcop_device *fc = NULL;
+       int ret;
+
+       if ((fc = flexcop_device_kmalloc(sizeof(struct flexcop_usb))) == NULL) {
+               err("out of memory\n");
+               return -ENOMEM;
+       }
+
+/* general flexcop init */
+       fc_usb = fc->bus_specific;
+       fc_usb->fc_dev = fc;
+
+       fc->read_ibi_reg  = flexcop_usb_read_ibi_reg;
+       fc->write_ibi_reg = flexcop_usb_write_ibi_reg;
+       fc->i2c_request = flexcop_usb_i2c_request;
+       fc->get_mac_addr = flexcop_usb_get_mac_addr;
+
+       fc->stream_control = flexcop_usb_stream_control;
+
+       fc->pid_filtering = 1;
+       fc->bus_type = FC_USB;
+
+       fc->dev = &udev->dev;
+       fc->owner = THIS_MODULE;
+
+/* bus specific part */
+       fc_usb->udev = udev;
+       fc_usb->uintf = intf;
+       if ((ret = flexcop_usb_init(fc_usb)) != 0)
+               goto err_kfree;
+
+/* init flexcop */
+       if ((ret = flexcop_device_initialize(fc)) != 0)
+               goto err_usb_exit;
+
+/* xfer init */
+       if ((ret = flexcop_usb_transfer_init(fc_usb)) != 0)
+               goto err_fc_exit;
+
+       info("%s successfully initialized and connected.",DRIVER_NAME);
+       ret = 0;
+       goto success;
+err_fc_exit:
+       flexcop_device_exit(fc);
+err_usb_exit:
+       flexcop_usb_exit(fc_usb);
+err_kfree:
+       flexcop_device_kfree(fc);
+success:
+       return ret;
+}
+
+static void flexcop_usb_disconnect(struct usb_interface *intf)
+{
+       struct flexcop_usb *fc_usb = usb_get_intfdata(intf);
+       flexcop_usb_transfer_exit(fc_usb);
+       flexcop_device_exit(fc_usb->fc_dev);
+       flexcop_usb_exit(fc_usb);
+       flexcop_device_kfree(fc_usb->fc_dev);
+       info("%s successfully deinitialized and disconnected.",DRIVER_NAME);
+}
+
+static struct usb_device_id flexcop_usb_table [] = {
+           { USB_DEVICE(0x0af7, 0x0101) },
+           { }
+};
+
+/* 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",
+       .probe          = flexcop_usb_probe,
+       .disconnect = flexcop_usb_disconnect,
+       .id_table       = flexcop_usb_table,
+};
+
+/* module stuff */
+static int __init flexcop_usb_module_init(void)
+{
+       int result;
+       if ((result = usb_register(&flexcop_usb_driver))) {
+               err("usb_register failed. (%d)",result);
+               return result;
+       }
+
+       return 0;
+}
+
+static void __exit flexcop_usb_module_exit(void)
+{
+       /* deregister this driver from the USB subsystem */
+       usb_deregister(&flexcop_usb_driver);
+}
+
+module_init(flexcop_usb_module_init);
+module_exit(flexcop_usb_module_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_NAME);
+MODULE_LICENSE("GPL");
diff -urN linux/drivers/media/dvb/b2c2/flexcop-usb.h 
linux/drivers/media/dvb/b2c2/flexcop-usb.h
--- linux/drivers/media/dvb/b2c2/flexcop-usb.h  1970/01/01 00:00:00
+++ linux/drivers/media/dvb/b2c2/flexcop-usb.h  2005-05-26 10:12:42.410907000 
+0100     1.1
@@ -0,0 +1,119 @@
+#ifndef __FLEXCOP_USB_H_INCLUDED__
+#define __FLEXCOP_USB_H_INCLUDED__
+
+#include <linux/usb.h>
+
+/* transfer parameters */
+#define B2C2_USB_FRAMES_PER_ISO                4
+#define B2C2_USB_NUM_ISO_URB           4
+
+#define B2C2_USB_CTRL_PIPE_IN          usb_rcvctrlpipe(fc_usb->udev,0)
+#define B2C2_USB_CTRL_PIPE_OUT         usb_sndctrlpipe(fc_usb->udev,0)
+#define B2C2_USB_DATA_PIPE                     
usb_rcvisocpipe(fc_usb->udev,0x81)
+
+struct flexcop_usb {
+       struct usb_device *udev;
+       struct usb_interface *uintf;
+
+       u8 *iso_buffer;
+       int buffer_size;
+       dma_addr_t dma_addr;
+       struct urb *iso_urb[B2C2_USB_NUM_ISO_URB];
+
+       struct flexcop_device *fc_dev;
+
+       u8 tmp_buffer[1023+190];
+       int tmp_buffer_length;
+};
+
+#if 0
+/* request types TODO What is its use?*/
+typedef enum {
+
+/* something is wrong with this part
+       RTYPE_READ_DW         = (1 << 6),
+       RTYPE_WRITE_DW_1      = (3 << 6),
+       RTYPE_READ_V8_MEMORY  = (6 << 6),
+       RTYPE_WRITE_V8_MEMORY = (7 << 6),
+       RTYPE_WRITE_V8_FLASH  = (8 << 6),
+       RTYPE_GENERIC         = (9 << 6),
+*/
+} flexcop_usb_request_type_t;
+#endif
+
+/* request */
+typedef enum {
+       B2C2_USB_WRITE_V8_MEM = 0x04,
+       B2C2_USB_READ_V8_MEM  = 0x05,
+       B2C2_USB_READ_REG     = 0x08,
+       B2C2_USB_WRITE_REG    = 0x0A,
+/*     B2C2_USB_WRITEREGLO   = 0x0A, */
+       B2C2_USB_WRITEREGHI   = 0x0B,
+       B2C2_USB_FLASH_BLOCK  = 0x10,
+       B2C2_USB_I2C_REQUEST  = 0x11,
+       B2C2_USB_UTILITY      = 0x12,
+} flexcop_usb_request_t;
+
+/* function definition for I2C_REQUEST */
+typedef enum {
+       USB_FUNC_I2C_WRITE       = 0x01,
+       USB_FUNC_I2C_MULTIWRITE  = 0x02,
+       USB_FUNC_I2C_READ        = 0x03,
+       USB_FUNC_I2C_REPEATWRITE = 0x04,
+       USB_FUNC_GET_DESCRIPTOR  = 0x05,
+       USB_FUNC_I2C_REPEATREAD  = 0x06,
+/* DKT 020208 - add this to support special case of DiSEqC */
+       USB_FUNC_I2C_CHECKWRITE  = 0x07,
+       USB_FUNC_I2C_CHECKRESULT = 0x08,
+} flexcop_usb_i2c_function_t;
+
+/*
+ * function definition for UTILITY request 0x12
+ * DKT 020304 - new utility function
+ */
+typedef enum {
+       UTILITY_SET_FILTER          = 0x01,
+       UTILITY_DATA_ENABLE         = 0x02,
+       UTILITY_FLEX_MULTIWRITE     = 0x03,
+       UTILITY_SET_BUFFER_SIZE     = 0x04,
+       UTILITY_FLEX_OPERATOR       = 0x05,
+       UTILITY_FLEX_RESET300_START = 0x06,
+       UTILITY_FLEX_RESET300_STOP  = 0x07,
+       UTILITY_FLEX_RESET300       = 0x08,
+       UTILITY_SET_ISO_SIZE        = 0x09,
+       UTILITY_DATA_RESET          = 0x0A,
+       UTILITY_GET_DATA_STATUS     = 0x10,
+       UTILITY_GET_V8_REG          = 0x11,
+/* DKT 020326 - add function for v1.14 */
+       UTILITY_SRAM_WRITE          = 0x12,
+       UTILITY_SRAM_READ           = 0x13,
+       UTILITY_SRAM_TESTFILL       = 0x14,
+       UTILITY_SRAM_TESTSET        = 0x15,
+       UTILITY_SRAM_TESTVERIFY     = 0x16,
+} flexcop_usb_utility_function_t;
+
+#define B2C2_WAIT_FOR_OPERATION_RW  1*HZ       /* 1 s */
+#define B2C2_WAIT_FOR_OPERATION_RDW 3*HZ       /* 3 s */
+#define B2C2_WAIT_FOR_OPERATION_WDW 1*HZ       /* 1 s */
+
+#define B2C2_WAIT_FOR_OPERATION_V8READ   3*HZ  /* 3 s */
+#define B2C2_WAIT_FOR_OPERATION_V8WRITE  3*HZ  /* 3 s */
+#define B2C2_WAIT_FOR_OPERATION_V8FLASH  3*HZ  /* 3 s */
+
+typedef enum {
+       V8_MEMORY_PAGE_DVB_CI = 0x20,
+       V8_MEMORY_PAGE_DVB_DS = 0x40,
+       V8_MEMORY_PAGE_MULTI2 = 0x60,
+       V8_MEMORY_PAGE_FLASH  = 0x80
+} flexcop_usb_mem_page_t;
+
+#define V8_MEMORY_EXTENDED      (1 << 15)
+
+#define USB_MEM_READ_MAX                32
+#define USB_MEM_WRITE_MAX               1
+#define USB_FLASH_MAX                   8
+
+#define V8_MEMORY_PAGE_SIZE     0x8000      // 32K
+#define V8_MEMORY_PAGE_MASK     0x7FFF
+
+#endif
diff -urN linux/drivers/media/dvb/b2c2/flexcop.c 
linux/drivers/media/dvb/b2c2/flexcop.c
--- linux/drivers/media/dvb/b2c2/flexcop.c      1970/01/01 00:00:00
+++ linux/drivers/media/dvb/b2c2/flexcop.c      2005-05-26 10:12:42.422791000 
+0100     1.1
@@ -0,0 +1,286 @@
+/*
+ * flexcop.c - driver for digital TV devices equipped with B2C2 
FlexcopII(b)/III
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher <patrick.boettcher@desy.de>
+ *
+ * based on the skystar2-driver
+ * Copyright (C) 2003 Vadim Catana, skystar@moldova.cc
+ *
+ * Acknowledgements:
+ *     John Jurrius from BBTI, Inc. for extensive support with
+ *         code examples and data books
+ *
+ *     Bjarne Steinsbo, bjarne at steinsbo.com (some ideas for rewriting)
+ *
+ * Contributions to the skystar2-driver have been done by
+ *     Vincenzo Di Massa, hawk.it at tiscalinet.it (several DiSEqC fixes)
+ *     Roberto Ragusa, r.ragusa at libero.it (polishing, restyling the code)
+ *     Niklas Peinecke, peinecke at gdv.uni-hannover.de (hardware pid/mac 
filtering)
+ *
+ *
+ * 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 "flexcop.h"
+
+#define DRIVER_NAME "B2C2 FlexcopII/II(b)/III digital TV receiver chip"
+#define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de"
+
+#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
+#define DEBSTATUS ""
+#else
+#define DEBSTATUS " (debugging is not enabled)"
+#endif
+
+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);
+#undef DEBSTATUS
+
+/* global zero for ibi values */
+flexcop_ibi_value ibi_zero;
+
+static int flexcop_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+       struct flexcop_device *fc = dvbdmxfeed->demux->priv;
+       return flexcop_pid_feed_control(fc,dvbdmxfeed,1);
+}
+
+static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+       struct flexcop_device *fc = dvbdmxfeed->demux->priv;
+       return flexcop_pid_feed_control(fc,dvbdmxfeed,0);
+}
+
+static int flexcop_dvb_init(struct flexcop_device *fc)
+{
+       int ret;
+       if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV 
device",fc->owner)) < 0) {
+               err("error registering DVB adapter");
+               return ret;
+       }
+       fc->dvb_adapter.priv = fc;
+
+       fc->demux.dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING 
| DMX_MEMORY_BASED_FILTERING);
+       fc->demux.priv = fc;
+
+       fc->demux.filternum = fc->demux.feednum = FC_MAX_FEED;
+
+       fc->demux.start_feed = flexcop_dvb_start_feed;
+       fc->demux.stop_feed = flexcop_dvb_stop_feed;
+       fc->demux.write_to_decoder = NULL;
+
+       if ((ret = dvb_dmx_init(&fc->demux)) < 0) {
+               err("dvb_dmx failed: error %d",ret);
+               goto err_dmx;
+       }
+
+       fc->hw_frontend.source = DMX_FRONTEND_0;
+
+       fc->dmxdev.filternum = fc->demux.feednum;
+       fc->dmxdev.demux = &fc->demux.dmx;
+       fc->dmxdev.capabilities = 0;
+       if ((ret = dvb_dmxdev_init(&fc->dmxdev, &fc->dvb_adapter)) < 0) {
+               err("dvb_dmxdev_init failed: error %d",ret);
+               goto err_dmx_dev;
+       }
+
+       if ((ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, 
&fc->hw_frontend)) < 0) {
+               err("adding hw_frontend to dmx failed: error %d",ret);
+               goto err_dmx_add_hw_frontend;
+       }
+
+       fc->mem_frontend.source = DMX_MEMORY_FE;
+       if ((ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, 
&fc->mem_frontend)) < 0) {
+               err("adding mem_frontend to dmx failed: error %d",ret);
+               goto err_dmx_add_mem_frontend;
+       }
+
+       if ((ret = fc->demux.dmx.connect_frontend(&fc->demux.dmx, 
&fc->hw_frontend)) < 0) {
+               err("connect frontend failed: error %d",ret);
+               goto err_connect_frontend;
+       }
+
+       dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx);
+
+       fc->init_state |= FC_STATE_DVB_INIT;
+       goto success;
+
+err_connect_frontend:
+       fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend);
+err_dmx_add_mem_frontend:
+       fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->hw_frontend);
+err_dmx_add_hw_frontend:
+       dvb_dmxdev_release(&fc->dmxdev);
+err_dmx_dev:
+       dvb_dmx_release(&fc->demux);
+err_dmx:
+       dvb_unregister_adapter(&fc->dvb_adapter);
+       return ret;
+
+success:
+       return 0;
+}
+
+static void flexcop_dvb_exit(struct flexcop_device *fc)
+{
+       if (fc->init_state & FC_STATE_DVB_INIT) {
+               dvb_net_release(&fc->dvbnet);
+
+               fc->demux.dmx.close(&fc->demux.dmx);
+               fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend);
+               fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->hw_frontend);
+               dvb_dmxdev_release(&fc->dmxdev);
+               dvb_dmx_release(&fc->demux);
+               dvb_unregister_adapter(&fc->dvb_adapter);
+
+               deb_info("deinitialized dvb stuff\n");
+       }
+       fc->init_state &= ~FC_STATE_DVB_INIT;
+}
+
+/* these methods are necessary to achieve the long-term-goal of hiding the
+ * struct flexcop_device from the bus-parts */
+void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len)
+{
+       dvb_dmx_swfilter(&fc->demux, buf, len);
+}
+EXPORT_SYMBOL(flexcop_pass_dmx_data);
+
+void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no)
+{
+       dvb_dmx_swfilter_packets(&fc->demux, buf, no);
+}
+EXPORT_SYMBOL(flexcop_pass_dmx_packets);
+
+static void flexcop_reset(struct flexcop_device *fc)
+{
+       flexcop_ibi_value v210,v204;
+
+/* reset the flexcop itself */
+       fc->write_ibi_reg(fc,ctrl_208,ibi_zero);
+
+       v210.raw = 0;
+       v210.sw_reset_210.reset_blocks = 0xff;
+       v210.sw_reset_210.Block_reset_enable = 0xb2;
+       fc->write_ibi_reg(fc,sw_reset_210,v210);
+
+/* reset the periphical devices */
+
+       v204 = fc->read_ibi_reg(fc,misc_204);
+       v204.misc_204.Per_reset_sig = 0;
+       fc->write_ibi_reg(fc,misc_204,v204);
+       v204.misc_204.Per_reset_sig = 1;
+       fc->write_ibi_reg(fc,misc_204,v204);
+}
+
+struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len)
+{
+       void *bus;
+       struct flexcop_device *fc = kmalloc(sizeof(struct flexcop_device), 
GFP_KERNEL);
+       if (!fc) {
+               err("no memory");
+               return NULL;
+       }
+       memset(fc, 0, sizeof(struct flexcop_device));
+
+       bus = kmalloc(bus_specific_len, GFP_KERNEL);
+       if (!bus) {
+               err("no memory");
+               kfree(fc);
+               return NULL;
+       }
+       memset(bus, 0, bus_specific_len);
+
+       fc->bus_specific = bus;
+
+       return fc;
+}
+EXPORT_SYMBOL(flexcop_device_kmalloc);
+
+void flexcop_device_kfree(struct flexcop_device *fc)
+{
+       kfree(fc->bus_specific);
+       kfree(fc);
+}
+EXPORT_SYMBOL(flexcop_device_kfree);
+
+int flexcop_device_initialize(struct flexcop_device *fc)
+{
+       int ret;
+       ibi_zero.raw = 0;
+
+       flexcop_reset(fc);
+       flexcop_determine_revision(fc);
+       flexcop_sram_init(fc);
+       flexcop_hw_filter_init(fc);
+
+       flexcop_smc_ctrl(fc, 0);
+
+       if ((ret = flexcop_dvb_init(fc)))
+               goto error;
+
+       /* do the MAC address reading after initializing the dvb_adapter */
+       if (fc->get_mac_addr(fc, 0) == 0) {
+               u8 *b = fc->dvb_adapter.proposed_mac;
+               info("MAC address = %02x:%02x:%02x:%02x:%02x:%02x", 
b[0],b[1],b[2],b[3],b[4],b[5]);
+               flexcop_set_mac_filter(fc,b);
+               flexcop_mac_filter_ctrl(fc,1);
+       } else
+               warn("reading of MAC address failed.\n");
+
+
+       if ((ret = flexcop_i2c_init(fc)))
+               goto error;
+
+       if ((ret = flexcop_frontend_init(fc)))
+               goto error;
+
+       flexcop_device_name(fc,"initialization of","complete");
+
+       ret = 0;
+       goto success;
+error:
+       flexcop_device_exit(fc);
+success:
+       return ret;
+}
+EXPORT_SYMBOL(flexcop_device_initialize);
+
+void flexcop_device_exit(struct flexcop_device *fc)
+{
+       flexcop_frontend_exit(fc);
+       flexcop_i2c_exit(fc);
+       flexcop_dvb_exit(fc);
+}
+EXPORT_SYMBOL(flexcop_device_exit);
+
+static int flexcop_module_init(void)
+{
+       info(DRIVER_NAME " loaded successfully");
+       return 0;
+}
+
+static void flexcop_module_cleanup(void)
+{
+       info(DRIVER_NAME " unloaded successfully");
+}
+
+module_init(flexcop_module_init);
+module_exit(flexcop_module_cleanup);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_NAME);
+MODULE_LICENSE("GPL");
diff -urN linux/drivers/media/dvb/b2c2/flexcop.h 
linux/drivers/media/dvb/b2c2/flexcop.h
--- linux/drivers/media/dvb/b2c2/flexcop.h      1970/01/01 00:00:00
+++ linux/drivers/media/dvb/b2c2/flexcop.h      2005-05-26 10:12:42.435810000 
+0100     1.1
@@ -0,0 +1,30 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 
FlexcopII(b)/III
+ *
+ * flexcop.h - private header file for all flexcop-chip-source files.
+ *
+ * see flexcop.c for copyright information.
+ */
+#ifndef __FLEXCOP_H__
+#define __FLEXCOP_H___
+
+#define FC_LOG_PREFIX "b2c2-flexcop"
+#include "flexcop-common.h"
+
+extern int b2c2_flexcop_debug;
+
+/* debug */
+#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
+#define dprintk(level,args...) \
+       do { if ((b2c2_flexcop_debug & level)) printk(args); } while (0)
+#else
+#define dprintk(level,args...)
+#endif
+
+#define deb_info(args...)  dprintk(0x01,args)
+#define deb_tuner(args...) dprintk(0x02,args)
+#define deb_i2c(args...)   dprintk(0x04,args)
+#define deb_ts(args...)    dprintk(0x08,args)
+#define deb_sram(args...)  dprintk(0x10,args)
+
+#endif
diff -urN linux/drivers/media/dvb/b2c2/Kconfig 
linux/drivers/media/dvb/b2c2/Kconfig
--- linux/drivers/media/dvb/b2c2/Kconfig        2005/02/07 02:54:47     1.4
+++ linux/drivers/media/dvb/b2c2/Kconfig        2005/05/26 09:12:42     1.5
@@ -1,26 +1,50 @@
-config DVB_B2C2_SKYSTAR
-       tristate "B2C2/Technisat Air/Sky/CableStar 2 PCI"
-       depends on DVB_CORE && PCI
+config DVB_B2C2_FLEXCOP
+       tristate "Technisat/B2C2 FlexCopII(b) and FlexCopIII adapters"
+       depends on DVB_CORE
        select DVB_STV0299
        select DVB_MT352
        select DVB_MT312
        select DVB_NXT2002
+       select DVB_STV0297
        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.
+         Support for the digital TV receiver chip made by B2C2 Inc. included in
+         Technisats PCI cards and USB boxes.
 
          Say Y if you own such a device and want to use it.
 
-config DVB_B2C2_USB
-       tristate "B2C2/Technisat Air/Sky/Cable2PC USB"
-       depends on DVB_CORE && USB && EXPERIMENTAL
+config DVB_B2C2_FLEXCOP_PCI
+       tristate "Technisat/B2C2 Air/Sky/Cable2PC PCI"
+       depends on DVB_B2C2_FLEXCOP && PCI
+       help
+         Support for the Air/Sky/CableStar2 PCI card (DVB/ATSC) by 
Technisat/B2C2.
+
+         Say Y if you own such a device and want to use it.
+
+config DVB_B2C2_FLEXCOP_USB
+       tristate "Technisat/B2C2 Air/Sky/Cable2PC USB"
+       depends on DVB_B2C2_FLEXCOP && USB
+       help
+         Support for the Air/Sky/Cable2PC USB1.1 box (DVB/ATSC) by 
Technisat/B2C2,
+
+         Say Y if you own such a device and want to use it.
+
+config DVB_B2C2_FLEXCOP_DEBUG
+       bool "Enable debug for the B2C2 FlexCop drivers"
+       depends on DVB_B2C2_FLEXCOP
+       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 Air/Sky/Cable2PC USB DVB device by B2C2. Currently
-         the does nothing, but providing basic function for the used usb 
-         protocol.
+         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.
-
diff -urN linux/drivers/media/dvb/b2c2/Makefile 
linux/drivers/media/dvb/b2c2/Makefile
--- linux/drivers/media/dvb/b2c2/Makefile       2004/12/27 02:15:54     1.2
+++ linux/drivers/media/dvb/b2c2/Makefile       2005/05/26 09:12:42     1.3
@@ -1,6 +1,14 @@
-obj-b2c2-usb = b2c2-usb-core.o b2c2-common.o
+b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \
+       flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o \
+       flexcop-dma.o
+obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
+
+b2c2-flexcop-pci-objs = flexcop-pci.o
+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
-obj-$(CONFIG_DVB_B2C2_USB) + = b2c2-usb.o
 
 EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff -urN linux/drivers/media/dvb/b2c2/skystar2.c 
linux/drivers/media/dvb/b2c2/skystar2.c
--- linux/drivers/media/dvb/b2c2/skystar2.c     2005/04/08 18:58:16     1.13
+++ linux/drivers/media/dvb/b2c2/skystar2.c     2005/05/26 09:12:42     1.14
@@ -97,7 +97,7 @@
        u8 mac_addr[8];
        u32 dw_sram_type;
 
-       struct dvb_adapter *dvb_adapter;
+       struct dvb_adapter dvb_adapter;
        struct dvb_demux demux;
        struct dmxdev dmxdev;
        struct dmx_frontend hw_frontend;
@@ -2461,7 +2461,7 @@
                       skystar2->pdev->subsystem_vendor,
                       skystar2->pdev->subsystem_device);
        } else {
-               if (dvb_register_frontend(skystar2->dvb_adapter, skystar2->fe)) 
{
+               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);
@@ -2486,17 +2486,17 @@
        if (ret < 0)
                goto out;
 
-       ret = dvb_register_adapter(&dvb_adapter, skystar2_pci_driver.name,
+       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;
        }
 
-       adapter = pci_get_drvdata(pdev);
-
        dvb_adapter->priv = adapter;
-       adapter->dvb_adapter = dvb_adapter;
 
 
        init_MUTEX(&adapter->i2c_sem);
@@ -2541,7 +2541,7 @@
        adapter->dmxdev.demux = dmx;
        adapter->dmxdev.capabilities = 0;
 
-       ret = dvb_dmxdev_init(&adapter->dmxdev, adapter->dvb_adapter);
+       ret = dvb_dmxdev_init(&adapter->dmxdev, &adapter->dvb_adapter);
        if (ret < 0)
                goto err_dmx_release;
 
@@ -2559,7 +2559,7 @@
        if (ret < 0)
                goto err_remove_mem_frontend;
 
-       dvb_net_init(adapter->dvb_adapter, &adapter->dvbnet, &dvbdemux->dmx);
+       dvb_net_init(&adapter->dvb_adapter, &adapter->dvbnet, &dvbdemux->dmx);
 
        frontend_init(adapter);
 out:
@@ -2576,7 +2576,7 @@
 err_i2c_del:
        i2c_del_adapter(&adapter->i2c_adap);
 err_dvb_unregister:
-       dvb_unregister_adapter(adapter->dvb_adapter);
+       dvb_unregister_adapter(&adapter->dvb_adapter);
 err_halt:
        driver_halt(pdev);
        goto out;
@@ -2605,7 +2605,7 @@
        if (adapter->fe != NULL)
                dvb_unregister_frontend(adapter->fe);
 
-       dvb_unregister_adapter(adapter->dvb_adapter);
+       dvb_unregister_adapter(&adapter->dvb_adapter);
 
                        i2c_del_adapter(&adapter->i2c_adap);
 
diff -urN linux/drivers/media/dvb/b2c2/b2c2-common.c 
linux/drivers/media/dvb/b2c2/b2c2-common.c
--- linux/drivers/media/dvb/b2c2/Attic/b2c2-common.c    2005-05-26 
10:12:42.508186000 +0100     1.2
+++ linux/drivers/media/dvb/b2c2/Attic/b2c2-common.c    1970/01/01 00:00:00+0100
@@ -1,214 +0,0 @@
-/*
- * b2c2-common.c - common methods for the B2C2/Technisat SkyStar2 PCI DVB card 
and
- *                 for the B2C2/Technisat Sky/Cable/AirStar USB devices
- *                 based on the FlexCopII/FlexCopIII 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, r.ragusa at libero.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 "stv0299.h"
-#include "mt352.h"
-#include "mt312.h"
-
-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 samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
-{
-       static u8 mt352_clock_config [] = { 0x89, 0x10, 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,
-};
diff -urN linux/drivers/media/dvb/b2c2/b2c2-usb-core.c 
linux/drivers/media/dvb/b2c2/b2c2-usb-core.c
--- linux/drivers/media/dvb/b2c2/Attic/b2c2-usb-core.c  2005-05-26 
10:12:42.520751000 +0100     1.4
+++ linux/drivers/media/dvb/b2c2/Attic/b2c2-usb-core.c  1970/01/01 00:00:00+0100
@@ -1,549 +0,0 @@
-/*
- * Copyright (C) 2004 Patrick Boettcher <patrick.boettcher@desy.de>,
- *                    Luca Bertagnolio <>,
- *
- * based on information provided by John Jurrius from BBTI, Inc.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation, version 2.
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/usb.h>
-#include <linux/moduleparam.h>
-#include <linux/pci.h>
-#include <linux/version.h>
-
-#include "dmxdev.h"
-#include "dvb_demux.h"
-#include "dvb_filter.h"
-#include "dvb_net.h"
-#include "dvb_frontend.h"
-
-/* debug */
-#define dprintk(level,args...) \
-           do { if ((debug & level)) { printk(args); } } while (0)
-#define debug_dump(b,l) if (debug) {\
-       int i; deb_xfer("%s: %d > ",__FUNCTION__,l); \
-       for (i = 0; i < l; i++) deb_xfer("%02x ", b[i]); \
-       deb_xfer("\n");\
-}
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,ts=2,ctrl=4 (or-able)).");
-
-#define deb_info(args...) dprintk(0x01,args)
-#define deb_ts(args...)   dprintk(0x02,args)
-#define deb_ctrl(args...) dprintk(0x04,args)
-
-/* Version information */
-#define DRIVER_VERSION "0.0"
-#define DRIVER_DESC "Driver for B2C2/Technisat Air/Cable/Sky-2-PC USB devices"
-#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
-
-/* transfer parameters */
-#define B2C2_USB_FRAMES_PER_ISO                4
-#define B2C2_USB_NUM_ISO_URB           4    /* TODO check out a good value */
-
-#define B2C2_USB_CTRL_PIPE_IN          usb_rcvctrlpipe(b2c2->udev,0)
-#define B2C2_USB_CTRL_PIPE_OUT         usb_sndctrlpipe(b2c2->udev,0)
-#define B2C2_USB_DATA_PIPE                     usb_rcvisocpipe(b2c2->udev,0x81)
-
-struct usb_b2c2_usb {
-       struct usb_device *udev;
-       struct usb_interface *uintf;
-
-       u8 *iso_buffer;
-       int buffer_size;
-       dma_addr_t iso_dma_handle;
-       struct urb *iso_urb[B2C2_USB_NUM_ISO_URB];
-};
-
-
-/*
- * USB
- * 10 90 34 12 78 56 04 00
- * usb_control_msg(udev, usb_sndctrlpipe(udev,0),
- * 0x90,
- * 0x10,
- * 0x1234,
- * 0x5678,
- * buf,
- * 4,
- * 5*HZ);
- *
- * extern int usb_control_msg(struct usb_device *dev, unsigned int pipe,
- * __u8 request,
- * __u8 requesttype,
- * __u16 value,
- * __u16 index,
- * void *data,
- * __u16 size,
- * int timeout);
- *
- */
-
-/* request types */
-typedef enum {
-
-/* something is wrong with this part
-       RTYPE_READ_DW         = (1 << 6),
-       RTYPE_WRITE_DW_1      = (3 << 6),
-       RTYPE_READ_V8_MEMORY  = (6 << 6),
-       RTYPE_WRITE_V8_MEMORY = (7 << 6),
-       RTYPE_WRITE_V8_FLASH  = (8 << 6),
-       RTYPE_GENERIC         = (9 << 6),
-*/
-       RTYPE_READ_DW = (3 << 6),
-       RTYPE_WRITE_DW_1 = (1 << 6),
-       
-       RTYPE_READ_V8_MEMORY  = (6 << 6),
-       RTYPE_WRITE_V8_MEMORY = (7 << 6),
-       RTYPE_WRITE_V8_FLASH  = (8 << 6),
-       RTYPE_GENERIC         = (9 << 6),
-} b2c2_usb_request_type_t;
-
-/* request */
-typedef enum {
-       B2C2_USB_WRITE_V8_MEM = 0x04,
-       B2C2_USB_READ_V8_MEM  = 0x05,
-       B2C2_USB_READ_REG     = 0x08,
-       B2C2_USB_WRITE_REG    = 0x0A,
-/*     B2C2_USB_WRITEREGLO   = 0x0A, */
-       B2C2_USB_WRITEREGHI   = 0x0B,
-       B2C2_USB_FLASH_BLOCK  = 0x10,
-       B2C2_USB_I2C_REQUEST  = 0x11,
-       B2C2_USB_UTILITY      = 0x12,
-} b2c2_usb_request_t;
-
-/* function definition for I2C_REQUEST */
-typedef enum {
-       USB_FUNC_I2C_WRITE       = 0x01,
-       USB_FUNC_I2C_MULTIWRITE  = 0x02,
-       USB_FUNC_I2C_READ        = 0x03,
-       USB_FUNC_I2C_REPEATWRITE = 0x04,
-       USB_FUNC_GET_DESCRIPTOR  = 0x05,
-       USB_FUNC_I2C_REPEATREAD  = 0x06,
-/* DKT 020208 - add this to support special case of DiSEqC */
-       USB_FUNC_I2C_CHECKWRITE  = 0x07,
-       USB_FUNC_I2C_CHECKRESULT = 0x08,
-} b2c2_usb_i2c_function_t;
-
-/*
- * function definition for UTILITY request 0x12
- * DKT 020304 - new utility function
- */
-typedef enum {
-       UTILITY_SET_FILTER          = 0x01,
-       UTILITY_DATA_ENABLE         = 0x02,
-       UTILITY_FLEX_MULTIWRITE     = 0x03,
-       UTILITY_SET_BUFFER_SIZE     = 0x04,
-       UTILITY_FLEX_OPERATOR       = 0x05,
-       UTILITY_FLEX_RESET300_START = 0x06,
-       UTILITY_FLEX_RESET300_STOP  = 0x07,
-       UTILITY_FLEX_RESET300       = 0x08,
-       UTILITY_SET_ISO_SIZE        = 0x09,
-       UTILITY_DATA_RESET          = 0x0A,
-       UTILITY_GET_DATA_STATUS     = 0x10,
-       UTILITY_GET_V8_REG          = 0x11,
-/* DKT 020326 - add function for v1.14 */
-       UTILITY_SRAM_WRITE          = 0x12,
-       UTILITY_SRAM_READ           = 0x13,
-       UTILITY_SRAM_TESTFILL       = 0x14,
-       UTILITY_SRAM_TESTSET        = 0x15,
-       UTILITY_SRAM_TESTVERIFY     = 0x16,
-} b2c2_usb_utility_function_t;
-
-#define B2C2_WAIT_FOR_OPERATION_RW  1  // 1 s
-#define B2C2_WAIT_FOR_OPERATION_RDW 3  // 3 s
-#define B2C2_WAIT_FOR_OPERATION_WDW 1  // 1 s
-
-#define B2C2_WAIT_FOR_OPERATION_V8READ   3  // 3 s
-#define B2C2_WAIT_FOR_OPERATION_V8WRITE  3  // 3 s
-#define B2C2_WAIT_FOR_OPERATION_V8FLASH  3  // 3 s
-
-/* JLP 111700: we will include the 1 bit gap between the upper and lower 3 bits
- * in the IBI address, to make the V8 code simpler.
- * PCI ADDRESS FORMAT: 0x71C -> 0000 0111 0001 1100 (these are the six bits 
used)
- *                  in general: 0000 0HHH 000L LL00
- * IBI ADDRESS FORMAT:                    RHHH BLLL
- *
- * where R is the read(1)/write(0) bit, B is the busy bit
- * and HHH and LLL are the two sets of three bits from the PCI address.
- */
-#define B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(usPCI) (u8) (((usPCI >> 2) & 0x07) 
+ ((usPCI >> 4) & 0x70))
-#define B2C2_FLEX_INTERNALADDR_TO_PCIOFFSET(ucAddr) (u16) (((ucAddr & 0x07) << 
2) + ((ucAddr & 0x70) << 4))
-
-/*
- * DKT 020228 - forget about this VENDOR_BUFFER_SIZE, read and write register
- * deal with DWORD or 4 bytes, that should be should from now on
- */
-static u32 b2c2_usb_read_dw(struct usb_b2c2_usb *b2c2, u16 wRegOffsPCI)
-{
-       u32 val;
-       u16 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) | 
0x0080;
-       int len = usb_control_msg(b2c2->udev,
-                       B2C2_USB_CTRL_PIPE_IN,
-                       B2C2_USB_READ_REG,
-                       RTYPE_READ_DW,
-                       wAddress,
-                       0,
-                       &val,
-                       sizeof(u32),
-                       B2C2_WAIT_FOR_OPERATION_RDW * 1000);
-
-       if (len != sizeof(u32)) {
-               err("error while reading dword from %d 
(%d).",wAddress,wRegOffsPCI);
-               return -EIO;
-       } else
-               return val;
-}
-
-/*
- * DKT 020228 - from now on, we don't support anything older than firm 1.00
- * I eliminated the write register as a 2 trip of writing hi word and lo word
- * and force this to write only 4 bytes at a time.
- * NOTE: this should work with all the firmware from 1.00 and newer
- */
-static int b2c2_usb_write_dw(struct usb_b2c2_usb *b2c2, u16 wRegOffsPCI, u32 
val)
-{
-       u16 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI);
-       int len = usb_control_msg(b2c2->udev,
-                       B2C2_USB_CTRL_PIPE_OUT,
-                       B2C2_USB_WRITE_REG,
-                       RTYPE_WRITE_DW_1,
-                       wAddress,
-                       0,
-                       &val,
-                       sizeof(u32),
-                       B2C2_WAIT_FOR_OPERATION_RDW * 1000);
-
-       if (len != sizeof(u32)) {
-               err("error while reading dword from %d 
(%d).",wAddress,wRegOffsPCI);
-               return -EIO;
-       } else
-               return 0;
-}
-
-/*
- * DKT 010817 - add support for V8 memory read/write and flash update
- */
-static int b2c2_usb_v8_memory_req(struct usb_b2c2_usb *b2c2,
-               b2c2_usb_request_t req, u8 page, u16 wAddress,
-               u16 buflen, u8 *pbBuffer)
-{
-       u8 dwRequestType;
-       u16 wIndex;
-       int nWaitTime,pipe,len;
-
-       wIndex = page << 8;
-
-       switch (req) {
-               case B2C2_USB_READ_V8_MEM:
-                       nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
-                       dwRequestType = (u8) RTYPE_READ_V8_MEMORY;
-                       pipe = B2C2_USB_CTRL_PIPE_IN;
-               break;
-               case B2C2_USB_WRITE_V8_MEM:
-                       wIndex |= pbBuffer[0];
-                       nWaitTime = B2C2_WAIT_FOR_OPERATION_V8WRITE;
-                       dwRequestType = (u8) RTYPE_WRITE_V8_MEMORY;
-                       pipe = B2C2_USB_CTRL_PIPE_OUT;
-               break;
-               case B2C2_USB_FLASH_BLOCK:
-                       nWaitTime = B2C2_WAIT_FOR_OPERATION_V8FLASH;
-                       dwRequestType = (u8) RTYPE_WRITE_V8_FLASH;
-                       pipe = B2C2_USB_CTRL_PIPE_OUT;
-               break;
-               default:
-                       deb_info("unsupported request for v8_mem_req 
%x.\n",req);
-               return -EINVAL;
-       }
-       len = usb_control_msg(b2c2->udev,pipe,
-                       req,
-                       dwRequestType,
-                       wAddress,
-                       wIndex,
-                       pbBuffer,
-                       buflen,
-                       nWaitTime * 1000);
-       return len == buflen ? 0 : -EIO;
-}
-
-static int b2c2_usb_i2c_req(struct usb_b2c2_usb *b2c2,
-               b2c2_usb_request_t req, b2c2_usb_i2c_function_t func,
-               u8 port, u8 chipaddr, u8 addr, u8 buflen, u8 *buf)
-{
-       u16 wValue, wIndex;
-       int nWaitTime,pipe,len;
-       u8 dwRequestType;
-
-       switch (func) {
-               case USB_FUNC_I2C_WRITE:
-               case USB_FUNC_I2C_MULTIWRITE:
-               case USB_FUNC_I2C_REPEATWRITE:
-               /* DKT 020208 - add this to support special case of DiSEqC */
-               case USB_FUNC_I2C_CHECKWRITE:
-                       pipe = B2C2_USB_CTRL_PIPE_OUT;
-                       nWaitTime = 2;
-                       dwRequestType = (u8) RTYPE_GENERIC;
-               break;
-               case USB_FUNC_I2C_READ:
-               case USB_FUNC_I2C_REPEATREAD:
-                       pipe = B2C2_USB_CTRL_PIPE_IN;
-                       nWaitTime = 2;
-                       dwRequestType = (u8) RTYPE_GENERIC;
-               break;
-               default:
-                       deb_info("unsupported function for i2c_req %x\n",func);
-                       return -EINVAL;
-       }
-       wValue = (func << 8 ) | port;
-       wIndex = (chipaddr << 8 ) | addr;
-
-       len = usb_control_msg(b2c2->udev,pipe,
-                       req,
-                       dwRequestType,
-                       addr,
-                       wIndex,
-                       buf,
-                       buflen,
-                       nWaitTime * 1000);
-       return len == buflen ? 0 : -EIO;
-}
-
-int static b2c2_usb_utility_req(struct usb_b2c2_usb *b2c2, int set,
-               b2c2_usb_utility_function_t func, u8 extra, u16 wIndex,
-               u16 buflen, u8 *pvBuffer)
-{
-       u16 wValue;
-       int nWaitTime = 2,
-               pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN,
-               len;
-
-       wValue = (func << 8) | extra;
-
-       len = usb_control_msg(b2c2->udev,pipe,
-                       B2C2_USB_UTILITY,
-                       (u8) RTYPE_GENERIC,
-                       wValue,
-                       wIndex,
-                       pvBuffer,
-                       buflen,
-                       nWaitTime * 1000);
-       return len == buflen ? 0 : -EIO;
-}
-
-
-
-static void b2c2_dumpfourreg(struct usb_b2c2_usb *b2c2, u16 offs)
-{
-       u32 r0,r1,r2,r3;
-       r0 = r1 = r2 = r3 = 0;
-       r0 = b2c2_usb_read_dw(b2c2,offs);
-       r1 = b2c2_usb_read_dw(b2c2,offs + 0x04);
-       r2 = b2c2_usb_read_dw(b2c2,offs + 0x08);
-       r3 = b2c2_usb_read_dw(b2c2,offs + 0x0c);
-       deb_ctrl("dump: offset: %03x, %08x, %08x, %08x, 
%08x\n",offs,r0,r1,r2,r3);
-}
-
-static void b2c2_urb_complete(struct urb *urb, struct pt_regs *ptregs)
-{
-       struct usb_b2c2_usb *b2c2 = urb->context;
-       deb_ts("urb completed, bufsize: %d\n",urb->transfer_buffer_length);
-
-//     urb_submit_urb(urb,GFP_ATOMIC); enable for real action
-}
-
-static void b2c2_exit_usb(struct usb_b2c2_usb *b2c2)
-{
-       int i;
-       for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++)
-               if (b2c2->iso_urb[i] != NULL) { /* not sure about unlink_urb 
and iso-urbs TODO */
-                       deb_info("unlinking/killing urb no. %d\n",i);
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,7)
-                       usb_unlink_urb(b2c2->iso_urb[i]);
-#else
-                       usb_kill_urb(b2c2->iso_urb[i]);
-#endif
-                       usb_free_urb(b2c2->iso_urb[i]);
-               }
-
-       if (b2c2->iso_buffer != NULL)
-               pci_free_consistent(NULL,b2c2->buffer_size, b2c2->iso_buffer, 
b2c2->iso_dma_handle);
-
-}
-
-static int b2c2_init_usb(struct usb_b2c2_usb *b2c2)
-{
-       u16 frame_size = 
le16_to_cpu(b2c2->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize);
-       int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * 
frame_size,i,j,ret;
-       int buffer_offset = 0;
-
-       deb_info("creating %d iso-urbs with %d frames each of %d bytes size = 
%d.\n",
-                       B2C2_USB_NUM_ISO_URB, B2C2_USB_FRAMES_PER_ISO, 
frame_size,bufsize);
-
-       b2c2->iso_buffer = 
pci_alloc_consistent(NULL,bufsize,&b2c2->iso_dma_handle);
-       if (b2c2->iso_buffer == NULL)
-               return -ENOMEM;
-       memset(b2c2->iso_buffer, 0, bufsize);
-       b2c2->buffer_size = bufsize;
-
-       /* creating iso urbs */
-       for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++)
-               if (!(b2c2->iso_urb[i] = 
usb_alloc_urb(B2C2_USB_FRAMES_PER_ISO,GFP_ATOMIC))) {
-                       ret = -ENOMEM;
-                       goto urb_error;
-               }
-       /* initialising and submitting iso urbs */
-       for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) {
-               int frame_offset = 0;
-               struct urb *urb = b2c2->iso_urb[i];
-               deb_info("initializing and submitting urb no. %d (buf_offset: 
%d).\n",i,buffer_offset);
-
-               urb->dev = b2c2->udev;
-               urb->context = b2c2;
-               urb->complete = b2c2_urb_complete;
-               urb->pipe = B2C2_USB_DATA_PIPE;
-               urb->transfer_flags = URB_ISO_ASAP;
-               urb->interval = 1;
-               urb->number_of_packets = B2C2_USB_FRAMES_PER_ISO;
-               urb->transfer_buffer_length = frame_size * 
B2C2_USB_FRAMES_PER_ISO;
-               urb->transfer_buffer = b2c2->iso_buffer + buffer_offset;
-
-               buffer_offset += frame_size * B2C2_USB_FRAMES_PER_ISO;
-               for (j = 0; j < B2C2_USB_FRAMES_PER_ISO; j++) {
-                       deb_info("urb no: %d, frame: %d, frame_offset: 
%d\n",i,j,frame_offset);
-                       urb->iso_frame_desc[j].offset = frame_offset;
-                       urb->iso_frame_desc[j].length = frame_size;
-                       frame_offset += frame_size;
-               }
-
-               if ((ret = usb_submit_urb(b2c2->iso_urb[i],GFP_ATOMIC))) {
-                       err("submitting urb %d failed with %d.",i,ret);
-                       goto urb_error;
-               }
-               deb_info("submitted urb no. %d.\n",i);
-       }
-
-       ret = 0;
-       goto success;
-urb_error:
-       b2c2_exit_usb(b2c2);
-success:
-       return ret;
-}
-
-static int b2c2_usb_probe(struct usb_interface *intf,
-               const struct usb_device_id *id)
-{
-       struct usb_device *udev = interface_to_usbdev(intf);
-       struct usb_b2c2_usb *b2c2 = NULL;
-       int ret;
-
-       b2c2 = kmalloc(sizeof(struct usb_b2c2_usb),GFP_KERNEL);
-       if (b2c2 == NULL) {
-               err("no memory");
-               return -ENOMEM;
-       }
-       b2c2->udev = udev;
-       b2c2->uintf = intf;
-
-       /* use the alternate setting with the larges buffer */
-       usb_set_interface(udev,0,1);
-
-       if ((ret = b2c2_init_usb(b2c2)))
-               goto usb_init_error;
-
-       usb_set_intfdata(intf,b2c2);
-
-       switch (udev->speed) {
-               case USB_SPEED_LOW:
-                       err("cannot handle USB speed because it is to sLOW.");
-                       break;
-               case USB_SPEED_FULL:
-                       info("running at FULL speed.");
-                       break;
-               case USB_SPEED_HIGH:
-                       info("running at HIGH speed.");
-                       break;
-               case USB_SPEED_UNKNOWN: /* fall through */
-               default:
-                       err("cannot handle USB speed because it is unkown.");
-               break;
-       }
-
-       b2c2_dumpfourreg(b2c2,0x200);
-       b2c2_dumpfourreg(b2c2,0x300);
-       b2c2_dumpfourreg(b2c2,0x400);
-       b2c2_dumpfourreg(b2c2,0x700);
-
-
-       if (ret == 0)
-               info("%s successfully initialized and connected.",DRIVER_DESC);
-       else
-               info("%s error while loading driver (%d)",DRIVER_DESC,ret);
-
-       ret = 0;
-       goto success;
-
-usb_init_error:
-       kfree(b2c2);
-success:
-       return ret;
-}
-
-static void b2c2_usb_disconnect(struct usb_interface *intf)
-{
-       struct usb_b2c2_usb *b2c2 = usb_get_intfdata(intf);
-       usb_set_intfdata(intf,NULL);
-       if (b2c2 != NULL) {
-               b2c2_exit_usb(b2c2);
-               kfree(b2c2);
-       }
-       info("%s successfully deinitialized and disconnected.",DRIVER_DESC);
-
-}
-
-static struct usb_device_id b2c2_usb_table [] = {
-           { USB_DEVICE(0x0af7, 0x0101) }
-};
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver b2c2_usb_driver = {
-       .owner          = THIS_MODULE,
-       .name           = "dvb_b2c2_usb",
-       .probe          = b2c2_usb_probe,
-       .disconnect = b2c2_usb_disconnect,
-       .id_table       = b2c2_usb_table,
-};
-
-/* module stuff */
-static int __init b2c2_usb_init(void)
-{
-       int result;
-       if ((result = usb_register(&b2c2_usb_driver))) {
-               err("usb_register failed. Error number %d",result);
-               return result;
-       }
-
-       return 0;
-}
-
-static void __exit b2c2_usb_exit(void)
-{
-       /* deregister this driver from the USB subsystem */
-       usb_deregister(&b2c2_usb_driver);
-}
-
-module_init (b2c2_usb_init);
-module_exit (b2c2_usb_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(usb, b2c2_usb_table);
diff -urN linux/drivers/media/dvb/bt8xx/dst_ca.c 
linux/drivers/media/dvb/bt8xx/dst_ca.c
--- linux/drivers/media/dvb/bt8xx/dst_ca.c      1970/01/01 00:00:00
+++ linux/drivers/media/dvb/bt8xx/dst_ca.c      2005-05-26 10:12:42.629811000 
+0100     1.1
@@ -0,0 +1,861 @@
+/*
+       CA-driver for TwinHan DST Frontend/Card
+
+       Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <linux/dvb/ca.h>
+#include "dvbdev.h"
+#include "dvb_frontend.h"
+
+#include "dst_ca.h"
+#include "dst_common.h"
+
+static unsigned int verbose = 1;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
+
+static unsigned int debug = 1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "debug messages, default is 1 (yes)");
+
+#define dprintk if (debug) printk
+
+/*     Need some more work     */
+static int ca_set_slot_descr(void)
+{
+       /*      We could make this more graceful ?      */
+       return -EOPNOTSUPP;
+}
+
+/*     Need some more work     */
+static int ca_set_pid(void)
+{
+       /*      We could make this more graceful ?      */
+       return -EOPNOTSUPP;
+}
+
+
+static int put_checksum(u8 *check_string, int length)
+{
+       u8 i = 0, checksum = 0;
+
+       if (verbose > 3) {
+               dprintk("%s: ========================= Checksum calculation 
===========================\n", __FUNCTION__);
+               dprintk("%s: String Length=[0x%02x]\n", __FUNCTION__, length);
+
+               dprintk("%s: String=[", __FUNCTION__);
+       }
+       while (i < length) {
+               if (verbose > 3)
+                       dprintk(" %02x", check_string[i]);
+               checksum += check_string[i];
+               i++;
+       }
+       if (verbose > 3) {
+               dprintk(" ]\n");
+               dprintk("%s: Sum=[%02x]\n", __FUNCTION__, checksum);
+       }
+       check_string[length] = ~checksum + 1;
+       if (verbose > 3) {
+               dprintk("%s: Checksum=[%02x]\n", __FUNCTION__, 
check_string[length]);
+               dprintk("%s: 
==========================================================================\n", 
__FUNCTION__);
+       }
+
+       return 0;
+}
+
+static int dst_ci_command(struct dst_state* state, u8 * data, u8 *ca_string, 
u8 len, int read)
+{
+       u8 reply;
+
+       dst_comm_init(state);
+       msleep(65);
+
+       if (write_dst(state, data, len)) {
+               dprintk("%s: Write not successful, trying to recover\n", 
__FUNCTION__);
+               dst_error_recovery(state);
+               return -1;
+       }
+
+       if ((dst_pio_disable(state)) < 0) {
+               dprintk("%s: DST PIO disable failed.\n", __FUNCTION__);
+               return -1;
+       }
+
+       if (read_dst(state, &reply, GET_ACK) < 0) {
+               dprintk("%s: Read not successful, trying to recover\n", 
__FUNCTION__);
+               dst_error_recovery(state);
+               return -1;
+       }
+
+       if (read) {
+               if (! dst_wait_dst_ready(state, LONG_DELAY)) {
+                       dprintk("%s: 8820 not ready\n", __FUNCTION__);
+                       return -1;
+               }
+
+               if (read_dst(state, ca_string, 128) < 0) {      /*      Try to 
make this dynamic        */
+                       dprintk("%s: Read not successful, trying to recover\n", 
__FUNCTION__);
+                       dst_error_recovery(state);
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+
+static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 
*ca_string, int read)
+{
+       u8 dst_ca_comm_err = 0;
+
+       while (dst_ca_comm_err < RETRIES) {
+               dst_comm_init(state);
+               if (verbose > 2)
+                       dprintk("%s: Put Command\n", __FUNCTION__);
+               if (dst_ci_command(state, data, ca_string, len, read)) {        
// If error
+                       dst_error_recovery(state);
+                       dst_ca_comm_err++; // work required here.
+               }
+               break;
+       }
+
+       return 0;
+}
+
+
+
+static int ca_get_app_info(struct dst_state *state)
+{
+       static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff};
+
+       put_checksum(&command[0], command[0]);
+       if ((dst_put_ci(state, command, sizeof(command), state->messages, 
GET_REPLY)) < 0) {
+               dprintk("%s: -->dst_put_ci FAILED !\n", __FUNCTION__);
+               return -1;
+       }
+       if (verbose > 1) {
+               dprintk("%s: -->dst_put_ci SUCCESS !\n", __FUNCTION__);
+
+               dprintk("%s: ================================ CI Module 
Application Info ======================================\n", __FUNCTION__);
+               dprintk("%s: Application Type=[%d], Application Vendor=[%d], 
Vendor Code=[%d]\n%s: Application info=[%s]\n",
+                       __FUNCTION__, state->messages[7], (state->messages[8] 
<< 8) | state->messages[9],
+                       (state->messages[10] << 8) | state->messages[11], 
__FUNCTION__, (char *)(&state->messages[12]));
+               dprintk("%s: 
==================================================================================================\n",
 __FUNCTION__);
+       }
+
+       return 0;
+}
+
+static int ca_get_slot_caps(struct dst_state *state, struct ca_caps 
*p_ca_caps, void *arg)
+{
+       int i;
+       u8 slot_cap[256];
+       static u8 slot_command[8] = {0x07, 0x40, 0x02, 0x00, 0x02, 0x00, 0x00, 
0xff};
+
+       put_checksum(&slot_command[0], slot_command[0]);
+       if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_cap, 
GET_REPLY)) < 0) {
+               dprintk("%s: -->dst_put_ci FAILED !\n", __FUNCTION__);
+               return -1;
+       }
+       if (verbose > 1)
+               dprintk("%s: -->dst_put_ci SUCCESS !\n", __FUNCTION__);
+
+       /*      Will implement the rest soon            */
+
+       if (verbose > 1) {
+               dprintk("%s: Slot cap = [%d]\n", __FUNCTION__, slot_cap[7]);
+               dprintk("===================================\n");
+               for (i = 0; i < 8; i++)
+                       dprintk(" %d", slot_cap[i]);
+               dprintk("\n");
+       }
+
+       p_ca_caps->slot_num = 1;
+       p_ca_caps->slot_type = 1;
+       p_ca_caps->descr_num = slot_cap[7];
+       p_ca_caps->descr_type = 1;
+
+
+       if (copy_to_user((struct ca_caps *)arg, p_ca_caps, sizeof (struct 
ca_caps))) {
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+/*     Need some more work     */
+static int ca_get_slot_descr(struct dst_state *state, struct ca_msg 
*p_ca_message, void *arg)
+{
+       return -EOPNOTSUPP;
+}
+
+
+static int ca_get_slot_info(struct dst_state *state, struct ca_slot_info 
*p_ca_slot_info, void *arg)
+{
+       int i;
+       static u8 slot_command[8] = {0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 
0xff};
+
+       u8 *slot_info = state->rxbuffer;
+
+       put_checksum(&slot_command[0], 7);
+       if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_info, 
GET_REPLY)) < 0) {
+               dprintk("%s: -->dst_put_ci FAILED !\n", __FUNCTION__);
+               return -1;
+       }
+       if (verbose > 1)
+               dprintk("%s: -->dst_put_ci SUCCESS !\n", __FUNCTION__);
+
+       /*      Will implement the rest soon            */
+
+       if (verbose > 1) {
+               dprintk("%s: Slot info = [%d]\n", __FUNCTION__, slot_info[3]);
+               dprintk("===================================\n");
+               for (i = 0; i < 8; i++)
+                       dprintk(" %d", slot_info[i]);
+               dprintk("\n");
+       }
+
+       if (slot_info[4] & 0x80) {
+               p_ca_slot_info->flags = CA_CI_MODULE_PRESENT;
+               p_ca_slot_info->num = 1;
+               p_ca_slot_info->type = CA_CI;
+       }
+       else if (slot_info[4] & 0x40) {
+               p_ca_slot_info->flags = CA_CI_MODULE_READY;
+               p_ca_slot_info->num = 1;
+               p_ca_slot_info->type = CA_CI;
+       }
+       else {
+               p_ca_slot_info->flags = 0;
+       }
+
+       if (copy_to_user((struct ca_slot_info *)arg, p_ca_slot_info, sizeof 
(struct ca_slot_info))) {
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+
+
+
+static int ca_get_message(struct dst_state *state, struct ca_msg 
*p_ca_message, void *arg)
+{
+       u8 i = 0;
+       u32 command = 0;
+
+       if (copy_from_user(p_ca_message, (void *)arg, sizeof (struct ca_msg)))
+               return -EFAULT;
+
+
+       if (p_ca_message->msg) {
+               if (verbose > 3)
+                       dprintk("Message = [%02x %02x %02x]\n", 
p_ca_message->msg[0], p_ca_message->msg[1], p_ca_message->msg[2]);
+
+               for (i = 0; i < 3; i++) {
+                       command = command | p_ca_message->msg[i];
+                       if (i < 2)
+                               command = command << 8;
+               }
+               if (verbose > 3)
+                       dprintk("%s:Command=[0x%x]\n", __FUNCTION__, command);
+
+               switch (command) {
+                       case CA_APP_INFO:
+                               memcpy(p_ca_message->msg, state->messages, 128);
+                               if (copy_to_user((void *)arg, p_ca_message, 
sizeof (struct ca_msg)) )
+                                       return -EFAULT;
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static int handle_en50221_tag(struct dst_state *state, struct ca_msg 
*p_ca_message, struct ca_msg *hw_buffer)
+{
+       if (state->dst_hw_cap & DST_TYPE_HAS_SESSION) {
+               hw_buffer->msg[2] = p_ca_message->msg[1];               /*      
        MSB                     */
+               hw_buffer->msg[3] = p_ca_message->msg[2];               /*      
        LSB                     */
+       }
+       else {
+               hw_buffer->msg[2] = 0x03;
+               hw_buffer->msg[3] = 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)
+{
+       if ((dst_put_ci(state, hw_buffer->msg, (hw_buffer->length + 1), 
hw_buffer->msg, reply)) < 0) {
+               dprintk("%s: DST-CI Command failed.\n", __FUNCTION__);
+               dprintk("%s: Resetting DST.\n", __FUNCTION__);
+               rdc_reset_state(state);
+               return -1;
+       }
+       if (verbose > 2)
+               dprintk("%s: DST-CI Command succes.\n", __FUNCTION__);
+
+       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 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];
+               }
+       }
+       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");
+
+       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);
+
+       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!            */
+
+               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__);
+               }
+
+               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++;
+               }
+
+               /*                      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;
+                       }
+
+                       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;
+       }
+       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];
+               }
+
+               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];
+
+               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]);
+
+                       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);
+               }
+
+               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;
+
+               /*              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;
+               }
+
+               /*              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;
+                               }
+
+                               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");
+               }
+       }
+
+       /*              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);
+
+       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)
+{
+       int ca_pmt_reply_test = 0;
+
+       /*      Do test board                   */
+       /*      Not there yet but soon          */
+
+
+       /*      CA PMT Reply capable            */
+       if (ca_pmt_reply_test) {
+               if ((ca_set_pmt(state, p_ca_message, hw_buffer, 1, GET_REPLY)) 
< 0) {
+                       dprintk("%s: ca_set_pmt.. failed !\n", __FUNCTION__);
+                       return -1;
+               }
+
+       /*      Process CA PMT Reply            */
+       /*      will implement soon             */
+               dprintk("%s: Not there yet\n", __FUNCTION__);
+       }
+       /*      CA PMT Reply not capable        */
+       if (!ca_pmt_reply_test) {
+               if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, NO_REPLY)) < 
0) {
+                       dprintk("%s: ca_set_pmt.. failed !\n", __FUNCTION__);
+                       return -1;
+               }
+               if (verbose > 3)
+                       dprintk("%s: ca_set_pmt.. success !\n", __FUNCTION__);
+       /*      put a dummy message             */
+
+       }
+       return 0;
+}
+
+static int ca_send_message(struct dst_state *state, struct ca_msg 
*p_ca_message, void *arg)
+{
+       int i = 0;
+       unsigned int ca_message_header_len;
+
+       u32 command = 0;
+       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__);
+               return -ENOMEM;
+       }
+       if (verbose > 3)
+               dprintk("%s\n", __FUNCTION__);
+
+       if (copy_from_user(p_ca_message, (void *)arg, sizeof (struct ca_msg)))
+               return -EFAULT;
+
+       if (p_ca_message->msg) {
+               ca_message_header_len = p_ca_message->length;   /*      Restore 
it back when you are done       */
+               /*      EN50221 tag     */
+               command = 0;
+
+               for (i = 0; i < 3; i++) {
+                       command = command | p_ca_message->msg[i];
+                       if (i < 2)
+                               command = command << 8;
+               }
+               if (verbose > 3)
+                       dprintk("%s:Command=[0x%x]\n", __FUNCTION__, command);
+
+               switch (command) {
+                       case CA_PMT:
+                               if (verbose > 3)
+                                       dprintk("Command = SEND_CA_PMT\n");
+                               if ((ca_set_pmt(state, p_ca_message, hw_buffer, 
0, 0)) < 0) {
+                                       dprintk("%s: -->CA_PMT Failed !\n", 
__FUNCTION__);
+                                       return -1;
+                               }
+                               if (verbose > 3)
+                                       dprintk("%s: -->CA_PMT Success !\n", 
__FUNCTION__);
+//                             retval = dummy_set_pmt(state, p_ca_message, 
hw_buffer, 0, 0);
+
+                               break;
+
+                       case CA_PMT_REPLY:
+                               if (verbose > 3)
+                                       dprintk("Command = CA_PMT_REPLY\n");
+                               /*      Have to handle the 2 basic types of 
cards here  */
+                               if ((dst_check_ca_pmt(state, p_ca_message, 
hw_buffer)) < 0) {
+                                       dprintk("%s: -->CA_PMT_REPLY Failed 
!\n", __FUNCTION__);
+                                       return -1;
+                               }
+                               if (verbose > 3)
+                                       dprintk("%s: -->CA_PMT_REPLY Success 
!\n", __FUNCTION__);
+
+                               /*      Certain boards do behave different ?    
        */
+//                             retval = ca_set_pmt(state, p_ca_message, 
hw_buffer, 1, 1);
+
+                       case CA_APP_INFO_ENQUIRY:               // only for 
debugging
+                               if (verbose > 3)
+                                       dprintk("%s: Getting Cam Application 
information\n", __FUNCTION__);
+
+                               if ((ca_get_app_info(state)) < 0) {
+                                       dprintk("%s: -->CA_APP_INFO_ENQUIRY 
Failed !\n", __FUNCTION__);
+                                       return -1;
+                               }
+                               if (verbose > 3)
+                                       printk("%s: -->CA_APP_INFO_ENQUIRY 
Success !\n", __FUNCTION__);
+
+                               break;
+               }
+       }
+       return 0;
+}
+
+static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int 
cmd, void *arg)
+{
+       struct dvb_device* dvbdev = (struct dvb_device*) file->private_data;
+       struct dst_state* state = (struct dst_state*) dvbdev->priv;
+       struct ca_slot_info *p_ca_slot_info;
+       struct ca_caps *p_ca_caps;
+       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__);
+               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__);
+               return -ENOMEM;
+       }
+
+       if ((p_ca_caps = (struct ca_caps *) kmalloc(sizeof (struct ca_caps), 
GFP_KERNEL)) == NULL) {
+               printk("%s: Memory allocation failure\n", __FUNCTION__);
+               return -ENOMEM;
+       }
+
+       /*      We have now only the standard ioctl's, the driver is upposed to 
handle internals.       */
+       switch (cmd) {
+               case CA_SEND_MSG:
+                       if (verbose > 1)
+                               dprintk("%s: Sending message\n", __FUNCTION__);
+                       if ((ca_send_message(state, p_ca_message, arg)) < 0) {
+                               dprintk("%s: -->CA_SEND_MSG Failed !\n", 
__FUNCTION__);
+                               return -1;
+                       }
+
+                       break;
+
+               case CA_GET_MSG:
+                       if (verbose > 1)
+                               dprintk("%s: Getting message\n", __FUNCTION__);
+                       if ((ca_get_message(state, p_ca_message, arg)) < 0) {
+                               dprintk("%s: -->CA_GET_MSG Failed !\n", 
__FUNCTION__);
+                               return -1;
+                       }
+                       if (verbose > 1)
+                               dprintk("%s: -->CA_GET_MSG Success !\n", 
__FUNCTION__);
+
+                       break;
+
+               case CA_RESET:
+                       if (verbose > 1)
+                               dprintk("%s: Resetting DST\n", __FUNCTION__);
+                       dst_error_bailout(state);
+                       msleep(4000);
+
+                       break;
+
+               case CA_GET_SLOT_INFO:
+                       if (verbose > 1)
+                               dprintk("%s: Getting Slot info\n", 
__FUNCTION__);
+                       if ((ca_get_slot_info(state, p_ca_slot_info, arg)) < 0) 
{
+                               dprintk("%s: -->CA_GET_SLOT_INFO Failed !\n", 
__FUNCTION__);
+                               return -1;
+                       }
+                       if (verbose > 1)
+                               dprintk("%s: -->CA_GET_SLOT_INFO Success !\n", 
__FUNCTION__);
+
+                       break;
+
+               case CA_GET_CAP:
+                       if (verbose > 1)
+                               dprintk("%s: Getting Slot capabilities\n", 
__FUNCTION__);
+                       if ((ca_get_slot_caps(state, p_ca_caps, arg)) < 0) {
+                               dprintk("%s: -->CA_GET_CAP Failed !\n", 
__FUNCTION__);
+                               return -1;
+                       }
+                       if (verbose > 1)
+                               dprintk("%s: -->CA_GET_CAP Success !\n", 
__FUNCTION__);
+
+                       break;
+
+               case CA_GET_DESCR_INFO:
+                       if (verbose > 1)
+                               dprintk("%s: Getting descrambler 
description\n", __FUNCTION__);
+                       if ((ca_get_slot_descr(state, p_ca_message, arg)) < 0) {
+                               dprintk("%s: -->CA_GET_DESCR_INFO Failed !\n", 
__FUNCTION__);
+                               return -1;
+                       }
+                       if (verbose > 1)
+                               dprintk("%s: -->CA_GET_DESCR_INFO Success !\n", 
__FUNCTION__);
+
+                       break;
+
+               case CA_SET_DESCR:
+                       if (verbose > 1)
+                               dprintk("%s: Setting descrambler\n", 
__FUNCTION__);
+                       if ((ca_set_slot_descr()) < 0) {
+                               dprintk("%s: -->CA_SET_DESCR Failed !\n", 
__FUNCTION__);
+                               return -1;
+                       }
+                       if (verbose > 1)
+                               dprintk("%s: -->CA_SET_DESCR Success !\n", 
__FUNCTION__);
+
+                       break;
+
+               case CA_SET_PID:
+                       if (verbose > 1)
+                               dprintk("%s: Setting PID\n", __FUNCTION__);
+                       if ((ca_set_pid()) < 0) {
+                               dprintk("%s: -->CA_SET_PID Failed !\n", 
__FUNCTION__);
+                               return -1;
+                       }
+                       if (verbose > 1)
+                               dprintk("%s: -->CA_SET_PID Success !\n", 
__FUNCTION__);
+
+               default:
+                       return -EOPNOTSUPP;
+               };
+
+       return 0;
+}
+
+static int dst_ca_open(struct inode *inode, struct file *file)
+{
+       if (verbose > 4)
+               dprintk("%s:Device opened [%p]\n", __FUNCTION__, file);
+       try_module_get(THIS_MODULE);
+
+       return 0;
+}
+
+static int dst_ca_release(struct inode *inode, struct file *file)
+{
+       if (verbose > 4)
+               dprintk("%s:Device closed.\n", __FUNCTION__);
+       module_put(THIS_MODULE);
+
+       return 0;
+}
+
+static int dst_ca_read(struct file *file, char __user * buffer, size_t length, 
loff_t * offset)
+{
+       int bytes_read = 0;
+
+       if (verbose > 4)
+               dprintk("%s:Device read.\n", __FUNCTION__);
+
+       return bytes_read;
+}
+
+static int dst_ca_write(struct file *file, const char __user * buffer, size_t 
length, loff_t * offset)
+{
+       if (verbose > 4)
+               dprintk("%s:Device write.\n", __FUNCTION__);
+
+       return 0;
+}
+
+static struct file_operations dst_ca_fops = {
+       .owner = THIS_MODULE,
+       .ioctl = (void *)dst_ca_ioctl,
+       .open = dst_ca_open,
+       .release = dst_ca_release,
+       .read = dst_ca_read,
+       .write = dst_ca_write
+};
+
+static struct dvb_device dvbdev_ca = {
+       .priv = NULL,
+       .users = 1,
+       .readers = 1,
+       .writers = 1,
+       .fops = &dst_ca_fops
+};
+
+int dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter)
+{
+       struct dvb_device *dvbdev;
+       if (verbose > 4)
+               dprintk("%s:registering DST-CA device\n", __FUNCTION__);
+       dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, 
DVB_DEVICE_CA);
+       return 0;
+}
+
+EXPORT_SYMBOL(dst_ca_attach);
+
+MODULE_DESCRIPTION("DST DVB-S/T/C Combo CA driver");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_LICENSE("GPL");
diff -urN linux/drivers/media/dvb/bt8xx/dst_ca.h 
linux/drivers/media/dvb/bt8xx/dst_ca.h
--- linux/drivers/media/dvb/bt8xx/dst_ca.h      1970/01/01 00:00:00
+++ linux/drivers/media/dvb/bt8xx/dst_ca.h      2005-05-26 10:12:42.648828000 
+0100     1.1
@@ -0,0 +1,58 @@
+/*
+       CA-driver for TwinHan DST Frontend/Card
+
+       Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _DST_CA_H_
+#define _DST_CA_H_
+
+#define RETRIES                        5
+
+
+#define        CA_APP_INFO_ENQUIRY     0x9f8020
+#define        CA_APP_INFO             0x9f8021
+#define        CA_ENTER_MENU           0x9f8022
+#define CA_INFO_ENQUIRY                0x9f8030
+#define        CA_INFO                 0x9f8031
+#define CA_PMT                 0x9f8032
+#define CA_PMT_REPLY           0x9f8033
+
+#define CA_CLOSE_MMI           0x9f8800
+#define CA_DISPLAY_CONTROL     0x9f8801
+#define CA_DISPLAY_REPLY       0x9f8802
+#define CA_TEXT_LAST           0x9f8803
+#define CA_TEXT_MORE           0x9f8804
+#define CA_KEYPAD_CONTROL      0x9f8805
+#define CA_KEYPRESS            0x9f8806
+
+#define CA_ENQUIRY             0x9f8807
+#define CA_ANSWER              0x9f8808
+#define CA_MENU_LAST           0x9f8809
+#define CA_MENU_MORE           0x9f880a
+#define CA_MENU_ANSWER         0x9f880b
+#define CA_LIST_LAST           0x9f880c
+#define CA_LIST_MORE           0x9f880d
+
+
+struct dst_ca_private {
+       struct dst_state *dst;
+       struct dvb_device *dvbdev;
+};
+
+
+#endif
diff -urN linux/drivers/media/dvb/bt8xx/dst_common.h 
linux/drivers/media/dvb/bt8xx/dst_common.h
--- linux/drivers/media/dvb/bt8xx/dst_common.h  1970/01/01 00:00:00
+++ linux/drivers/media/dvb/bt8xx/dst_common.h  2005-05-26 10:12:42.660069000 
+0100     1.1
@@ -0,0 +1,153 @@
+/*
+       Frontend-driver for TwinHan DST Frontend
+
+       Copyright (C) 2003 Jamie Honan
+       Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef DST_COMMON_H
+#define DST_COMMON_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/device.h>
+#include "bt878.h"
+
+#include "dst_ca.h"
+
+
+#define NO_DELAY               0
+#define LONG_DELAY             1
+#define DEVICE_INIT            2
+
+#define DELAY                  1
+
+#define DST_TYPE_IS_SAT                0
+#define DST_TYPE_IS_TERR       1
+#define DST_TYPE_IS_CABLE      2
+#define DST_TYPE_IS_ATSC       3
+
+#define DST_TYPE_HAS_NEWTUNE   1
+#define DST_TYPE_HAS_TS204     2
+#define DST_TYPE_HAS_SYMDIV    4
+#define DST_TYPE_HAS_FW_1      8
+#define DST_TYPE_HAS_FW_2      16
+#define DST_TYPE_HAS_FW_3      32
+#define DST_TYPE_HAS_FW_BUILD  64
+
+/*     Card capability list    */
+
+#define DST_TYPE_HAS_MAC       1
+#define DST_TYPE_HAS_DISEQC3   2
+#define DST_TYPE_HAS_DISEQC4   4
+#define DST_TYPE_HAS_DISEQC5   8
+#define DST_TYPE_HAS_MOTO      16
+#define DST_TYPE_HAS_CA                32
+#define        DST_TYPE_HAS_ANALOG     64      /*      Analog inputs   */
+#define DST_TYPE_HAS_SESSION   128
+
+
+#define RDC_8820_PIO_0_DISABLE 0
+#define RDC_8820_PIO_0_ENABLE  1
+#define RDC_8820_INT           2
+#define RDC_8820_RESET         4
+
+/*     DST Communication       */
+#define GET_REPLY              1
+#define NO_REPLY               0
+
+#define GET_ACK                        1
+#define FIXED_COMM             8
+
+#define ACK                    0xff
+
+struct dst_state {
+
+       struct i2c_adapter* i2c;
+
+       struct bt878* bt;
+
+       struct dvb_frontend_ops ops;
+
+       /* configuration settings */
+       const struct dst_config* config;
+
+       struct dvb_frontend frontend;
+
+       /* private ASIC data */
+       u8 tx_tuna[10];
+       u8 rx_tuna[10];
+       u8 rxbuffer[10];
+       u8 diseq_flags;
+       u8 dst_type;
+       u32 type_flags;
+       u32 frequency;          /* intermediate frequency in kHz for QPSK */
+       fe_spectral_inversion_t inversion;
+       u32 symbol_rate;        /* symbol rate in Symbols per second */
+       fe_code_rate_t fec;
+       fe_sec_voltage_t voltage;
+       fe_sec_tone_mode_t tone;
+       u32 decode_freq;
+       u8 decode_lock;
+       u16 decode_strength;
+       u16 decode_snr;
+       unsigned long cur_jiff;
+       u8 k22;
+       fe_bandwidth_t bandwidth;
+       u32 dst_hw_cap;
+       u8 dst_fw_version;
+       fe_sec_mini_cmd_t minicmd;
+       u8 messages[256];
+};
+
+struct dst_types {
+       char *device_id;
+       int offset;
+       u8 dst_type;
+       u32 type_flags;
+       u32 dst_feature;
+};
+
+
+
+struct dst_config
+{
+       /* the ASIC i2c address */
+       u8 demod_address;
+};
+
+
+int rdc_reset_state(struct dst_state *state);
+int rdc_8820_reset(struct dst_state *state);
+
+int dst_wait_dst_ready(struct dst_state *state, u8 delay_mode);
+int dst_pio_enable(struct dst_state *state);
+int dst_pio_disable(struct dst_state *state);
+int dst_error_recovery(struct dst_state* state);
+int dst_error_bailout(struct dst_state *state);
+int dst_comm_init(struct dst_state* state);
+
+int write_dst(struct dst_state *state, u8 * data, u8 len);
+int read_dst(struct dst_state *state, u8 * ret, u8 len);
+u8 dst_check_sum(u8 * buf, u32 len);
+struct dst_state* dst_attach(struct dst_state* state, struct dvb_adapter 
*dvb_adapter);
+int dst_ca_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter);
+int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh, 
int delay);
+
+int dst_command(struct dst_state* state, u8 * data, u8 len);
+
+
+#endif // DST_COMMON_H
diff -urN linux/drivers/media/dvb/bt8xx/Kconfig 
linux/drivers/media/dvb/bt8xx/Kconfig
--- linux/drivers/media/dvb/bt8xx/Kconfig       2005/04/08 18:58:16     1.5
+++ linux/drivers/media/dvb/bt8xx/Kconfig       2005/05/26 09:12:42     1.6
@@ -11,9 +11,8 @@
          the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards and
          pcHDTV HD2000 cards.
 
-          Since these cards have no MPEG decoder onboard, they transmit
+         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 if you own such a device and want to use it.
-
diff -urN linux/drivers/media/dvb/bt8xx/Makefile 
linux/drivers/media/dvb/bt8xx/Makefile
--- linux/drivers/media/dvb/bt8xx/Makefile      2004/12/27 02:15:54     1.2
+++ linux/drivers/media/dvb/bt8xx/Makefile      2005/05/26 09:12:42     1.3
@@ -1,5 +1,3 @@
-
-obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o
+obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
 
 EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video 
-Idrivers/media/dvb/frontends
-
diff -urN linux/drivers/media/dvb/bt8xx/bt878.c 
linux/drivers/media/dvb/bt8xx/bt878.c
--- linux/drivers/media/dvb/bt8xx/bt878.c       2005/04/08 18:58:16     1.6
+++ linux/drivers/media/dvb/bt8xx/bt878.c       2005/05/26 09:12:42     1.7
@@ -4,27 +4,27 @@
  * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
  *
  * large parts based on the bttv driver
- * Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
- *                        & Marcus Metzler (mocm@thp.uni-koeln.de)
+ * Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@metzlerbros.de)
+ *                        & Marcus Metzler (mocm@metzlerbros.de)
  * (c) 1999,2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
 
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
 
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- * 
+ *
  */
 
 #include <linux/module.h>
@@ -58,7 +58,7 @@
 MODULE_PARM_DESC(verbose,
                 "verbose startup messages, default is 1 (yes)");
 module_param_named(debug, bt878_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+MODULE_PARM_DESC(debug, "Turn on/off debugging, default is 0 (off).");
 
 int bt878_num;
 struct bt878 bt878[BT878_MAX];
@@ -128,21 +128,21 @@
 }
 
 /* RISC instructions */
-#define RISC_WRITE             (0x01 << 28)
-#define RISC_JUMP              (0x07 << 28)
-#define RISC_SYNC              (0x08 << 28)
+#define RISC_WRITE             (0x01 << 28)
+#define RISC_JUMP              (0x07 << 28)
+#define RISC_SYNC              (0x08 << 28)
 
 /* RISC bits */
-#define RISC_WR_SOL            (1 << 27)
-#define RISC_WR_EOL            (1 << 26)
-#define RISC_IRQ               (1 << 24)
+#define RISC_WR_SOL            (1 << 27)
+#define RISC_WR_EOL            (1 << 26)
+#define RISC_IRQ               (1 << 24)
 #define RISC_STATUS(status)    ((((~status) & 0x0F) << 20) | ((status & 0x0F) 
<< 16))
-#define RISC_SYNC_RESYNC       (1 << 15)
-#define RISC_SYNC_FM1          0x06
-#define RISC_SYNC_VRO          0x0C
+#define RISC_SYNC_RESYNC       (1 << 15)
+#define RISC_SYNC_FM1          0x06
+#define RISC_SYNC_VRO          0x0C
 
 #define RISC_FLUSH()           bt->risc_pos = 0
-#define RISC_INSTR(instr)      bt->risc_cpu[bt->risc_pos++] = 
cpu_to_le32(instr)
+#define RISC_INSTR(instr)      bt->risc_cpu[bt->risc_pos++] = 
cpu_to_le32(instr)
 
 static int bt878_make_risc(struct bt878 *bt)
 {
@@ -173,7 +173,7 @@
        RISC_INSTR(RISC_SYNC | RISC_SYNC_FM1 | op_sync_orin);
        RISC_INSTR(0);
 
-       dprintk("bt878: risc len lines %u, bytes per line %u\n", 
+       dprintk("bt878: risc len lines %u, bytes per line %u\n",
                        bt->line_count, bt->line_bytes);
        for (line = 0; line < bt->line_count; line++) {
                // At the beginning of every block we issue an IRQ with 
previous (finished) block number set
@@ -228,14 +228,14 @@
         * Hacked for DST to:
         * SCERR | OCERR | FDSR | FTRGT | FBUS | RISCI
         */
-       int_mask = BT878_ASCERR | BT878_AOCERR | BT878_APABORT | 
-               BT878_ARIPERR | BT878_APPERR | BT878_AFDSR | BT878_AFTRGT | 
+       int_mask = BT878_ASCERR | BT878_AOCERR | BT878_APABORT |
+               BT878_ARIPERR | BT878_APPERR | BT878_AFDSR | BT878_AFTRGT |
                BT878_AFBUS | BT878_ARISCI;
 
 
        /* ignore pesky bits */
        int_mask &= ~irq_err_ignore;
-       
+
        btwrite(int_mask, BT878_AINT_MASK);
        btwrite(controlreg, BT878_AGPIO_DMA_CTL);
 }
@@ -461,9 +461,9 @@
        pci_set_drvdata(dev, bt);
 
 /*        if(init_bt878(btv) < 0) {
-                bt878_remove(dev);
-                return -EIO;
-        }
+               bt878_remove(dev);
+               return -EIO;
+       }
 */
 
        if ((result = bt878_mem_alloc(bt))) {
@@ -536,10 +536,10 @@
 MODULE_DEVICE_TABLE(pci, bt878_pci_tbl);
 
 static struct pci_driver bt878_pci_driver = {
-      .name    = "bt878",
+      .name    = "bt878",
       .id_table = bt878_pci_tbl,
-      .probe   = bt878_probe,
-      .remove  = bt878_remove,
+      .probe   = bt878_probe,
+      .remove  = bt878_remove,
 };
 
 static int bt878_pci_driver_registered = 0;
@@ -558,7 +558,7 @@
               (BT878_VERSION_CODE >> 8) & 0xff,
               BT878_VERSION_CODE & 0xff);
 /*
-        bt878_check_chipset();
+       bt878_check_chipset();
 */
        /* later we register inside of bt878_find_audio_dma()
         * because we may want to ignore certain cards */
diff -urN linux/drivers/media/dvb/bt8xx/bt878.h 
linux/drivers/media/dvb/bt8xx/bt878.h
--- linux/drivers/media/dvb/bt8xx/bt878.h       2005/03/18 17:37:26     1.4
+++ linux/drivers/media/dvb/bt8xx/bt878.h       2005/05/26 09:12:42     1.5
@@ -1,4 +1,4 @@
-/* 
+/*
     bt878.h - Bt878 audio module (register offsets)
 
     Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
@@ -120,14 +120,14 @@
        u32 risc_pos;
 
        struct tasklet_struct tasklet;
-       int shutdown;   
+       int shutdown;
 };
 
 extern struct bt878 bt878[BT878_MAX];
 
 void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin,
                u32 irq_err_ignore);
-void bt878_stop(struct bt878 *bt);          
+void bt878_stop(struct bt878 *bt);
 
 #if defined(__powerpc__)       /* big-endian */
 extern __inline__ void io_st_le32(volatile unsigned __iomem *addr, unsigned 
val)
diff -urN linux/drivers/media/dvb/bt8xx/dst.c 
linux/drivers/media/dvb/bt8xx/dst.c
--- linux/drivers/media/dvb/bt8xx/dst.c 2005/04/08 18:58:16     1.3
+++ linux/drivers/media/dvb/bt8xx/dst.c 2005/05/26 09:12:42     1.4
@@ -1,25 +1,25 @@
 /*
-    Frontend-driver for TwinHan DST Frontend
-
-    Copyright (C) 2003 Jamie Honan
-
-    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.
 
+       Frontend/Card driver for TwinHan DST Frontend
+       Copyright (C) 2003 Jamie Honan
+       Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -31,59 +31,22 @@
 
 #include "dvb_frontend.h"
 #include "dst_priv.h"
-#include "dst.h"
+#include "dst_common.h"
 
-struct dst_state {
 
-       struct i2c_adapter* i2c;
+static unsigned int verbose = 1;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
 
-       struct bt878* bt;
+static unsigned int debug = 1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "debug messages, default is 0 (yes)");
 
-       struct dvb_frontend_ops ops;
-
-       /* configuration settings */
-       const struct dst_config* config;
-
-       struct dvb_frontend frontend;
-
-       /* private demodulator data */
-       u8 tx_tuna[10];
-       u8 rx_tuna[10];
-       u8 rxbuffer[10];
-       u8 diseq_flags;
-       u8 dst_type;
-       u32 type_flags;
-       u32 frequency;          /* intermediate frequency in kHz for QPSK */
-       fe_spectral_inversion_t inversion;
-       u32 symbol_rate;        /* symbol rate in Symbols per second */
-       fe_code_rate_t fec;
-       fe_sec_voltage_t voltage;
-       fe_sec_tone_mode_t tone;
-       u32 decode_freq;
-       u8 decode_lock;
-       u16 decode_strength;
-       u16 decode_snr;
-       unsigned long cur_jiff;
-       u8 k22;
-       fe_bandwidth_t bandwidth;
-};
+static unsigned int dst_addons;
+module_param(dst_addons, int, 0644);
+MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
 
-static unsigned int dst_verbose = 0;
-module_param(dst_verbose, int, 0644);
-MODULE_PARM_DESC(dst_verbose, "verbose startup messages, default is 1 (yes)");
-static unsigned int dst_debug = 0;
-module_param(dst_debug, int, 0644);
-MODULE_PARM_DESC(dst_debug, "debug messages, default is 0 (no)");
-
-#define dprintk        if (dst_debug) printk
-
-#define DST_TYPE_IS_SAT                0
-#define DST_TYPE_IS_TERR       1
-#define DST_TYPE_IS_CABLE      2
-
-#define DST_TYPE_HAS_NEWTUNE   1
-#define DST_TYPE_HAS_TS204     2
-#define DST_TYPE_HAS_SYMDIV    4
+#define dprintk        if (debug) printk
 
 #define HAS_LOCK       1
 #define ATTEMPT_TUNE   2
@@ -97,7 +60,7 @@
        bt878_device_control(state->bt, DST_IG_TS, &bits);
 }
 
-static int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 
outhigh)
+int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh, 
int delay)
 {
        union dst_gpio_packet enb;
        union dst_gpio_packet bits;
@@ -105,26 +68,33 @@
 
        enb.enb.mask = mask;
        enb.enb.enable = enbb;
+       if (verbose > 4)
+               dprintk("%s: mask=[%04x], enbb=[%04x], outhigh=[%04x]\n", 
__FUNCTION__, mask, enbb, outhigh);
+
        if ((err = bt878_device_control(state->bt, DST_IG_ENABLE, &enb)) < 0) {
-               dprintk("%s: dst_gpio_enb error (err == %i, mask == 0x%02x, enb 
== 0x%02x)\n", __FUNCTION__, err, mask, enbb);
+               dprintk("%s: dst_gpio_enb error (err == %i, mask == %02x, enb 
== %02x)\n", __FUNCTION__, err, mask, enbb);
                return -EREMOTEIO;
        }
-
+       udelay(1000);
        /* because complete disabling means no output, no need to do output 
packet */
        if (enbb == 0)
                return 0;
 
+       if (delay)
+               msleep(10);
+
        bits.outp.mask = enbb;
        bits.outp.highvals = outhigh;
 
        if ((err = bt878_device_control(state->bt, DST_IG_WRITE, &bits)) < 0) {
-               dprintk("%s: dst_gpio_outb error (err == %i, enbb == 0x%02x, 
outhigh == 0x%02x)\n", __FUNCTION__, err, enbb, outhigh);
+               dprintk("%s: dst_gpio_outb error (err == %i, enbb == %02x, 
outhigh == %02x)\n", __FUNCTION__, err, enbb, outhigh);
                return -EREMOTEIO;
        }
        return 0;
 }
+EXPORT_SYMBOL(dst_gpio_outb);
 
-static int dst_gpio_inb(struct dst_state *state, u8 * result)
+int dst_gpio_inb(struct dst_state *state, u8 * result)
 {
        union dst_gpio_packet rd_packet;
        int err;
@@ -139,143 +109,225 @@
        *result = (u8) rd_packet.rd.value;
        return 0;
 }
+EXPORT_SYMBOL(dst_gpio_inb);
 
-#define DST_I2C_ENABLE 1
-#define DST_8820       2
-
-static int dst_reset8820(struct dst_state *state)
+int rdc_reset_state(struct dst_state *state)
 {
-       int retval;
-       /* pull 8820 gpio pin low, wait, high, wait, then low */
-       // dprintk ("%s: reset 8820\n", __FUNCTION__);
-       retval = dst_gpio_outb(state, DST_8820, DST_8820, 0);
-       if (retval < 0)
-               return retval;
+       if (verbose > 1)
+               dprintk("%s: Resetting state machine\n", __FUNCTION__);
+
+       if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, 0, NO_DELAY) < 0) {
+               dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+               return -1;
+       }
+
        msleep(10);
-       retval = dst_gpio_outb(state, DST_8820, DST_8820, DST_8820);
-       if (retval < 0)
-               return retval;
-       /* wait for more feedback on what works here *
-          msleep(10);
-          retval = dst_gpio_outb(dst, DST_8820, DST_8820, 0);
-          if (retval < 0)
-          return retval;
-        */
+
+       if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, RDC_8820_INT, 
NO_DELAY) < 0) {
+               dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+               msleep(10);
+               return -1;
+       }
+
        return 0;
 }
+EXPORT_SYMBOL(rdc_reset_state);
 
-static int dst_i2c_enable(struct dst_state *state)
+int rdc_8820_reset(struct dst_state *state)
 {
-       int retval;
-       /* pull I2C enable gpio pin low, wait */
-       // dprintk ("%s: i2c enable\n", __FUNCTION__);
-       retval = dst_gpio_outb(state, ~0, DST_I2C_ENABLE, 0);
-       if (retval < 0)
-               return retval;
-       // dprintk ("%s: i2c enable delay\n", __FUNCTION__);
-       msleep(33);
+       if (verbose > 1)
+               dprintk("%s: Resetting DST\n", __FUNCTION__);
+
+       if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, 0, NO_DELAY) < 
0) {
+               dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+               return -1;
+       }
+       udelay(1000);
+       if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, 
RDC_8820_RESET, DELAY) < 0) {
+               dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+               return -1;
+       }
+
        return 0;
 }
+EXPORT_SYMBOL(rdc_8820_reset);
 
-static int dst_i2c_disable(struct dst_state *state)
+int dst_pio_enable(struct dst_state *state)
 {
-       int retval;
-       /* release I2C enable gpio pin, wait */
-       // dprintk ("%s: i2c disable\n", __FUNCTION__);
-       retval = dst_gpio_outb(state, ~0, 0, 0);
-       if (retval < 0)
-               return retval;
-       // dprintk ("%s: i2c disable delay\n", __FUNCTION__);
-       msleep(33);
+       if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_ENABLE, 0, NO_DELAY) < 0) {
+               dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+               return -1;
+       }
+       udelay(1000);
        return 0;
 }
+EXPORT_SYMBOL(dst_pio_enable);
 
-static int dst_wait_dst_ready(struct dst_state *state)
+int dst_pio_disable(struct dst_state *state)
+{
+       if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_DISABLE, 
RDC_8820_PIO_0_DISABLE, NO_DELAY) < 0) {
+               dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+               return -1;
+       }
+       if (state->type_flags & DST_TYPE_HAS_FW_1)
+               udelay(1000);
+
+       return 0;
+}
+EXPORT_SYMBOL(dst_pio_disable);
+
+int dst_wait_dst_ready(struct dst_state *state, u8 delay_mode)
 {
        u8 reply;
-       int retval;
        int i;
+
        for (i = 0; i < 200; i++) {
-               retval = dst_gpio_inb(state, &reply);
-               if (retval < 0)
-                       return retval;
-               if ((reply & DST_I2C_ENABLE) == 0) {
-                       dprintk("%s: dst wait ready after %d\n", __FUNCTION__, 
i);
+               if (dst_gpio_inb(state, &reply) < 0) {
+                       dprintk("%s: dst_gpio_inb ERROR !\n", __FUNCTION__);
+                       return -1;
+               }
+
+               if ((reply & RDC_8820_PIO_0_ENABLE) == 0) {
+                       if (verbose > 4)
+                               dprintk("%s: dst wait ready after %d\n", 
__FUNCTION__, i);
                        return 1;
                }
                msleep(10);
        }
-       dprintk("%s: dst wait NOT ready after %d\n", __FUNCTION__, i);
+       if (verbose > 1)
+               dprintk("%s: dst wait NOT ready after %d\n", __FUNCTION__, i);
+
+       return 0;
+}
+EXPORT_SYMBOL(dst_wait_dst_ready);
+
+int dst_error_recovery(struct dst_state *state)
+{
+       dprintk("%s: Trying to return from previous errors...\n", __FUNCTION__);
+       dst_pio_disable(state);
+       msleep(10);
+       dst_pio_enable(state);
+       msleep(10);
+
        return 0;
 }
+EXPORT_SYMBOL(dst_error_recovery);
 
-static int write_dst(struct dst_state *state, u8 * data, u8 len)
+int dst_error_bailout(struct dst_state *state)
+{
+       dprintk("%s: Trying to bailout from previous error...\n", __FUNCTION__);
+       rdc_8820_reset(state);
+       dst_pio_disable(state);
+       msleep(10);
+
+       return 0;
+}
+EXPORT_SYMBOL(dst_error_bailout);
+
+
+int dst_comm_init(struct dst_state* state)
+{
+       if (verbose > 1)
+               dprintk ("%s: Initializing DST..\n", __FUNCTION__);
+       if ((dst_pio_enable(state)) < 0) {
+               dprintk("%s: PIO Enable Failed.\n", __FUNCTION__);
+               return -1;
+       }
+       if ((rdc_reset_state(state)) < 0) {
+               dprintk("%s: RDC 8820 State RESET Failed.\n", __FUNCTION__);
+               return -1;
+       }
+       if (state->type_flags & DST_TYPE_HAS_FW_1)
+               msleep(100);
+       else
+               msleep(5);
+
+       return 0;
+}
+EXPORT_SYMBOL(dst_comm_init);
+
+
+int write_dst(struct dst_state *state, u8 *data, u8 len)
 {
        struct i2c_msg msg = {
                .addr = state->config->demod_address,.flags = 0,.buf = 
data,.len = len
        };
+
        int err;
        int cnt;
-
-       if (dst_debug && dst_verbose) {
+       if (debug && (verbose > 4)) {
                u8 i;
-               dprintk("%s writing", __FUNCTION__);
-               for (i = 0; i < len; i++) {
-                       dprintk(" 0x%02x", data[i]);
+               if (verbose > 4) {
+                       dprintk("%s writing", __FUNCTION__);
+                       for (i = 0; i < len; i++)
+                               dprintk(" %02x", data[i]);
+                       dprintk("\n");
                }
-               dprintk("\n");
        }
-       msleep(30);
-       for (cnt = 0; cnt < 4; cnt++) {
+       for (cnt = 0; cnt < 2; cnt++) {
                if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
-                       dprintk("%s: write_dst error (err == %i, len == 0x%02x, 
b0 == 0x%02x)\n", __FUNCTION__, err, len, data[0]);
-                       dst_i2c_disable(state);
-                       msleep(500);
-                       dst_i2c_enable(state);
-                       msleep(500);
+                       dprintk("%s: _write_dst error (err == %i, len == 
0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, data[0]);
+                       dst_error_recovery(state);
                        continue;
                } else
                        break;
        }
-       if (cnt >= 4)
-               return -EREMOTEIO;
+
+       if (cnt >= 2) {
+               if (verbose > 1)
+                       printk("%s: RDC 8820 RESET...\n", __FUNCTION__);
+               dst_error_bailout(state);
+
+               return -1;
+       }
+
        return 0;
 }
+EXPORT_SYMBOL(write_dst);
 
-static int read_dst(struct dst_state *state, u8 * ret, u8 len)
+int read_dst(struct dst_state *state, u8 * ret, u8 len)
 {
        struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 
I2C_M_RD,.buf = ret,.len = len };
        int err;
        int cnt;
 
-       for (cnt = 0; cnt < 4; cnt++) {
+       for (cnt = 0; cnt < 2; cnt++) {
                if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
+
                        dprintk("%s: read_dst error (err == %i, len == 0x%02x, 
b0 == 0x%02x)\n", __FUNCTION__, err, len, ret[0]);
-                       dst_i2c_disable(state);
-                       dst_i2c_enable(state);
+                       dst_error_recovery(state);
+
                        continue;
                } else
                        break;
        }
-       if (cnt >= 4)
-               return -EREMOTEIO;
-       dprintk("%s reply is 0x%x\n", __FUNCTION__, ret[0]);
-       if (dst_debug && dst_verbose) {
+       if (cnt >= 2) {
+               if (verbose > 1)
+                       printk("%s: RDC 8820 RESET...\n", __FUNCTION__);
+               dst_error_bailout(state);
+
+               return -1;
+       }
+       if (debug && (verbose > 4)) {
+               dprintk("%s reply is 0x%x\n", __FUNCTION__, ret[0]);
                for (err = 1; err < len; err++)
                        dprintk(" 0x%x", ret[err]);
                if (err > 1)
                        dprintk("\n");
        }
+
        return 0;
 }
+EXPORT_SYMBOL(read_dst);
 
 static int dst_set_freq(struct dst_state *state, u32 freq)
 {
        u8 *val;
 
        state->frequency = freq;
+       if (debug > 4)
+               dprintk("%s: set Frequency %u\n", __FUNCTION__, freq);
 
-       // dprintk("%s: set frequency %u\n", __FUNCTION__, freq);
        if (state->dst_type == DST_TYPE_IS_SAT) {
                freq = freq / 1000;
                if (freq < 950 || freq > 2150)
@@ -398,7 +450,8 @@
        if (state->dst_type == DST_TYPE_IS_TERR) {
                return 0;
        }
-       // dprintk("%s: set srate %u\n", __FUNCTION__, srate);
+       if (debug > 4)
+               dprintk("%s: set symrate %u\n", __FUNCTION__, srate);
        srate /= 1000;
        val = &state->tx_tuna[0];
 
@@ -407,7 +460,10 @@
                sval <<= 20;
                do_div(sval, 88000);
                symcalc = (u32) sval;
-               // dprintk("%s: set symcalc %u\n", __FUNCTION__, symcalc);
+
+               if (debug > 4)
+                       dprintk("%s: set symcalc %u\n", __FUNCTION__, symcalc);
+
                val[5] = (u8) (symcalc >> 12);
                val[6] = (u8) (symcalc >> 4);
                val[7] = (u8) (symcalc << 4);
@@ -422,7 +478,7 @@
        return 0;
 }
 
-static u8 dst_check_sum(u8 * buf, u32 len)
+u8 dst_check_sum(u8 * buf, u32 len)
 {
        u32 i;
        u8 val = 0;
@@ -433,28 +489,7 @@
        }
        return ((~val) + 1);
 }
-
-struct dst_types {
-       char *mstr;
-       int offs;
-       u8 dst_type;
-       u32 type_flags;
-};
-
-static struct dst_types dst_tlist[] = {
-       {"DST-020", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_SYMDIV},
-       {"DST-030", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_TS204 | 
DST_TYPE_HAS_NEWTUNE},
-       {"DST-03T", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_SYMDIV | 
DST_TYPE_HAS_TS204},
-       {"DST-MOT", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_SYMDIV},
-       {"DST-CI",  1, DST_TYPE_IS_SAT, DST_TYPE_HAS_TS204 | 
DST_TYPE_HAS_NEWTUNE},
-       {"DSTMCI",  1, DST_TYPE_IS_SAT, DST_TYPE_HAS_NEWTUNE},
-       {"DSTFCI",  1, DST_TYPE_IS_SAT, DST_TYPE_HAS_NEWTUNE},
-       {"DCTNEW",  1, DST_TYPE_IS_CABLE, DST_TYPE_HAS_NEWTUNE},
-       {"DCT-CI",  1, DST_TYPE_IS_CABLE, DST_TYPE_HAS_NEWTUNE | 
DST_TYPE_HAS_TS204},
-       {"DTTDIG",  1, DST_TYPE_IS_TERR, 0}
-};
-
-/* DCTNEW and DCT-CI are guesses */
+EXPORT_SYMBOL(dst_check_sum);
 
 static void dst_type_flags_print(u32 type_flags)
 {
@@ -465,93 +500,270 @@
                printk(" 0x%x ts204", DST_TYPE_HAS_TS204);
        if (type_flags & DST_TYPE_HAS_SYMDIV)
                printk(" 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
+       if (type_flags & DST_TYPE_HAS_FW_1)
+               printk(" 0x%x firmware version = 1", DST_TYPE_HAS_FW_1);
+       if (type_flags & DST_TYPE_HAS_FW_2)
+               printk(" 0x%x firmware version = 2", DST_TYPE_HAS_FW_2);
+       if (type_flags & DST_TYPE_HAS_FW_3)
+               printk(" 0x%x firmware version = 3", DST_TYPE_HAS_FW_3);
+//     if ((type_flags & DST_TYPE_HAS_FW_BUILD) && new_fw)
+
        printk("\n");
 }
 
-static int dst_type_print(u8 type)
+
+static int dst_type_print (u8 type)
 {
        char *otype;
        switch (type) {
        case DST_TYPE_IS_SAT:
                otype = "satellite";
                break;
+
        case DST_TYPE_IS_TERR:
                otype = "terrestrial";
                break;
+
        case DST_TYPE_IS_CABLE:
                otype = "cable";
                break;
+
        default:
                printk("%s: invalid dst type %d\n", __FUNCTION__, type);
                return -EINVAL;
        }
        printk("DST type : %s\n", otype);
+
        return 0;
 }
 
-static int dst_check_ci(struct dst_state *state)
+/*
+       Known cards list
+       Satellite
+       -------------------
+                 200103A
+       VP-1020   DST-MOT       LG(old), TS=188
+
+       VP-1020   DST-03T       LG(new), TS=204
+       VP-1022   DST-03T       LG(new), TS=204
+       VP-1025   DST-03T       LG(new), TS=204
+
+       VP-1030   DSTMCI,       LG(new), TS=188
+       VP-1032   DSTMCI,       LG(new), TS=188
+
+       Cable
+       -------------------
+       VP-2030   DCT-CI,       Samsung, TS=204
+       VP-2021   DCT-CI,       Unknown, TS=204
+       VP-2031   DCT-CI,       Philips, TS=188
+       VP-2040   DCT-CI,       Philips, TS=188, with CA daughter board
+       VP-2040   DCT-CI,       Philips, TS=204, without CA daughter board
+
+       Terrestrial
+       -------------------
+       VP-3050  DTTNXT                  TS=188
+       VP-3040  DTT-CI,        Philips, TS=188
+       VP-3040  DTT-CI,        Philips, TS=204
+
+       ATSC
+       -------------------
+       VP-3220  ATSCDI,                 TS=188
+       VP-3250  ATSCAD,                 TS=188
+
+*/
+
+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,
+               .dst_feature = 0
+       },      /*      obsolete        */
+
+       {
+               .device_id = "DST-020",
+               .offset = 0,
+               .dst_type =  DST_TYPE_IS_SAT,
+               .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
+               .dst_feature = 0
+       },      /*      obsolete        */
+
+       {
+               .device_id = "DST-030",
+               .offset =  0,
+               .dst_type = DST_TYPE_IS_SAT,
+               .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | 
DST_TYPE_HAS_FW_1,
+               .dst_feature = 0
+       },      /*      obsolete        */
+
+       {
+               .device_id = "DST-03T",
+               .offset = 0,
+               .dst_type = DST_TYPE_IS_SAT,
+               .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | 
DST_TYPE_HAS_FW_2,
+               .dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | 
DST_TYPE_HAS_DISEQC5
+                                                        | DST_TYPE_HAS_MAC | 
DST_TYPE_HAS_MOTO
+        },
+
+       {
+               .device_id = "DST-MOT",
+               .offset =  0,
+               .dst_type = DST_TYPE_IS_SAT,
+               .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
+               .dst_feature = 0
+       },      /*      obsolete        */
+
+       {
+               .device_id = "DST-CI",
+               .offset = 1,
+               .dst_type = DST_TYPE_IS_SAT,
+               .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | 
DST_TYPE_HAS_FW_1,
+               .dst_feature = DST_TYPE_HAS_CA
+       },      /*      An OEM board    */
+
+       {
+               .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,
+               .dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | 
DST_TYPE_HAS_DISEQC4
+                                                       | DST_TYPE_HAS_MOTO | 
DST_TYPE_HAS_MAC
+       },
+
+       {
+               .device_id = "DSTFCI",
+               .offset = 1,
+               .dst_type = DST_TYPE_IS_SAT,
+               .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
+               .dst_feature = 0
+       },      /* unknown to vendor    */
+
+       {
+               .device_id = "DCT-CI",
+               .offset = 1,
+               .dst_type = DST_TYPE_IS_CABLE,
+               .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | 
DST_TYPE_HAS_FW_1
+                                                       | DST_TYPE_HAS_FW_2 | 
DST_TYPE_HAS_FW_BUILD,
+               .dst_feature = DST_TYPE_HAS_CA
+       },
+
+       {
+               .device_id = "DCTNEW",
+               .offset = 1,
+               .dst_type = DST_TYPE_IS_CABLE,
+               .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_3,
+               .dst_feature = 0
+       },
+
+       {
+               .device_id = "DTT-CI",
+               .offset = 1,
+               .dst_type = DST_TYPE_IS_TERR,
+               .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2 | 
DST_TYPE_HAS_FW_BUILD,
+               .dst_feature = 0
+       },
+
+       {
+               .device_id = "DTTDIG",
+               .offset = 1,
+               .dst_type = DST_TYPE_IS_TERR,
+               .type_flags = DST_TYPE_HAS_FW_2,
+               .dst_feature = 0
+       },
+
+       {
+               .device_id = "DTTNXT",
+               .offset = 1,
+               .dst_type = DST_TYPE_IS_TERR,
+               .type_flags = DST_TYPE_HAS_FW_2,
+               .dst_feature = DST_TYPE_HAS_ANALOG
+       },
+
+       {
+               .device_id = "ATSCDI",
+               .offset = 1,
+               .dst_type = DST_TYPE_IS_ATSC,
+               .type_flags = DST_TYPE_HAS_FW_2,
+               .dst_feature = 0
+       },
+
+       {
+               .device_id = "ATSCAD",
+               .offset = 1,
+               .dst_type = DST_TYPE_IS_ATSC,
+               .type_flags = DST_TYPE_HAS_FW_2,
+               .dst_feature = 0
+       },
+
+       { }
+
+};
+
+
+static int dst_get_device_id(struct dst_state *state)
 {
-       u8 txbuf[8];
-       u8 rxbuf[8];
-       int retval;
+       u8 reply;
+
        int i;
-       struct dst_types *dsp;
-       u8 use_dst_type;
-       u32 use_type_flags;
-
-       memset(txbuf, 0, sizeof(txbuf));
-       txbuf[1] = 6;
-       txbuf[7] = dst_check_sum(txbuf, 7);
-
-       dst_i2c_enable(state);
-       dst_reset8820(state);
-       retval = write_dst(state, txbuf, 8);
-       if (retval < 0) {
-               dst_i2c_disable(state);
-               dprintk("%s: write not successful, maybe no card?\n", 
__FUNCTION__);
-               return retval;
-       }
-       msleep(3);
-       retval = read_dst(state, rxbuf, 1);
-       dst_i2c_disable(state);
-       if (retval < 0) {
-               dprintk("%s: read not successful, maybe no card?\n", 
__FUNCTION__);
-               return retval;
-       }
-       if (rxbuf[0] != 0xff) {
-               dprintk("%s: write reply not 0xff, not ci (%02x)\n", 
__FUNCTION__, rxbuf[0]);
-               return retval;
-       }
-       if (!dst_wait_dst_ready(state))
-               return 0;
-       // dst_i2c_enable(i2c); Dimitri
-       retval = read_dst(state, rxbuf, 8);
-       dst_i2c_disable(state);
-       if (retval < 0) {
-               dprintk("%s: read not successful\n", __FUNCTION__);
-               return retval;
+       struct dst_types *p_dst_type;
+       u8 use_dst_type = 0;
+       u32 use_type_flags = 0;
+
+       static u8 device_type[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 
0xff};
+
+       device_type[7] = dst_check_sum(device_type, 7);
+
+       if (write_dst(state, device_type, FIXED_COMM))
+               return -1;              /*      Write failed            */
+
+       if ((dst_pio_disable(state)) < 0)
+               return -1;
+
+       if (read_dst(state, &reply, GET_ACK))
+               return -1;              /*      Read failure            */
+
+       if (reply != ACK) {
+               dprintk("%s: Write not Acknowledged! [Reply=0x%02x]\n", 
__FUNCTION__, reply);
+               return -1;              /*      Unack'd write           */
        }
-       if (rxbuf[7] != dst_check_sum(rxbuf, 7)) {
-               dprintk("%s: checksum failure\n", __FUNCTION__);
-               return retval;
+
+       if (!dst_wait_dst_ready(state, DEVICE_INIT))
+               return -1;              /*      DST not ready yet       */
+
+       if (read_dst(state, state->rxbuffer, FIXED_COMM))
+               return -1;
+
+       dst_pio_disable(state);
+
+       if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
+               dprintk("%s: Checksum failure! \n", __FUNCTION__);
+               return -1;              /*      Checksum failure        */
        }
-       rxbuf[7] = '\0';
-       for (i = 0, dsp = &dst_tlist[0]; i < sizeof(dst_tlist) / 
sizeof(dst_tlist[0]); i++, dsp++) {
-               if (!strncmp(&rxbuf[dsp->offs], dsp->mstr, strlen(dsp->mstr))) {
-                       use_type_flags = dsp->type_flags;
-                       use_dst_type = dsp->dst_type;
-                       printk("%s: recognize %s\n", __FUNCTION__, dsp->mstr);
+
+       state->rxbuffer[7] = '\0';
+
+       for (i = 0, p_dst_type = dst_tlist; i < ARRAY_SIZE (dst_tlist); i++, 
p_dst_type++) {
+               if (!strncmp (&state->rxbuffer[p_dst_type->offset], 
p_dst_type->device_id, strlen (p_dst_type->device_id))) {
+                       use_type_flags = p_dst_type->type_flags;
+                       use_dst_type = p_dst_type->dst_type;
+
+                       /*      Card capabilities       */
+                       state->dst_hw_cap = p_dst_type->dst_feature;
+                       printk ("%s: Recognise [%s]\n", __FUNCTION__, 
p_dst_type->device_id);
+
                        break;
                }
        }
-       if (i >= sizeof(dst_tlist) / sizeof(dst_tlist[0])) {
-               printk("%s: unable to recognize %s or %s\n", __FUNCTION__, 
&rxbuf[0], &rxbuf[1]);
-               printk("%s please email linux-dvb@linuxtv.org with this type 
in\n", __FUNCTION__);
+
+       if (i >= sizeof (dst_tlist) / sizeof (dst_tlist [0])) {
+               printk("%s: Unable to recognize %s or %s\n", __FUNCTION__, 
&state->rxbuffer[0], &state->rxbuffer[1]);
+               printk("%s: please email linux-dvb@linuxtv.org with this type 
in\n", __FUNCTION__);
                use_dst_type = DST_TYPE_IS_SAT;
                use_type_flags = DST_TYPE_HAS_SYMDIV;
        }
-       dst_type_print(use_dst_type);
 
+       dst_type_print(use_dst_type);
        state->type_flags = use_type_flags;
        state->dst_type = use_dst_type;
        dst_type_flags_print(state->type_flags);
@@ -559,50 +771,102 @@
        if (state->type_flags & DST_TYPE_HAS_TS204) {
                dst_packsize(state, 204);
        }
+
        return 0;
 }
 
-static int dst_command(struct dst_state* state, u8 * data, u8 len)
+static int dst_probe(struct dst_state *state)
+{
+       if ((rdc_8820_reset(state)) < 0) {
+               dprintk("%s: RDC 8820 RESET Failed.\n", __FUNCTION__);
+               return -1;
+       }
+       if (dst_addons & DST_TYPE_HAS_CA)
+               msleep(4000);
+       else
+               msleep(100);
+
+       if ((dst_comm_init(state)) < 0) {
+               dprintk("%s: DST Initialization Failed.\n", __FUNCTION__);
+               return -1;
+       }
+       msleep(100);
+       if (dst_get_device_id(state) < 0) {
+               dprintk("%s: unknown device.\n", __FUNCTION__);
+               return -1;
+       }
+
+       return 0;
+}
+
+int dst_command(struct dst_state* state, u8 * data, u8 len)
 {
-       int retval;
        u8 reply;
+       if ((dst_comm_init(state)) < 0) {
+               dprintk("%s: DST Communication Initialization Failed.\n", 
__FUNCTION__);
+               return -1;
+       }
 
-       dst_i2c_enable(state);
-       dst_reset8820(state);
-       retval = write_dst(state, data, len);
-       if (retval < 0) {
-               dst_i2c_disable(state);
-               dprintk("%s: write not successful\n", __FUNCTION__);
-               return retval;
+       if (write_dst(state, data, len)) {
+               if (verbose > 1)
+                       dprintk("%s: Tring to recover.. \n", __FUNCTION__);
+               if ((dst_error_recovery(state)) < 0) {
+                       dprintk("%s: Recovery Failed.\n", __FUNCTION__);
+                       return -1;
+               }
+               return -1;
        }
-       msleep(33);
-       retval = read_dst(state, &reply, 1);
-       dst_i2c_disable(state);
-       if (retval < 0) {
-               dprintk("%s: read verify  not successful\n", __FUNCTION__);
-               return retval;
+       if ((dst_pio_disable(state)) < 0) {
+               dprintk("%s: PIO Disable Failed.\n", __FUNCTION__);
+               return -1;
+       }
+       if (state->type_flags & DST_TYPE_HAS_FW_1)
+               udelay(3000);
+
+       if (read_dst(state, &reply, GET_ACK)) {
+               if (verbose > 1)
+                       dprintk("%s: Trying to recover.. \n", __FUNCTION__);
+               if ((dst_error_recovery(state)) < 0) {
+                       dprintk("%s: Recovery Failed.\n", __FUNCTION__);
+                       return -1;
+               }
+               return -1;
        }
-       if (reply != 0xff) {
-               dprintk("%s: write reply not 0xff 0x%02x \n", __FUNCTION__, 
reply);
-               return 0;
+
+       if (reply != ACK) {
+               dprintk("%s: write not acknowledged 0x%02x \n", __FUNCTION__, 
reply);
+               return -1;
        }
        if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3))
                return 0;
-       if (!dst_wait_dst_ready(state))
-               return 0;
-       // dst_i2c_enable(i2c); Per dimitri
-       retval = read_dst(state, state->rxbuffer, 8);
-       dst_i2c_disable(state);
-       if (retval < 0) {
-               dprintk("%s: read not successful\n", __FUNCTION__);
-               return 0;
+
+//     udelay(3000);
+       if (state->type_flags & DST_TYPE_HAS_FW_1)
+               udelay(3000);
+       else
+               udelay(2000);
+
+       if (!dst_wait_dst_ready(state, NO_DELAY))
+               return -1;
+
+       if (read_dst(state, state->rxbuffer, FIXED_COMM)) {
+               if (verbose > 1)
+                       dprintk("%s: Trying to recover.. \n", __FUNCTION__);
+               if ((dst_error_recovery(state)) < 0) {
+                       dprintk("%s: Recovery failed.\n", __FUNCTION__);
+                       return -1;
+               }
+               return -1;
        }
+
        if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
                dprintk("%s: checksum failure\n", __FUNCTION__);
-               return 0;
+               return -1;
        }
+
        return 0;
 }
+EXPORT_SYMBOL(dst_command);
 
 static int dst_get_signal(struct dst_state* state)
 {
@@ -646,11 +910,17 @@
                paket[4] = 0;
        else
                paket[4] = 1;
+
        if (state->tone == SEC_TONE_ON)
-               paket[2] = state->k22;
+               paket[2] = 0x02;
        else
                paket[2] = 0;
-       paket[7] = dst_check_sum(&paket[0], 7);
+       if (state->minicmd == SEC_MINI_A)
+               paket[3] = 0x02;
+       else
+               paket[3] = 0;
+
+       paket[7] = dst_check_sum (paket, 7);
        dst_command(state, paket, 8);
        return 0;
 }
@@ -658,21 +928,26 @@
 static int dst_get_tuna(struct dst_state* state)
 {
        int retval;
+
        if ((state->diseq_flags & ATTEMPT_TUNE) == 0)
                return 0;
+
        state->diseq_flags &= ~(HAS_LOCK);
-       if (!dst_wait_dst_ready(state))
+       if (!dst_wait_dst_ready(state, NO_DELAY))
                return 0;
+
        if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
                /* how to get variable length reply ???? */
                retval = read_dst(state, state->rx_tuna, 10);
        } else {
-               retval = read_dst(state, &state->rx_tuna[2], 8);
+               retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
        }
+
        if (retval < 0) {
                dprintk("%s: read not successful\n", __FUNCTION__);
                return 0;
        }
+
        if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
                if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
                        dprintk("%s: checksum failure?\n", __FUNCTION__);
@@ -709,7 +984,9 @@
        int retval;
        u8 reply;
 
-       dprintk("%s: type_flags 0x%x \n", __FUNCTION__, state->type_flags);
+       if (debug > 4)
+               dprintk("%s: type_flags 0x%x \n", __FUNCTION__, 
state->type_flags);
+
        state->decode_freq = 0;
        state->decode_lock = state->decode_strength = state->decode_snr = 0;
        if (state->dst_type == DST_TYPE_IS_SAT) {
@@ -717,32 +994,41 @@
                        dst_set_voltage(fe, SEC_VOLTAGE_13);
        }
        state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE);
-       dst_i2c_enable(state);
+
+       if ((dst_comm_init(state)) < 0) {
+               dprintk("%s: DST Communication initialization failed.\n", 
__FUNCTION__);
+               return -1;
+       }
+
        if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
-               dst_reset8820(state);
                state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9);
                retval = write_dst(state, &state->tx_tuna[0], 10);
+
        } else {
                state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[2], 7);
-               retval = write_dst(state, &state->tx_tuna[2], 8);
+               retval = write_dst(state, &state->tx_tuna[2], FIXED_COMM);
        }
        if (retval < 0) {
-               dst_i2c_disable(state);
+               dst_pio_disable(state);
                dprintk("%s: write not successful\n", __FUNCTION__);
                return retval;
        }
-       msleep(3);
-       retval = read_dst(state, &reply, 1);
-       dst_i2c_disable(state);
-       if (retval < 0) {
-               dprintk("%s: read verify  not successful\n", __FUNCTION__);
-               return retval;
+
+       if ((dst_pio_disable(state)) < 0) {
+               dprintk("%s: DST PIO disable failed !\n", __FUNCTION__);
+               return -1;
        }
-       if (reply != 0xff) {
-               dprintk("%s: write reply not 0xff 0x%02x \n", __FUNCTION__, 
reply);
+
+       if ((read_dst(state, &reply, GET_ACK) < 0)) {
+               dprintk("%s: read verify not successful.\n", __FUNCTION__);
+               return -1;
+       }
+       if (reply != ACK) {
+               dprintk("%s: write not acknowledged 0x%02x \n", __FUNCTION__, 
reply);
                return 0;
        }
        state->diseq_flags |= ATTEMPT_TUNE;
+
        return dst_get_tuna(state);
 }
 
@@ -796,22 +1082,25 @@
                        need_cmd = 1;
                state->diseq_flags |= HAS_POWER;
                break;
+
        case SEC_VOLTAGE_18:
                if ((state->diseq_flags & HAS_POWER) == 0)
                        need_cmd = 1;
                state->diseq_flags |= HAS_POWER;
                val[8] |= 0x40;
                break;
+
        case SEC_VOLTAGE_OFF:
                need_cmd = 1;
                state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
                break;
+
        default:
                return -EINVAL;
        }
-       if (need_cmd) {
+       if (need_cmd)
                dst_tone_power_cmd(state);
-       }
+
        return 0;
 }
 
@@ -832,13 +1121,16 @@
        switch (tone) {
        case SEC_TONE_OFF:
                break;
+
        case SEC_TONE_ON:
                val[8] |= 1;
                break;
+
        default:
                return -EINVAL;
        }
        dst_tone_power_cmd(state);
+
        return 0;
 }
 
@@ -913,10 +1205,16 @@
        struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
 
        dst_set_freq(state, p->frequency);
+       if (verbose > 4)
+               dprintk("Set Frequency = [%d]\n", p->frequency);
+
        dst_set_inversion(state, p->inversion);
        if (state->dst_type == DST_TYPE_IS_SAT) {
                dst_set_fec(state, p->u.qpsk.fec_inner);
                dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
+               if (verbose > 4)
+                       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) {
@@ -958,50 +1256,47 @@
 static struct dvb_frontend_ops dst_dvbs_ops;
 static struct dvb_frontend_ops dst_dvbc_ops;
 
-struct dvb_frontend* dst_attach(const struct dst_config* config,
-                               struct i2c_adapter* i2c,
-                               struct bt878 *bt)
-{
-       struct dst_state* state = NULL;
-
-       /* allocate memory for the internal state */
-       state = (struct dst_state*) kmalloc(sizeof(struct dst_state), 
GFP_KERNEL);
-       if (state == NULL) goto error;
-
-       /* setup the state */
-       state->config = config;
-       state->i2c = i2c;
-       state->bt = bt;
+struct dst_state* dst_attach(struct dst_state *state, struct dvb_adapter 
*dvb_adapter)
+{
 
-       /* check if the demod is there */
-       if (dst_check_ci(state) < 0) goto error;
+       /* check if the ASIC is there */
+       if (dst_probe(state) < 0) {
+               if (state)
+                       kfree(state);
 
+               return NULL;
+       }
        /* determine settings based on type */
        switch (state->dst_type) {
        case DST_TYPE_IS_TERR:
                memcpy(&state->ops, &dst_dvbt_ops, sizeof(struct 
dvb_frontend_ops));
                break;
+
        case DST_TYPE_IS_CABLE:
                memcpy(&state->ops, &dst_dvbc_ops, sizeof(struct 
dvb_frontend_ops));
                break;
+
        case DST_TYPE_IS_SAT:
                memcpy(&state->ops, &dst_dvbs_ops, sizeof(struct 
dvb_frontend_ops));
                break;
+
        default:
-               printk("dst: unknown frontend type. please report to the 
LinuxTV.org DVB mailinglist.\n");
-               goto error;
+               printk("%s: unknown DST type. please report to the LinuxTV.org 
DVB mailinglist.\n", __FUNCTION__);
+               if (state)
+                       kfree(state);
+
+               return NULL;
        }
 
        /* create dvb_frontend */
        state->frontend.ops = &state->ops;
        state->frontend.demodulator_priv = state;
-       return &state->frontend;
 
-error:
-       kfree(state);
-       return NULL;
+       return state;                           /*      Manu (DST is a card not 
a frontend)     */
 }
 
+EXPORT_SYMBOL(dst_attach);
+
 static struct dvb_frontend_ops dst_dvbt_ops = {
 
        .info = {
@@ -1051,6 +1346,7 @@
        .read_signal_strength = dst_read_signal_strength,
        .read_snr = dst_read_snr,
 
+       .diseqc_send_burst = dst_set_tone,
        .diseqc_send_master_cmd = dst_set_diseqc,
        .set_voltage = dst_set_voltage,
        .set_tone = dst_set_tone,
@@ -1082,8 +1378,7 @@
        .read_snr = dst_read_snr,
 };
 
+
 MODULE_DESCRIPTION("DST DVB-S/T/C Combo Frontend driver");
-MODULE_AUTHOR("Jamie Honan");
+MODULE_AUTHOR("Jamie Honan, Manu Abraham");
 MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(dst_attach);
diff -urN linux/drivers/media/dvb/bt8xx/dst_priv.h 
linux/drivers/media/dvb/bt8xx/dst_priv.h
--- linux/drivers/media/dvb/bt8xx/dst_priv.h    2005/04/08 18:58:16     1.2
+++ linux/drivers/media/dvb/bt8xx/dst_priv.h    2005/05/26 09:12:42     1.3
@@ -33,4 +33,3 @@
 struct bt878;
 
 int bt878_device_control(struct bt878 *bt, unsigned int cmd, union 
dst_gpio_packet *mp);
-
diff -urN linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c 
linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c
--- linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c   2005/04/08 18:58:16     1.9
+++ linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c   2005/05/26 09:12:42     1.10
@@ -142,7 +142,7 @@
        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_gpp_ctl_cfg, sizeof(mt352_gpp_ctl_cfg));
+       mt352_write(fe, mt352_gpp_ctl_cfg, sizeof(mt352_gpp_ctl_cfg));
        mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
 
        return 0;
@@ -161,7 +161,7 @@
        else if (params->frequency < 771000000) cp = 0xbc;
        else cp = 0xf4;
 
-        if (params->frequency == 0) bs = 0x03;
+       if (params->frequency == 0) bs = 0x03;
        else if (params->frequency < 443250000) bs = 0x02;
        else bs = 0x08;
 
@@ -190,44 +190,44 @@
 
 
    u32 osci[]={950000,1019000,1075000,1178000,1296000,1432000,
-               1576000,1718000,1856000,2036000,2150000};
+              1576000,1718000,1856000,2036000,2150000};
    u32 bandsel[]={0,0x00020000,0x00040000,0x00100800,0x00101000,
-               0x00102000,0x00104000,0x00108000,0x00110000,
-               0x00120000,0x00140000};
+              0x00102000,0x00104000,0x00108000,0x00110000,
+              0x00120000,0x00140000};
 
 #define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */
-        printk("cx24108 debug: entering SetTunerFreq, freq=%d\n",freq);
+       printk("cx24108 debug: entering SetTunerFreq, freq=%d\n",freq);
 
-        /* This is really the bit driving the tuner chip cx24108 */
+       /* This is really the bit driving the tuner chip cx24108 */
 
-        if(freq<950000) freq=950000; /* kHz */
-        if(freq>2150000) freq=2150000; /* satellite IF is 950..2150MHz */
+       if(freq<950000) freq=950000; /* kHz */
+       if(freq>2150000) freq=2150000; /* satellite IF is 950..2150MHz */
 
-        /* decide which VCO to use for the input frequency */
-        for(i=1;(i<sizeof(osci)/sizeof(osci[0]))&&(osci[i]<freq);i++);
-        printk("cx24108 debug: select vco #%d (f=%d)\n",i,freq);
-        band=bandsel[i];
-        /* the gain values must be set by SetSymbolrate */
-        /* compute the pll divider needed, from Conexant data sheet,
-           resolved for (n*32+a), remember f(vco) is f(receive) *2 or *4,
-           depending on the divider bit. It is set to /4 on the 2 lowest
-           bands  */
-        n=((i<=2?2:1)*freq*10L)/(XTAL/100);
-        a=n%32; n/=32; if(a==0) n--;
-        pump=(freq<(osci[i-1]+osci[i])/2);
-        pll=0xf8000000|
-            ((pump?1:2)<<(14+11))|
-            ((n&0x1ff)<<(5+11))|
-            ((a&0x1f)<<11);
-        /* everything is shifted left 11 bits to left-align the bits in the
-           32bit word. Output to the tuner goes MSB-aligned, after all */
-        printk("cx24108 debug: pump=%d, n=%d, a=%d\n",pump,n,a);
-        cx24110_pll_write(fe,band);
-        /* set vga and vca to their widest-band settings, as a precaution.
-           SetSymbolrate might not be called to set this up */
-        cx24110_pll_write(fe,0x500c0000);
-        cx24110_pll_write(fe,0x83f1f800);
-        cx24110_pll_write(fe,pll);
+       /* decide which VCO to use for the input frequency */
+       for(i=1;(i<sizeof(osci)/sizeof(osci[0]))&&(osci[i]<freq);i++);
+       printk("cx24108 debug: select vco #%d (f=%d)\n",i,freq);
+       band=bandsel[i];
+       /* the gain values must be set by SetSymbolrate */
+       /* compute the pll divider needed, from Conexant data sheet,
+          resolved for (n*32+a), remember f(vco) is f(receive) *2 or *4,
+          depending on the divider bit. It is set to /4 on the 2 lowest
+          bands  */
+       n=((i<=2?2:1)*freq*10L)/(XTAL/100);
+       a=n%32; n/=32; if(a==0) n--;
+       pump=(freq<(osci[i-1]+osci[i])/2);
+       pll=0xf8000000|
+           ((pump?1:2)<<(14+11))|
+           ((n&0x1ff)<<(5+11))|
+           ((a&0x1f)<<11);
+       /* everything is shifted left 11 bits to left-align the bits in the
+          32bit word. Output to the tuner goes MSB-aligned, after all */
+       printk("cx24108 debug: pump=%d, n=%d, a=%d\n",pump,n,a);
+       cx24110_pll_write(fe,band);
+       /* set vga and vca to their widest-band settings, as a precaution.
+          SetSymbolrate might not be called to set this up */
+       cx24110_pll_write(fe,0x500c0000);
+       cx24110_pll_write(fe,0x83f1f800);
+       cx24110_pll_write(fe,pll);
 /*        writereg(client,0x56,0x7f);*/
 
        return 0;
@@ -299,7 +299,7 @@
        static u8 mt352_reset [] = { 0x50, 0x80 };
        static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
        static u8 mt352_agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF,
-                                      0x00, 0xFF, 0x00, 0x40, 0x40 };
+                                      0x00, 0xFF, 0x00, 0x40, 0x40 };
        static u8 mt352_av771_extra[] = { 0xB5, 0x7A };
        static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
 
@@ -463,6 +463,9 @@
 
 static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 {
+       int ret;
+       struct dst_state* state = NULL;
+
        switch(type) {
 #ifdef BTTV_DVICO_DVBT_LITE
        case BTTV_DVICO_DVBT_LITE:
@@ -503,7 +506,25 @@
                break;
 
        case BTTV_TWINHAN_DST:
-               card->fe = dst_attach(&dst_config, card->i2c_adapter, card->bt);
+               /*      DST is not a frontend driver !!!                */
+               state = (struct dst_state *) kmalloc(sizeof (struct dst_state), 
GFP_KERNEL);
+               /*      Setup the Card                                  */
+               state->config = &dst_config;
+               state->i2c = card->i2c_adapter;
+               state->bt = card->bt;
+
+               /*      DST is not a frontend, attaching the ASIC       */
+               if ((dst_attach(state, &card->dvb_adapter)) == NULL) {
+                       printk("%s: Could not find a Twinhan DST.\n", 
__FUNCTION__);
+                       break;
+               }
+               card->fe = &state->frontend;
+
+               /*      Attach other DST peripherals if any             */
+               /*      Conditional Access device                       */
+               if (state->dst_hw_cap & DST_TYPE_HAS_CA) {
+                       ret = dst_ca_attach(state, &card->dvb_adapter);
+               }
                if (card->fe != NULL) {
                        break;
                }
@@ -531,7 +552,7 @@
                       card->bt->dev->subsystem_vendor,
                       card->bt->dev->subsystem_device);
        } else {
-               if (dvb_register_frontend(card->dvb_adapter, card->fe)) {
+               if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
                        printk("dvb-bt8xx: Frontend registration failed!\n");
                        if (card->fe->ops->release)
                                card->fe->ops->release(card->fe);
@@ -550,7 +571,7 @@
                return result;
 
        }
-       card->dvb_adapter->priv = card;
+       card->dvb_adapter.priv = card;
 
        card->bt->adapter = card->i2c_adapter;
 
@@ -568,7 +589,7 @@
        if ((result = dvb_dmx_init(&card->demux)) < 0) {
                printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
 
-               dvb_unregister_adapter(card->dvb_adapter);
+               dvb_unregister_adapter(&card->dvb_adapter);
                return result;
        }
 
@@ -576,11 +597,11 @@
        card->dmxdev.demux = &card->demux.dmx;
        card->dmxdev.capabilities = 0;
 
-       if ((result = dvb_dmxdev_init(&card->dmxdev, card->dvb_adapter)) < 0) {
+       if ((result = dvb_dmxdev_init(&card->dmxdev, &card->dvb_adapter)) < 0) {
                printk("dvb_bt8xx: dvb_dmxdev_init failed (errno = %d)\n", 
result);
 
                dvb_dmx_release(&card->demux);
-               dvb_unregister_adapter(card->dvb_adapter);
+               dvb_unregister_adapter(&card->dvb_adapter);
                return result;
        }
 
@@ -591,7 +612,7 @@
 
                dvb_dmxdev_release(&card->dmxdev);
                dvb_dmx_release(&card->demux);
-               dvb_unregister_adapter(card->dvb_adapter);
+               dvb_unregister_adapter(&card->dvb_adapter);
                return result;
        }
 
@@ -603,7 +624,7 @@
                card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
                dvb_dmxdev_release(&card->dmxdev);
                dvb_dmx_release(&card->demux);
-               dvb_unregister_adapter(card->dvb_adapter);
+               dvb_unregister_adapter(&card->dvb_adapter);
                return result;
        }
 
@@ -614,11 +635,11 @@
                card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
                dvb_dmxdev_release(&card->dmxdev);
                dvb_dmx_release(&card->demux);
-               dvb_unregister_adapter(card->dvb_adapter);
+               dvb_unregister_adapter(&card->dvb_adapter);
                return result;
        }
 
-       dvb_net_init(card->dvb_adapter, &card->dvbnet, &card->demux.dmx);
+       dvb_net_init(&card->dvb_adapter, &card->dvbnet, &card->demux.dmx);
 
        tasklet_init(&card->bt->tasklet, dvb_bt8xx_task, (unsigned long) card);
 
@@ -648,7 +669,7 @@
        case BTTV_PINNACLESAT:
                card->gpio_mode = 0x0400c060;
                /* should be: 
BT878_A_GAIN=0,BT878_A_PWRDN,BT878_DA_DPM,BT878_DA_SBR,
-                             BT878_DA_IOM=1,BT878_DA_APP to enable serial 
highspeed mode. */
+                             BT878_DA_IOM=1,BT878_DA_APP to enable serial 
highspeed mode. */
                card->op_sync_orin = 0;
                card->irq_err_ignore = 0;
                break;
@@ -759,7 +780,7 @@
        dvb_dmxdev_release(&card->dmxdev);
        dvb_dmx_release(&card->demux);
        if (card->fe) dvb_unregister_frontend(card->fe);
-       dvb_unregister_adapter(card->dvb_adapter);
+       dvb_unregister_adapter(&card->dvb_adapter);
 
        kfree(card);
 
diff -urN linux/drivers/media/dvb/bt8xx/dvb-bt8xx.h 
linux/drivers/media/dvb/bt8xx/dvb-bt8xx.h
--- linux/drivers/media/dvb/bt8xx/dvb-bt8xx.h   2005/04/08 18:58:16     1.7
+++ linux/drivers/media/dvb/bt8xx/dvb-bt8xx.h   2005/05/26 09:12:42     1.8
@@ -31,7 +31,7 @@
 #include "bttv.h"
 #include "mt352.h"
 #include "sp887x.h"
-#include "dst.h"
+#include "dst_common.h"
 #include "nxt6000.h"
 #include "cx24110.h"
 #include "or51211.h"
@@ -40,7 +40,7 @@
        struct semaphore lock;
        int nfeeds;
        char card_name[32];
-       struct dvb_adapter *dvb_adapter;
+       struct dvb_adapter dvb_adapter;
        struct bt878 *bt;
        unsigned int bttv_nr;
        struct dvb_demux demux;
diff -urN linux/drivers/media/dvb/bt8xx/dst.h 
linux/drivers/media/dvb/bt8xx/dst.h
--- linux/drivers/media/dvb/bt8xx/Attic/dst.h   2005-05-26 10:12:42.822961000 
+0100     1.1
+++ linux/drivers/media/dvb/bt8xx/Attic/dst.h   1970/01/01 00:00:00+0100
@@ -1,40 +0,0 @@
-/*
-    Frontend-driver for TwinHan DST Frontend
-
-    Copyright (C) 2003 Jamie Honan
-
-    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 DST_H
-#define DST_H
-
-#include <linux/dvb/frontend.h>
-#include <linux/device.h>
-#include "bt878.h"
-
-struct dst_config
-{
-       /* the demodulator's i2c address */
-       u8 demod_address;
-};
-
-extern struct dvb_frontend* dst_attach(const struct dst_config* config,
-                                      struct i2c_adapter* i2c,
-                                      struct bt878 *bt);
-
-#endif // DST_H
diff -urN linux/drivers/media/dvb/cinergyT2/cinergyT2.c 
linux/drivers/media/dvb/cinergyT2/cinergyT2.c
--- linux/drivers/media/dvb/cinergyT2/cinergyT2.c       2005/04/29 11:15:07     
1.5
+++ linux/drivers/media/dvb/cinergyT2/cinergyT2.c       2005/05/26 09:12:42     
1.6
@@ -119,7 +119,7 @@
        struct dvb_demux demux;
        struct usb_device *udev;
        struct semaphore sem;
-       struct dvb_adapter *adapter;
+       struct dvb_adapter adapter;
        struct dvb_device *fedev;
        struct dmxdev dmxdev;
        struct dvb_net dvbnet;
@@ -813,15 +813,15 @@
        cinergyt2->dmxdev.demux = &cinergyt2->demux.dmx;
        cinergyt2->dmxdev.capabilities = 0;
 
-       if ((err = dvb_dmxdev_init(&cinergyt2->dmxdev, cinergyt2->adapter)) < 
0) {
+       if ((err = dvb_dmxdev_init(&cinergyt2->dmxdev, &cinergyt2->adapter)) < 
0) {
                dprintk(1, "dvb_dmxdev_init() failed (err = %d)\n", err);
                goto bailout;
        }
 
-       if (dvb_net_init(cinergyt2->adapter, &cinergyt2->dvbnet, 
&cinergyt2->demux.dmx))
+       if (dvb_net_init(&cinergyt2->adapter, &cinergyt2->dvbnet, 
&cinergyt2->demux.dmx))
                dprintk(1, "dvb_net_init() failed!\n");
 
-       dvb_register_device(cinergyt2->adapter, &cinergyt2->fedev,
+       dvb_register_device(&cinergyt2->adapter, &cinergyt2->fedev,
                            &cinergyt2_fe_template, cinergyt2,
                            DVB_DEVICE_FRONTEND);
 
@@ -848,7 +848,7 @@
 bailout:
        dvb_dmxdev_release(&cinergyt2->dmxdev);
        dvb_dmx_release(&cinergyt2->demux);
-       dvb_unregister_adapter (cinergyt2->adapter);
+       dvb_unregister_adapter (&cinergyt2->adapter);
        cinergyt2_free_stream_urbs (cinergyt2);
        kfree(cinergyt2);
        return -ENOMEM;
@@ -872,7 +872,7 @@
        dvb_dmxdev_release(&cinergyt2->dmxdev);
        dvb_dmx_release(&cinergyt2->demux);
        dvb_unregister_device(cinergyt2->fedev);
-       dvb_unregister_adapter(cinergyt2->adapter);
+       dvb_unregister_adapter(&cinergyt2->adapter);
 
        cinergyt2_free_stream_urbs(cinergyt2);
        up(&cinergyt2->sem);
diff -urN linux/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c 
linux/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c
--- linux/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c     2005/04/08 18:58:16     
1.2
+++ linux/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c     2005/05/26 09:12:42     
1.3
@@ -131,7 +131,7 @@
                deb_info("dvb_register_adapter failed: error %d", ret);
                goto err;
        }
-       dib->adapter->priv = dib;
+       dib->adapter.priv = dib;
        
 /* i2c is done in dibusb_i2c_init */
        
@@ -151,18 +151,18 @@
        dib->dmxdev.filternum = dib->demux.filternum;
        dib->dmxdev.demux = &dib->demux.dmx;
        dib->dmxdev.capabilities = 0;
-       if ((ret = dvb_dmxdev_init(&dib->dmxdev, dib->adapter)) < 0) {
+       if ((ret = dvb_dmxdev_init(&dib->dmxdev, &dib->adapter)) < 0) {
                err("dvb_dmxdev_init failed: error %d",ret);
                goto err_dmx_dev;
        }
 
-       dvb_net_init(dib->adapter, &dib->dvb_net, &dib->demux.dmx);
+       dvb_net_init(&dib->adapter, &dib->dvb_net, &dib->demux.dmx);
 
        goto success;
 err_dmx_dev:
        dvb_dmx_release(&dib->demux);
 err_dmx:
-       dvb_unregister_adapter(dib->adapter);
+       dvb_unregister_adapter(&dib->adapter);
 err:
        return ret;
 success:
@@ -179,7 +179,7 @@
                dib->demux.dmx.close(&dib->demux.dmx);
                dvb_dmxdev_release(&dib->dmxdev);
                dvb_dmx_release(&dib->demux);
-               dvb_unregister_adapter(dib->adapter);
+               dvb_unregister_adapter(&dib->adapter);
        }
        return 0;
 }
diff -urN linux/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c 
linux/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c
--- linux/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c  2005/04/08 18:58:16     
1.3
+++ linux/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c  2005/05/26 09:12:42     
1.4
@@ -183,7 +183,7 @@
                       dib->dibdev->name);
                return -ENODEV;
        } else {
-               if (dvb_register_frontend(dib->adapter, dib->fe)) {
+               if (dvb_register_frontend(&dib->adapter, dib->fe)) {
                        err("Frontend registration failed.");
                        if (dib->fe->ops->release)
                                dib->fe->ops->release(dib->fe);
@@ -206,7 +206,7 @@
 {
        int ret = 0;
 
-       dib->adapter->priv = dib;
+       dib->adapter.priv = dib;
 
        strncpy(dib->i2c_adap.name,dib->dibdev->name,I2C_NAME_SIZE);
 #ifdef I2C_ADAP_CLASS_TV_DIGITAL
diff -urN linux/drivers/media/dvb/dibusb/dvb-dibusb.h 
linux/drivers/media/dvb/dibusb/dvb-dibusb.h
--- linux/drivers/media/dvb/dibusb/dvb-dibusb.h 2005/04/08 18:58:16     1.6
+++ linux/drivers/media/dvb/dibusb/dvb-dibusb.h 2005/05/26 09:12:42     1.7
@@ -181,7 +181,7 @@
        struct semaphore i2c_sem;
 
        /* dvb */
-       struct dvb_adapter *adapter;
+       struct dvb_adapter adapter;
        struct dmxdev dmxdev;
        struct dvb_demux demux;
        struct dvb_net dvb_net;
diff -urN linux/drivers/media/dvb/dvb-core/dmxdev.c 
linux/drivers/media/dvb/dvb-core/dmxdev.c
--- linux/drivers/media/dvb/dvb-core/dmxdev.c   2005/04/08 18:58:16     1.9
+++ linux/drivers/media/dvb/dvb-core/dmxdev.c   2005/05/26 09:12:43     1.10
@@ -175,8 +175,8 @@
 
 static int dvb_dvr_open(struct inode *inode, struct file *file)
 {
-       struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
-       struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct dmxdev *dmxdev = dvbdev->priv;
        struct dmx_frontend *front;
 
        dprintk ("function : %s\n", __FUNCTION__);
@@ -224,8 +224,8 @@
 
 static int dvb_dvr_release(struct inode *inode, struct file *file)
 {
-       struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
-       struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct dmxdev *dmxdev = dvbdev->priv;
 
        if (down_interruptible (&dmxdev->mutex))
                return -ERESTARTSYS;
@@ -252,8 +252,8 @@
 static ssize_t dvb_dvr_write(struct file *file, const char __user *buf,
                size_t count, loff_t *ppos)
 {
-       struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
-       struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct dmxdev *dmxdev = dvbdev->priv;
        int ret;
 
        if (!dmxdev->demux->write)
@@ -270,8 +270,8 @@
 static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
                loff_t *ppos)
 {
-       struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
-       struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct dmxdev *dmxdev = dvbdev->priv;
        int ret;
 
        //down(&dmxdev->mutex);
@@ -345,7 +345,7 @@
                            const u8 *buffer2, size_t buffer2_len,
                            struct dmx_section_filter *filter, enum dmx_success 
success)
 {
-       struct dmxdev_filter *dmxdevfilter=(struct dmxdev_filter *) 
filter->priv;
+       struct dmxdev_filter *dmxdevfilter = filter->priv;
        int ret;
 
        if (dmxdevfilter->buffer.error) {
@@ -381,7 +381,7 @@
                       const u8 *buffer2, size_t buffer2_len,
                       struct dmx_ts_feed *feed, enum dmx_success success)
 {
-       struct dmxdev_filter *dmxdevfilter=(struct dmxdev_filter *) feed->priv;
+       struct dmxdev_filter *dmxdevfilter = feed->priv;
        struct dmxdev_buffer *buffer;
        int ret;
 
@@ -684,8 +684,8 @@
 
 static int dvb_demux_open(struct inode *inode, struct file *file)
 {
-       struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
-       struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct dmxdev *dmxdev = dvbdev->priv;
        int i;
        struct dmxdev_filter *dmxdevfilter;
 
@@ -1013,8 +1013,8 @@
 static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
                     unsigned int cmd, void *parg)
 {
-       struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
-       struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct dmxdev *dmxdev = dvbdev->priv;
 
        int ret=0;
 
@@ -1044,8 +1044,8 @@
 
 static unsigned int dvb_dvr_poll (struct file *file, poll_table *wait)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct dmxdev *dmxdev = (struct dmxdev *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct dmxdev *dmxdev = dvbdev->priv;
        unsigned int mask = 0;
 
        dprintk ("function : %s\n", __FUNCTION__);
diff -urN linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c 
linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
--- linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c   2005/04/08 18:58:16     
1.9
+++ linux/drivers/media/dvb/dvb-core/dvb_ca_en50221.c   2005/05/26 09:12:43     
1.10
@@ -829,7 +829,7 @@
  */
 void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221 *pubca, int slot, int 
change_type)
 {
-       struct dvb_ca_private *ca = (struct dvb_ca_private *) pubca->private;
+       struct dvb_ca_private *ca = pubca->private;
 
        dprintk("CAMCHANGE IRQ slot:%i change_type:%i\n", slot, change_type);
 
@@ -857,7 +857,7 @@
  */
 void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221 *pubca, int slot)
 {
-       struct dvb_ca_private *ca = (struct dvb_ca_private *) pubca->private;
+       struct dvb_ca_private *ca = pubca->private;
 
        dprintk("CAMREADY IRQ slot:%i\n", slot);
 
@@ -876,7 +876,7 @@
  */
 void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *pubca, int slot)
 {
-       struct dvb_ca_private *ca = (struct dvb_ca_private *) pubca->private;
+       struct dvb_ca_private *ca = pubca->private;
        int flags;
 
        dprintk("FR/DA IRQ slot:%i\n", slot);
@@ -993,7 +993,7 @@
  */
 static int dvb_ca_en50221_thread(void *data)
 {
-       struct dvb_ca_private *ca = (struct dvb_ca_private *) data;
+       struct dvb_ca_private *ca = data;
        char name[15];
        int slot;
        int flags;
@@ -1202,8 +1202,8 @@
 static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
                                      unsigned int cmd, void *parg)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct dvb_ca_private *ca = (struct dvb_ca_private *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct dvb_ca_private *ca = dvbdev->priv;
        int err = 0;
        int slot;
 
@@ -1225,7 +1225,7 @@
                break;
 
        case CA_GET_CAP: {
-               struct ca_caps *caps = (struct ca_caps *) parg;
+               struct ca_caps *caps = parg;
 
                caps->slot_num = ca->slot_count;
                caps->slot_type = CA_CI_LINK;
@@ -1235,7 +1235,7 @@
        }
 
        case CA_GET_SLOT_INFO: {
-               struct ca_slot_info *info = (struct ca_slot_info *) parg;
+               struct ca_slot_info *info = parg;
 
                if ((info->num > ca->slot_count) || (info->num < 0))
                        return -EINVAL;
@@ -1291,8 +1291,8 @@
 static ssize_t dvb_ca_en50221_io_write(struct file *file,
                                       const char __user * buf, size_t count, 
loff_t * ppos)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct dvb_ca_private *ca = (struct dvb_ca_private *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct dvb_ca_private *ca = dvbdev->priv;
        u8 slot, connection_id;
        int status;
        char fragbuf[HOST_LINK_BUF_SIZE];
@@ -1428,8 +1428,8 @@
 static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
                                      size_t count, loff_t * ppos)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct dvb_ca_private *ca = (struct dvb_ca_private *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct dvb_ca_private *ca = dvbdev->priv;
        int status;
        int result = 0;
        u8 hdr[2];
@@ -1526,8 +1526,8 @@
  */
 static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct dvb_ca_private *ca = (struct dvb_ca_private *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct dvb_ca_private *ca = dvbdev->priv;
        int err;
        int i;
 
@@ -1569,8 +1569,8 @@
  */
 static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct dvb_ca_private *ca = (struct dvb_ca_private *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct dvb_ca_private *ca = dvbdev->priv;
        int err = 0;
 
        dprintk("%s\n", __FUNCTION__);
@@ -1597,8 +1597,8 @@
  */
 static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * 
wait)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct dvb_ca_private *ca = (struct dvb_ca_private *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct dvb_ca_private *ca = dvbdev->priv;
        unsigned int mask = 0;
        int slot;
        int result = 0;
@@ -1750,7 +1750,7 @@
  */
 void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
 {
-       struct dvb_ca_private *ca = (struct dvb_ca_private *) pubca->private;
+       struct dvb_ca_private *ca = pubca->private;
        int i;
 
        dprintk("%s\n", __FUNCTION__);
diff -urN linux/drivers/media/dvb/dvb-core/dvb_frontend.c 
linux/drivers/media/dvb/dvb-core/dvb_frontend.c
--- linux/drivers/media/dvb/dvb-core/dvb_frontend.c     2005/04/08 18:58:16     
1.16
+++ linux/drivers/media/dvb/dvb-core/dvb_frontend.c     2005/05/26 09:12:43     
1.17
@@ -48,7 +48,7 @@
 static int dvb_powerdown_on_sleep = 1;
 
 module_param_named(frontend_debug, dvb_frontend_debug, int, 0644);
-MODULE_PARM_DESC(dvb_frontend_debug, "Turn on/off frontend core debugging 
(default:off).");
+MODULE_PARM_DESC(frontend_debug, "Turn on/off frontend core debugging 
(default:off).");
 module_param(dvb_shutdown_timeout, int, 0444);
 MODULE_PARM_DESC(dvb_shutdown_timeout, "wait <shutdown_timeout> seconds after 
close() before suspending hardware");
 module_param(dvb_force_auto_inversion, int, 0444);
@@ -117,7 +117,7 @@
 
 static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
 {
-       struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) 
fe->frontend_priv;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
        struct dvb_fe_events *events = &fepriv->events;
        struct dvb_frontend_event *e;
        int wp;
@@ -155,7 +155,7 @@
 static int dvb_frontend_get_event(struct dvb_frontend *fe,
                            struct dvb_frontend_event *event, int flags)
 {
-       struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) 
fe->frontend_priv;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
        struct dvb_fe_events *events = &fepriv->events;
 
        dprintk ("%s\n", __FUNCTION__);
@@ -234,7 +234,7 @@
 {
        int autoinversion;
        int ready = 0;
-       struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) 
fe->frontend_priv;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
        int original_inversion = fepriv->parameters.inversion;
        u32 original_frequency = fepriv->parameters.frequency;
 
@@ -321,7 +321,7 @@
 
 static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
 {
-       struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) 
fe->frontend_priv;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
 
        if (fepriv->exit)
                return 1;
@@ -335,7 +335,7 @@
 
 static int dvb_frontend_should_wakeup(struct dvb_frontend *fe)
 {
-       struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) 
fe->frontend_priv;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
 
        if (fepriv->wakeup) {
                fepriv->wakeup = 0;
@@ -346,7 +346,7 @@
 
 static void dvb_frontend_wakeup(struct dvb_frontend *fe)
 {
-       struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) 
fe->frontend_priv;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
 
        fepriv->wakeup = 1;
        wake_up_interruptible(&fepriv->wait_queue);
@@ -357,8 +357,8 @@
  */
 static int dvb_frontend_thread(void *data)
 {
-       struct dvb_frontend *fe = (struct dvb_frontend *) data;
-       struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) 
fe->frontend_priv;
+       struct dvb_frontend *fe = data;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
        unsigned long timeout;
        char name [15];
        int quality = 0, delay = 3*HZ;
@@ -520,7 +520,7 @@
 static void dvb_frontend_stop(struct dvb_frontend *fe)
 {
        unsigned long ret;
-       struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) 
fe->frontend_priv;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
 
        dprintk ("%s\n", __FUNCTION__);
 
@@ -559,7 +559,7 @@
 static int dvb_frontend_start(struct dvb_frontend *fe)
 {
        int ret;
-       struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) 
fe->frontend_priv;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
 
        dprintk ("%s\n", __FUNCTION__);
 
@@ -597,7 +597,7 @@
 {
        struct dvb_device *dvbdev = file->private_data;
        struct dvb_frontend *fe = dvbdev->priv;
-       struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) 
fe->frontend_priv;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
        int err = -EOPNOTSUPP;
 
        dprintk ("%s\n", __FUNCTION__);
@@ -615,7 +615,7 @@
 
        switch (cmd) {
        case FE_GET_INFO: {
-               struct dvb_frontend_info* info = (struct dvb_frontend_info*) 
parg;
+               struct dvb_frontend_info* info = parg;
                memcpy(info, &fe->ops->info, sizeof(struct dvb_frontend_info));
 
                /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
@@ -793,7 +793,7 @@
 {
        struct dvb_device *dvbdev = file->private_data;
        struct dvb_frontend *fe = dvbdev->priv;
-       struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) 
fe->frontend_priv;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
 
        dprintk ("%s\n", __FUNCTION__);
 
@@ -809,7 +809,7 @@
 {
        struct dvb_device *dvbdev = file->private_data;
        struct dvb_frontend *fe = dvbdev->priv;
-       struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) 
fe->frontend_priv;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
        int ret;
 
        dprintk ("%s\n", __FUNCTION__);
@@ -833,7 +833,7 @@
 {
        struct dvb_device *dvbdev = file->private_data;
        struct dvb_frontend *fe = dvbdev->priv;
-       struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) 
fe->frontend_priv;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
 
        dprintk ("%s\n", __FUNCTION__);
 
@@ -873,7 +873,7 @@
                up(&frontend_mutex);
                return -ENOMEM;
        }
-       fepriv = (struct dvb_frontend_private*) fe->frontend_priv;
+       fepriv = fe->frontend_priv;
        memset(fe->frontend_priv, 0, sizeof(struct dvb_frontend_private));
 
        init_MUTEX (&fepriv->sem);
@@ -897,7 +897,7 @@
 
 int dvb_unregister_frontend(struct dvb_frontend* fe)
 {
-       struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) 
fe->frontend_priv;
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
        dprintk ("%s\n", __FUNCTION__);
 
        down (&frontend_mutex);
diff -urN linux/drivers/media/dvb/dvb-core/dvb_net.c 
linux/drivers/media/dvb/dvb-core/dvb_net.c
--- linux/drivers/media/dvb/dvb-core/dvb_net.c  2005/04/08 18:58:16     1.19
+++ linux/drivers/media/dvb/dvb-core/dvb_net.c  2005/05/26 09:12:43     1.20
@@ -315,7 +315,7 @@
  */
 static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len 
)
 {
-       struct dvb_net_priv *priv = (struct dvb_net_priv *)dev->priv;
+       struct dvb_net_priv *priv = dev->priv;
        unsigned long skipped = 0L;
        u8 *ts, *ts_end, *from_where = NULL, ts_remain = 0, how_much = 0, 
new_ts = 1;
        struct ethhdr *ethh = NULL;
@@ -709,7 +709,7 @@
                               const u8 *buffer2, size_t buffer2_len,
                               struct dmx_ts_feed *feed, enum dmx_success 
success)
 {
-       struct net_device *dev = (struct net_device *)feed->priv;
+       struct net_device *dev = feed->priv;
 
        if (buffer2 != 0)
                printk(KERN_WARNING "buffer2 not 0: %p.\n", buffer2);
@@ -727,6 +727,7 @@
         u8 *eth;
         struct sk_buff *skb;
        struct net_device_stats *stats = &(((struct dvb_net_priv *) 
dev->priv)->stats);
+       int snap = 0;
 
        /* note: pkt_len includes a 32bit checksum */
        if (pkt_len < 16) {
@@ -750,9 +751,12 @@
                return;
        }
        if (pkt[5] & 0x02) {
-               //FIXME: handle LLC/SNAP
-                stats->rx_dropped++;
-                return;
+               /* handle LLC/SNAP, see rfc-1042 */
+               if (pkt_len < 24 || memcmp(&pkt[12], "\xaa\xaa\x03\0\0\0", 6)) {
+                       stats->rx_dropped++;
+                       return;
+               }
+               snap = 8;
         }
        if (pkt[7]) {
                /* FIXME: assemble datagram from multiple sections */
@@ -762,9 +766,9 @@
        }
 
        /* we have 14 byte ethernet header (ip header follows);
-        * 12 byte MPE header; 4 byte checksum; + 2 byte alignment
+        * 12 byte MPE header; 4 byte checksum; + 2 byte alignment, 8 byte 
LLC/SNAP
         */
-       if (!(skb = dev_alloc_skb(pkt_len - 4 - 12 + 14 + 2))) {
+       if (!(skb = dev_alloc_skb(pkt_len - 4 - 12 + 14 + 2 - snap))) {
                //printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", 
dev->name);
                stats->rx_dropped++;
                return;
@@ -773,8 +777,8 @@
        skb->dev = dev;
 
        /* copy L3 payload */
-       eth = (u8 *) skb_put(skb, pkt_len - 12 - 4 + 14);
-       memcpy(eth + 14, pkt + 12, pkt_len - 12 - 4);
+       eth = (u8 *) skb_put(skb, pkt_len - 12 - 4 + 14 - snap);
+       memcpy(eth + 14, pkt + 12 + snap, pkt_len - 12 - 4 - snap);
 
        /* create ethernet header: */
         eth[0]=pkt[0x0b];
@@ -786,8 +790,21 @@
 
         eth[6]=eth[7]=eth[8]=eth[9]=eth[10]=eth[11]=0;
 
-       eth[12] = 0x08; /* ETH_P_IP */
-       eth[13] = 0x00;
+       if (snap) {
+               eth[12] = pkt[18];
+               eth[13] = pkt[19];
+       } else {
+               /* protocol numbers are from rfc-1700 or
+                * http://www.iana.org/assignments/ethernet-numbers
+                */
+               if (pkt[12] >> 4 == 6) { /* version field from IP header */
+                       eth[12] = 0x86; /* IPv6 */
+                       eth[13] = 0xdd;
+               } else {
+                       eth[12] = 0x08; /* IPv4 */
+                       eth[13] = 0x00;
+               }
+       }
 
        skb->protocol = dvb_net_eth_type_trans(skb, dev);
 
@@ -801,7 +818,7 @@
                 struct dmx_section_filter *filter,
                 enum dmx_success success)
 {
-        struct net_device *dev=(struct net_device *) filter->priv;
+        struct net_device *dev = filter->priv;
 
        /**
         * we rely on the DVB API definition where exactly one complete
@@ -826,7 +843,7 @@
                   struct dmx_section_filter **secfilter,
                   u8 *mac, u8 *mac_mask)
 {
-       struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+       struct dvb_net_priv *priv = dev->priv;
        int ret;
 
        *secfilter=NULL;
@@ -870,7 +887,7 @@
 static int dvb_net_feed_start(struct net_device *dev)
 {
        int ret, i;
-       struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+       struct dvb_net_priv *priv = dev->priv;
         struct dmx_demux *demux = priv->demux;
         unsigned char *mac = (unsigned char *) dev->dev_addr;
 
@@ -965,7 +982,7 @@
 
 static int dvb_net_feed_stop(struct net_device *dev)
 {
-       struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+       struct dvb_net_priv *priv = dev->priv;
        int i;
 
        dprintk("%s\n", __FUNCTION__);
@@ -1016,7 +1033,7 @@
 
 static int dvb_set_mc_filter (struct net_device *dev, struct dev_mc_list *mc)
 {
-       struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+       struct dvb_net_priv *priv = dev->priv;
 
        if (priv->multi_num == DVB_NET_MULTICAST_MAX)
                return -ENOMEM;
@@ -1031,7 +1048,7 @@
 static void wq_set_multicast_list (void *data)
 {
        struct net_device *dev = data;
-       struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+       struct dvb_net_priv *priv = dev->priv;
 
        dvb_net_feed_stop(dev);
 
@@ -1066,7 +1083,7 @@
 
 static void dvb_net_set_multicast_list (struct net_device *dev)
 {
-       struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+       struct dvb_net_priv *priv = dev->priv;
        schedule_work(&priv->set_multicast_list_wq);
 }
 
@@ -1084,7 +1101,7 @@
 
 static int dvb_net_set_mac (struct net_device *dev, void *p)
 {
-       struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+       struct dvb_net_priv *priv = dev->priv;
        struct sockaddr *addr=p;
 
        memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
@@ -1098,7 +1115,7 @@
 
 static int dvb_net_open(struct net_device *dev)
 {
-       struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+       struct dvb_net_priv *priv = dev->priv;
 
        priv->in_use++;
        dvb_net_feed_start(dev);
@@ -1108,7 +1125,7 @@
 
 static int dvb_net_stop(struct net_device *dev)
 {
-       struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+       struct dvb_net_priv *priv = dev->priv;
 
        priv->in_use--;
         return dvb_net_feed_stop(dev);
@@ -1228,8 +1245,8 @@
 static int dvb_net_do_ioctl(struct inode *inode, struct file *file,
                  unsigned int cmd, void *parg)
 {
-       struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
-       struct dvb_net *dvbnet = (struct dvb_net *) dvbdev->priv;
+       struct dvb_device *dvbdev = file->private_data;
+       struct dvb_net *dvbnet = dvbdev->priv;
 
        if (((file->f_flags&O_ACCMODE)==O_RDONLY))
                return -EPERM;
@@ -1237,7 +1254,7 @@
        switch (cmd) {
        case NET_ADD_IF:
        {
-               struct dvb_net_if *dvbnetif=(struct dvb_net_if *)parg;
+               struct dvb_net_if *dvbnetif = parg;
                int result;
 
                if (!capable(CAP_SYS_ADMIN))
@@ -1258,7 +1275,7 @@
        {
                struct net_device *netdev;
                struct dvb_net_priv *priv_data;
-               struct dvb_net_if *dvbnetif=(struct dvb_net_if *)parg;
+               struct dvb_net_if *dvbnetif = parg;
 
                if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
                    !dvbnet->state[dvbnetif->if_num])
@@ -1266,7 +1283,7 @@
 
                netdev = dvbnet->device[dvbnetif->if_num];
 
-               priv_data=(struct dvb_net_priv*)netdev->priv;
+               priv_data = netdev->priv;
                dvbnetif->pid=priv_data->pid;
                dvbnetif->feedtype=priv_data->feedtype;
                break;
@@ -1288,7 +1305,7 @@
        /* binary compatiblity cruft */
        case __NET_ADD_IF_OLD:
        {
-               struct __dvb_net_if_old *dvbnetif=(struct __dvb_net_if_old 
*)parg;
+               struct __dvb_net_if_old *dvbnetif = parg;
                int result;
 
                if (!capable(CAP_SYS_ADMIN))
@@ -1309,7 +1326,7 @@
        {
                struct net_device *netdev;
                struct dvb_net_priv *priv_data;
-               struct __dvb_net_if_old *dvbnetif=(struct __dvb_net_if_old 
*)parg;
+               struct __dvb_net_if_old *dvbnetif = parg;
 
                if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
                    !dvbnet->state[dvbnetif->if_num])
@@ -1317,7 +1334,7 @@
 
                netdev = dvbnet->device[dvbnetif->if_num];
 
-               priv_data=(struct dvb_net_priv*)netdev->priv;
+               priv_data = netdev->priv;
                dvbnetif->pid=priv_data->pid;
                break;
        }
diff -urN linux/drivers/media/dvb/dvb-core/dvbdev.c 
linux/drivers/media/dvb/dvb-core/dvbdev.c
--- linux/drivers/media/dvb/dvb-core/dvbdev.c   2005/04/08 18:58:16     1.19
+++ linux/drivers/media/dvb/dvb-core/dvbdev.c   2005/05/26 09:12:43     1.20
@@ -286,9 +286,8 @@
 }
 
 
-int dvb_register_adapter(struct dvb_adapter **padap, const char *name, struct 
module *module)
+int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct 
module *module)
 {
-       struct dvb_adapter *adap;
        int num;
 
        if (down_interruptible (&dvbdev_register_lock))
@@ -299,11 +298,6 @@
                return -ENFILE;
        }
 
-       if (!(*padap = adap = kmalloc(sizeof(struct dvb_adapter), GFP_KERNEL))) 
{
-               up(&dvbdev_register_lock);
-               return -ENOMEM;
-       }
-
        memset (adap, 0, sizeof(struct dvb_adapter));
        INIT_LIST_HEAD (&adap->device_list);
 
@@ -331,7 +325,6 @@
                return -ERESTARTSYS;
        list_del (&adap->list_head);
        up (&dvbdev_register_lock);
-       kfree (adap);
        return 0;
 }
 EXPORT_SYMBOL(dvb_unregister_adapter);
diff -urN linux/drivers/media/dvb/dvb-core/dvbdev.h 
linux/drivers/media/dvb/dvb-core/dvbdev.h
--- linux/drivers/media/dvb/dvb-core/dvbdev.h   2005/03/18 17:37:26     1.12
+++ linux/drivers/media/dvb/dvb-core/dvbdev.h   2005/05/26 09:12:43     1.13
@@ -76,7 +76,7 @@
 };
 
 
-extern int dvb_register_adapter (struct dvb_adapter **padap, const char *name, 
struct module *module);
+extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, 
struct module *module);
 extern int dvb_unregister_adapter (struct dvb_adapter *adap);
 
 extern int dvb_register_device (struct dvb_adapter *adap,
diff -urN linux/drivers/media/dvb/frontends/Kconfig 
linux/drivers/media/dvb/frontends/Kconfig
--- linux/drivers/media/dvb/frontends/Kconfig   2005/04/08 18:58:16     1.17
+++ linux/drivers/media/dvb/frontends/Kconfig   2005/05/26 09:12:43     1.18
@@ -12,10 +12,10 @@
 
 config DVB_CX24110
        tristate "Conexant CX24110 based"
-       depends on DVB_CORE
-       help
+       depends on DVB_CORE
+       help
          A DVB-S tuner module. Say Y when you want to support this frontend.
- 
+
 config DVB_TDA8083
        tristate "Philips TDA8083 based"
        depends on DVB_CORE
@@ -127,8 +127,8 @@
 config DVB_ATMEL_AT76C651
        tristate "Atmel AT76C651 based"
        depends on DVB_CORE
-        help
-         A DVB-C tuner module. Say Y when you want to support this frontend.
+       help
+         A DVB-C tuner module. Say Y when you want to support this frontend.
 
 config DVB_VES1820
        tristate "VLSI VES1820 based"
@@ -158,10 +158,6 @@
        help
          An ATSC 8VSB tuner module. Say Y when you want to support this 
frontend.
 
-config DVB_OR51132
-       tristate "OR51132 based (pcHDTV)"
-       depends on DVB_CORE
-
 config DVB_OR51211
        tristate "or51211 based (pcHDTV HD2000 card)"
        depends on DVB_CORE
@@ -169,4 +165,12 @@
        help
          An ATSC 8VSB tuner module. Say Y when you want to support this 
frontend.
 
+config DVB_OR51132
+       tristate "OR51132 based (pcHDTV HD3000 card)"
+       depends on DVB_CORE
+       select FW_LOADER
+       help
+         An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+         to support this frontend.
+
 endmenu
diff -urN linux/drivers/media/dvb/frontends/at76c651.c 
linux/drivers/media/dvb/frontends/at76c651.c
--- linux/drivers/media/dvb/frontends/at76c651.c        2005/04/08 18:58:16     
1.9
+++ linux/drivers/media/dvb/frontends/at76c651.c        2005/05/26 09:12:43     
1.10
@@ -259,7 +259,7 @@
                                   struct dvb_frontend_parameters *p)
 {
        int ret;
-       struct at76c651_state* state = (struct at76c651_state*) 
fe->demodulator_priv;
+       struct at76c651_state* state = fe->demodulator_priv;
 
        at76c651_writereg(state, 0x0c, 0xc3);
        state->config->pll_set(fe, p);
@@ -276,7 +276,7 @@
 
 static int at76c651_set_defaults(struct dvb_frontend* fe)
 {
-       struct at76c651_state* state = (struct at76c651_state*) 
fe->demodulator_priv;
+       struct at76c651_state* state = fe->demodulator_priv;
 
        at76c651_set_symbol_rate(state, 6900000);
        at76c651_set_qam(state, QAM_64);
@@ -294,7 +294,7 @@
 
 static int at76c651_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
-       struct at76c651_state* state = (struct at76c651_state*) 
fe->demodulator_priv;
+       struct at76c651_state* state = fe->demodulator_priv;
        u8 sync;
 
        /*
@@ -319,7 +319,7 @@
 
 static int at76c651_read_ber(struct dvb_frontend* fe, u32* ber)
 {
-       struct at76c651_state* state = (struct at76c651_state*) 
fe->demodulator_priv;
+       struct at76c651_state* state = fe->demodulator_priv;
 
        *ber = (at76c651_readreg(state, 0x81) & 0x0F) << 16;
        *ber |= at76c651_readreg(state, 0x82) << 8;
@@ -331,7 +331,7 @@
 
 static int at76c651_read_signal_strength(struct dvb_frontend* fe, u16* 
strength)
 {
-       struct at76c651_state* state = (struct at76c651_state*) 
fe->demodulator_priv;
+       struct at76c651_state* state = fe->demodulator_priv;
 
        u8 gain = ~at76c651_readreg(state, 0x91);
        *strength = (gain << 8) | gain;
@@ -341,7 +341,7 @@
 
 static int at76c651_read_snr(struct dvb_frontend* fe, u16* snr)
 {
-       struct at76c651_state* state = (struct at76c651_state*) 
fe->demodulator_priv;
+       struct at76c651_state* state = fe->demodulator_priv;
 
        *snr = 0xFFFF -
            ((at76c651_readreg(state, 0x8F) << 8) |
@@ -352,7 +352,7 @@
 
 static int at76c651_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 {
-       struct at76c651_state* state = (struct at76c651_state*) 
fe->demodulator_priv;
+       struct at76c651_state* state = fe->demodulator_priv;
 
        *ucblocks = at76c651_readreg(state, 0x82);
 
@@ -369,7 +369,7 @@
 
 static void at76c651_release(struct dvb_frontend* fe)
 {
-       struct at76c651_state* state = (struct at76c651_state*) 
fe->demodulator_priv;
+       struct at76c651_state* state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -381,7 +381,7 @@
        struct at76c651_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = (struct at76c651_state*) kmalloc(sizeof(struct at76c651_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct at76c651_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
diff -urN linux/drivers/media/dvb/frontends/cx22700.c 
linux/drivers/media/dvb/frontends/cx22700.c
--- linux/drivers/media/dvb/frontends/cx22700.c 2005/04/08 18:58:16     1.4
+++ linux/drivers/media/dvb/frontends/cx22700.c 2005/05/26 09:12:43     1.5
@@ -232,7 +232,7 @@
 
 static int cx22700_init (struct dvb_frontend* fe)
 
-{      struct cx22700_state* state = (struct cx22700_state*) 
fe->demodulator_priv;
+{      struct cx22700_state* state = fe->demodulator_priv;
        int i;
 
        dprintk("cx22700_init: init chip\n");
@@ -258,7 +258,7 @@
 
 static int cx22700_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
-       struct cx22700_state* state = (struct cx22700_state*) 
fe->demodulator_priv;
+       struct cx22700_state* state = fe->demodulator_priv;
 
        u16 rs_ber = (cx22700_readreg (state, 0x0d) << 9)
                   | (cx22700_readreg (state, 0x0e) << 1);
@@ -286,7 +286,7 @@
 
 static int cx22700_read_ber(struct dvb_frontend* fe, u32* ber)
 {
-       struct cx22700_state* state = (struct cx22700_state*) 
fe->demodulator_priv;
+       struct cx22700_state* state = fe->demodulator_priv;
 
        *ber = cx22700_readreg (state, 0x0c) & 0x7f;
        cx22700_writereg (state, 0x0c, 0x00);
@@ -296,7 +296,7 @@
 
 static int cx22700_read_signal_strength(struct dvb_frontend* fe, u16* 
signal_strength)
 {
-       struct cx22700_state* state = (struct cx22700_state*) 
fe->demodulator_priv;
+       struct cx22700_state* state = fe->demodulator_priv;
 
        u16 rs_ber = (cx22700_readreg (state, 0x0d) << 9)
                   | (cx22700_readreg (state, 0x0e) << 1);
@@ -307,7 +307,7 @@
 
 static int cx22700_read_snr(struct dvb_frontend* fe, u16* snr)
 {
-       struct cx22700_state* state = (struct cx22700_state*) 
fe->demodulator_priv;
+       struct cx22700_state* state = fe->demodulator_priv;
 
        u16 rs_ber = (cx22700_readreg (state, 0x0d) << 9)
                   | (cx22700_readreg (state, 0x0e) << 1);
@@ -318,7 +318,7 @@
 
 static int cx22700_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 {
-       struct cx22700_state* state = (struct cx22700_state*) 
fe->demodulator_priv;
+       struct cx22700_state* state = fe->demodulator_priv;
 
        *ucblocks = cx22700_readreg (state, 0x0f);
        cx22700_writereg (state, 0x0f, 0x00);
@@ -328,7 +328,7 @@
 
 static int cx22700_set_frontend(struct dvb_frontend* fe, struct 
dvb_frontend_parameters *p)
 {
-       struct cx22700_state* state = (struct cx22700_state*) 
fe->demodulator_priv;
+       struct cx22700_state* state = fe->demodulator_priv;
 
        cx22700_writereg (state, 0x00, 0x02); /* XXX CHECKME: soft reset*/
        cx22700_writereg (state, 0x00, 0x00);
@@ -346,7 +346,7 @@
 
 static int cx22700_get_frontend(struct dvb_frontend* fe, struct 
dvb_frontend_parameters *p)
 {
-       struct cx22700_state* state = (struct cx22700_state*) 
fe->demodulator_priv;
+       struct cx22700_state* state = fe->demodulator_priv;
        u8 reg09 = cx22700_readreg (state, 0x09);
 
        p->inversion = reg09 & 0x1 ? INVERSION_ON : INVERSION_OFF;
@@ -363,7 +363,7 @@
 
 static void cx22700_release(struct dvb_frontend* fe)
 {
-       struct cx22700_state* state = (struct cx22700_state*) 
fe->demodulator_priv;
+       struct cx22700_state* state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -375,7 +375,7 @@
        struct cx22700_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = (struct cx22700_state*) kmalloc(sizeof(struct cx22700_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct cx22700_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
diff -urN linux/drivers/media/dvb/frontends/cx22702.c 
linux/drivers/media/dvb/frontends/cx22702.c
--- linux/drivers/media/dvb/frontends/cx22702.c 2005/05/19 12:08:24     1.5
+++ linux/drivers/media/dvb/frontends/cx22702.c 2005/05/26 09:12:43     1.6
@@ -200,7 +200,7 @@
 static int cx22702_set_tps (struct dvb_frontend* fe, struct 
dvb_frontend_parameters *p)
 {
        u8 val;
-       struct cx22702_state* state = (struct cx22702_state*) 
fe->demodulator_priv;
+       struct cx22702_state* state = fe->demodulator_priv;
 
        /* set PLL */
         cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe);
@@ -338,7 +338,7 @@
 static int cx22702_init (struct dvb_frontend* fe)
 {
        int i;
-       struct cx22702_state* state = (struct cx22702_state*) 
fe->demodulator_priv;
+       struct cx22702_state* state = fe->demodulator_priv;
 
        cx22702_writereg (state, 0x00, 0x02);
 
@@ -360,7 +360,7 @@
 
 static int cx22702_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
-       struct cx22702_state* state = (struct cx22702_state*) 
fe->demodulator_priv;
+       struct cx22702_state* state = fe->demodulator_priv;
        u8 reg0A;
        u8 reg23;
 
@@ -389,7 +389,7 @@
 
 static int cx22702_read_ber(struct dvb_frontend* fe, u32* ber)
 {
-       struct cx22702_state* state = (struct cx22702_state*) 
fe->demodulator_priv;
+       struct cx22702_state* state = fe->demodulator_priv;
 
        if(cx22702_readreg (state, 0xE4) & 0x02) {
                /* Realtime statistics */
@@ -406,7 +406,7 @@
 
 static int cx22702_read_signal_strength(struct dvb_frontend* fe, u16* 
signal_strength)
 {
-       struct cx22702_state* state = (struct cx22702_state*) 
fe->demodulator_priv;
+       struct cx22702_state* state = fe->demodulator_priv;
 
        *signal_strength = cx22702_readreg (state, 0x23);
 
@@ -415,7 +415,7 @@
 
 static int cx22702_read_snr(struct dvb_frontend* fe, u16* snr)
 {
-       struct cx22702_state* state = (struct cx22702_state*) 
fe->demodulator_priv;
+       struct cx22702_state* state = fe->demodulator_priv;
 
        u16 rs_ber=0;
        if(cx22702_readreg (state, 0xE4) & 0x02) {
@@ -434,7 +434,7 @@
 
 static int cx22702_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 {
-       struct cx22702_state* state = (struct cx22702_state*) 
fe->demodulator_priv;
+       struct cx22702_state* state = fe->demodulator_priv;
 
        u8 _ucblocks;
 
@@ -449,7 +449,7 @@
 
 static int cx22702_get_frontend(struct dvb_frontend* fe, struct 
dvb_frontend_parameters *p)
 {
-       struct cx22702_state* state = (struct cx22702_state*) 
fe->demodulator_priv;
+       struct cx22702_state* state = fe->demodulator_priv;
 
        u8 reg0C = cx22702_readreg (state, 0x0C);
 
@@ -459,7 +459,7 @@
 
 static void cx22702_release(struct dvb_frontend* fe)
 {
-       struct cx22702_state* state = (struct cx22702_state*) 
fe->demodulator_priv;
+       struct cx22702_state* state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -471,7 +471,7 @@
        struct cx22702_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = (struct cx22702_state*) kmalloc(sizeof(struct cx22702_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct cx22702_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
diff -urN linux/drivers/media/dvb/frontends/cx24110.c 
linux/drivers/media/dvb/frontends/cx24110.c
--- linux/drivers/media/dvb/frontends/cx24110.c 2005/04/08 18:58:16     1.8
+++ linux/drivers/media/dvb/frontends/cx24110.c 2005/05/26 09:12:43     1.9
@@ -315,7 +315,7 @@
 
 int cx24110_pll_write (struct dvb_frontend* fe, u32 data)
 {
-       struct cx24110_state *state = (struct cx24110_state*) 
fe->demodulator_priv;
+       struct cx24110_state *state = fe->demodulator_priv;
 
 /* tuner data is 21 bits long, must be left-aligned in data */
 /* tuner cx24108 is written through a dedicated 3wire interface on the demod 
chip */
@@ -356,7 +356,7 @@
 
 static int cx24110_initfe(struct dvb_frontend* fe)
 {
-       struct cx24110_state *state = (struct cx24110_state*) 
fe->demodulator_priv;
+       struct cx24110_state *state = fe->demodulator_priv;
 /* fixme (low): error handling */
         int i;
 
@@ -373,7 +373,7 @@
 
 static int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t 
voltage)
 {
-       struct cx24110_state *state = (struct cx24110_state*) 
fe->demodulator_priv;
+       struct cx24110_state *state = fe->demodulator_priv;
 
        switch (voltage) {
        case SEC_VOLTAGE_13:
@@ -385,8 +385,7 @@
        };
 }
 
-static int cx24110_diseqc_send_burst(struct dvb_frontend* fe,
-                       fe_sec_mini_cmd_t burst)
+static int cx24110_diseqc_send_burst(struct dvb_frontend* fe, 
fe_sec_mini_cmd_t burst)
 {
        int rv, bit, i;
        struct cx24110_state *state = fe->demodulator_priv;
@@ -413,7 +412,7 @@
                                   struct dvb_diseqc_master_cmd *cmd)
 {
        int i, rv;
-       struct cx24110_state *state = (struct cx24110_state*) 
fe->demodulator_priv;
+       struct cx24110_state *state = fe->demodulator_priv;
 
        for (i = 0; i < cmd->msg_len; i++)
                cx24110_writereg(state, 0x79 + i, cmd->msg[i]);
@@ -432,7 +431,7 @@
 
 static int cx24110_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
-       struct cx24110_state *state = (struct cx24110_state*) 
fe->demodulator_priv;
+       struct cx24110_state *state = fe->demodulator_priv;
 
        int sync = cx24110_readreg (state, 0x55);
 
@@ -460,7 +459,7 @@
 
 static int cx24110_read_ber(struct dvb_frontend* fe, u32* ber)
 {
-       struct cx24110_state *state = (struct cx24110_state*) 
fe->demodulator_priv;
+       struct cx24110_state *state = fe->demodulator_priv;
 
        /* fixme (maybe): value range is 16 bit. Scale? */
        if(cx24110_readreg(state,0x24)&0x10) {
@@ -478,7 +477,7 @@
 
 static int cx24110_read_signal_strength(struct dvb_frontend* fe, u16* 
signal_strength)
 {
-       struct cx24110_state *state = (struct cx24110_state*) 
fe->demodulator_priv;
+       struct cx24110_state *state = fe->demodulator_priv;
 
 /* no provision in hardware. Read the frontend AGC accumulator. No idea how to 
scale this, but I know it is 2s complement */
        u8 signal = cx24110_readreg (state, 0x27)+128;
@@ -489,7 +488,7 @@
 
 static int cx24110_read_snr(struct dvb_frontend* fe, u16* snr)
 {
-       struct cx24110_state *state = (struct cx24110_state*) 
fe->demodulator_priv;
+       struct cx24110_state *state = fe->demodulator_priv;
 
        /* no provision in hardware. Can be computed from the Es/N0 estimator, 
but I don't know how. */
        if(cx24110_readreg(state,0x6a)&0x80) {
@@ -505,7 +504,7 @@
 
 static int cx24110_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 {
-       struct cx24110_state *state = (struct cx24110_state*) 
fe->demodulator_priv;
+       struct cx24110_state *state = fe->demodulator_priv;
        u32 lastbyer;
 
        if(cx24110_readreg(state,0x10)&0x40) {
@@ -527,7 +526,7 @@
 
 static int cx24110_set_frontend(struct dvb_frontend* fe, struct 
dvb_frontend_parameters *p)
 {
-       struct cx24110_state *state = (struct cx24110_state*) 
fe->demodulator_priv;
+       struct cx24110_state *state = fe->demodulator_priv;
 
        state->config->pll_set(fe, p);
        cx24110_set_inversion (state, p->inversion);
@@ -540,7 +539,7 @@
 
 static int cx24110_get_frontend(struct dvb_frontend* fe, struct 
dvb_frontend_parameters *p)
 {
-       struct cx24110_state *state = (struct cx24110_state*) 
fe->demodulator_priv;
+       struct cx24110_state *state = fe->demodulator_priv;
        s32 afc; unsigned sclk;
 
 /* cannot read back tuner settings (freq). Need to have some private storage */
@@ -567,14 +566,14 @@
 
 static int cx24110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 {
-       struct cx24110_state *state = (struct cx24110_state*) 
fe->demodulator_priv;
+       struct cx24110_state *state = fe->demodulator_priv;
 
        return 
cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&~0x10)|(((tone==SEC_TONE_ON))?0x10:0));
 }
 
 static void cx24110_release(struct dvb_frontend* fe)
 {
-       struct cx24110_state* state = (struct cx24110_state*) 
fe->demodulator_priv;
+       struct cx24110_state* state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -587,7 +586,7 @@
        int ret;
 
        /* allocate memory for the internal state */
-       state = (struct cx24110_state*) kmalloc(sizeof(struct cx24110_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct cx24110_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
diff -urN linux/drivers/media/dvb/frontends/dib3000mb.c 
linux/drivers/media/dvb/frontends/dib3000mb.c
--- linux/drivers/media/dvb/frontends/dib3000mb.c       2005/04/08 18:58:16     
1.6
+++ linux/drivers/media/dvb/frontends/dib3000mb.c       2005/05/26 09:12:43     
1.7
@@ -56,12 +56,12 @@
 static int dib3000mb_set_frontend(struct dvb_frontend* fe,
                                  struct dvb_frontend_parameters *fep, int 
tuner)
 {
-       struct dib3000_state* state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state* state = fe->demodulator_priv;
        struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
        fe_code_rate_t fe_cr = FEC_NONE;
        int search_state, seq;
 
-       if (tuner) {
+       if (tuner && state->config.pll_addr && state->config.pll_set) {
                dib3000mb_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe));
                state->config.pll_set(fe, fep, NULL);
                dib3000mb_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
@@ -317,7 +317,7 @@
 
 static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)
 {
-       struct dib3000_state* state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state* state = fe->demodulator_priv;
 
        deb_info("dib3000mb is getting up.\n");
        wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_UP);
@@ -401,7 +401,7 @@
 static int dib3000mb_get_frontend(struct dvb_frontend* fe,
                                  struct dvb_frontend_parameters *fep)
 {
-       struct dib3000_state* state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state* state = fe->demodulator_priv;
        struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
        fe_code_rate_t *cr;
        u16 tps_val;
@@ -562,7 +562,7 @@
 
 static int dib3000mb_read_status(struct dvb_frontend* fe, fe_status_t *stat)
 {
-       struct dib3000_state* state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state* state = fe->demodulator_priv;
 
        *stat = 0;
 
@@ -594,7 +594,7 @@
 
 static int dib3000mb_read_ber(struct dvb_frontend* fe, u32 *ber)
 {
-       struct dib3000_state* state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state* state = fe->demodulator_priv;
 
        *ber = ((rd(DIB3000MB_REG_BER_MSB) << 16) | rd(DIB3000MB_REG_BER_LSB));
        return 0;
@@ -603,7 +603,7 @@
 /* see dib3000-watch dvb-apps for exact calcuations of signal_strength and snr 
*/
 static int dib3000mb_read_signal_strength(struct dvb_frontend* fe, u16 
*strength)
 {
-       struct dib3000_state* state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state* state = fe->demodulator_priv;
 
        *strength = rd(DIB3000MB_REG_SIGNAL_POWER) * 0xffff / 0x170;
        return 0;
@@ -611,7 +611,7 @@
 
 static int dib3000mb_read_snr(struct dvb_frontend* fe, u16 *snr)
 {
-       struct dib3000_state* state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state* state = fe->demodulator_priv;
        short sigpow = rd(DIB3000MB_REG_SIGNAL_POWER);
        int icipow = ((rd(DIB3000MB_REG_NOISE_POWER_MSB) & 0xff) << 16) |
                rd(DIB3000MB_REG_NOISE_POWER_LSB);
@@ -621,7 +621,7 @@
 
 static int dib3000mb_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
 {
-       struct dib3000_state* state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state* state = fe->demodulator_priv;
 
        *unc = rd(DIB3000MB_REG_UNC);
        return 0;
@@ -629,7 +629,7 @@
 
 static int dib3000mb_sleep(struct dvb_frontend* fe)
 {
-       struct dib3000_state* state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state* state = fe->demodulator_priv;
        deb_info("dib3000mb is going to bed.\n");
        wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_DOWN);
        return 0;
@@ -656,7 +656,7 @@
 
 static void dib3000mb_release(struct dvb_frontend* fe)
 {
-       struct dib3000_state *state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state *state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -671,7 +671,7 @@
 
 static int dib3000mb_fifo_control(struct dvb_frontend *fe, int onoff)
 {
-       struct dib3000_state *state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state *state = fe->demodulator_priv;
 
        deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling");
        if (onoff) {
@@ -692,7 +692,7 @@
 
 static int dib3000mb_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 
pll_addr)
 {
-       struct dib3000_state *state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state *state = fe->demodulator_priv;
        if (onoff) {
                wr(DIB3000MB_REG_TUNER, DIB3000_TUNER_WRITE_ENABLE(pll_addr));
        } else {
@@ -709,7 +709,7 @@
        struct dib3000_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = (struct dib3000_state*) kmalloc(sizeof(struct dib3000_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct dib3000_state), GFP_KERNEL);
        if (state == NULL)
                goto error;
        memset(state,0,sizeof(struct dib3000_state));
diff -urN linux/drivers/media/dvb/frontends/dib3000mc.c 
linux/drivers/media/dvb/frontends/dib3000mc.c
--- linux/drivers/media/dvb/frontends/dib3000mc.c       2005/04/08 18:58:16     
1.4
+++ linux/drivers/media/dvb/frontends/dib3000mc.c       2005/05/26 09:12:43     
1.5
@@ -297,7 +297,7 @@
 static int dib3000mc_get_frontend(struct dvb_frontend* fe,
                                  struct dvb_frontend_parameters *fep)
 {
-       struct dib3000_state* state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state* state = fe->demodulator_priv;
        struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
        fe_code_rate_t *cr;
        u16 tps_val,cr_val;
@@ -458,12 +458,12 @@
 static int dib3000mc_set_frontend(struct dvb_frontend* fe,
                                  struct dvb_frontend_parameters *fep, int 
tuner)
 {
-       struct dib3000_state* state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state* state = fe->demodulator_priv;
        struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
        int search_state,auto_val;
        u16 val;
 
-       if (tuner) { /* initial call from dvb */
+       if (tuner && state->config.pll_addr && state->config.pll_set) { /* 
initial call from dvb */
                dib3000mc_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe));
                state->config.pll_set(fe,fep,NULL);
                dib3000mc_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
@@ -659,7 +659,7 @@
 }
 static int dib3000mc_read_status(struct dvb_frontend* fe, fe_status_t *stat)
 {
-       struct dib3000_state* state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state* state = fe->demodulator_priv;
        u16 lock = rd(DIB3000MC_REG_LOCKING);
 
        *stat = 0;
@@ -679,14 +679,14 @@
 
 static int dib3000mc_read_ber(struct dvb_frontend* fe, u32 *ber)
 {
-       struct dib3000_state* state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state* state = fe->demodulator_priv;
        *ber = ((rd(DIB3000MC_REG_BER_MSB) << 16) | rd(DIB3000MC_REG_BER_LSB));
        return 0;
 }
 
 static int dib3000mc_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
 {
-       struct dib3000_state* state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state* state = fe->demodulator_priv;
 
        *unc = rd(DIB3000MC_REG_PACKET_ERROR_COUNT);
        return 0;
@@ -695,7 +695,7 @@
 /* see dib3000mb.c for calculation comments */
 static int dib3000mc_read_signal_strength(struct dvb_frontend* fe, u16 
*strength)
 {
-       struct dib3000_state* state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state* state = fe->demodulator_priv;
        u16 val = rd(DIB3000MC_REG_SIGNAL_NOISE_LSB);
        *strength = (((val >> 6) & 0xff) << 8) + (val & 0x3f);
 
@@ -706,7 +706,7 @@
 /* see dib3000mb.c for calculation comments */
 static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr)
 {
-       struct dib3000_state* state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state* state = fe->demodulator_priv;
        u16 val = rd(DIB3000MC_REG_SIGNAL_NOISE_LSB),
                val2 = rd(DIB3000MC_REG_SIGNAL_NOISE_MSB);
        u16 sig,noise;
@@ -726,7 +726,7 @@
 
 static int dib3000mc_sleep(struct dvb_frontend* fe)
 {
-       struct dib3000_state* state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state* state = fe->demodulator_priv;
 
        set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_PWR_DOWN);
        wr(DIB3000MC_REG_CLK_CFG_1,DIB3000MC_CLK_CFG_1_POWER_DOWN);
@@ -756,7 +756,7 @@
 
 static void dib3000mc_release(struct dvb_frontend* fe)
 {
-       struct dib3000_state *state = (struct dib3000_state *) 
fe->demodulator_priv;
+       struct dib3000_state *state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -771,7 +771,7 @@
 
 static int dib3000mc_fifo_control(struct dvb_frontend *fe, int onoff)
 {
-       struct dib3000_state *state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state *state = fe->demodulator_priv;
        u16 tmp = rd(DIB3000MC_REG_SMO_MODE);
 
        deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling");
@@ -803,7 +803,7 @@
 
 static int dib3000mc_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 
pll_addr)
 {
-       struct dib3000_state *state = (struct dib3000_state*) 
fe->demodulator_priv;
+       struct dib3000_state *state = fe->demodulator_priv;
        if (onoff) {
                wr(DIB3000MC_REG_TUNER, DIB3000_TUNER_WRITE_ENABLE(pll_addr));
        } else {
@@ -844,7 +844,7 @@
        u16 devid;
 
        /* allocate memory for the internal state */
-       state = (struct dib3000_state*) kmalloc(sizeof(struct dib3000_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct dib3000_state), GFP_KERNEL);
        if (state == NULL)
                goto error;
        memset(state,0,sizeof(struct dib3000_state));
diff -urN linux/drivers/media/dvb/frontends/dvb-pll.h 
linux/drivers/media/dvb/frontends/dvb-pll.h
--- linux/drivers/media/dvb/frontends/dvb-pll.h 2005/03/18 17:37:27     1.1
+++ linux/drivers/media/dvb/frontends/dvb-pll.h 2005/05/26 09:12:43     1.2
@@ -2,6 +2,9 @@
  * $Id: dvb-pll.h,v 1.2 2005/02/10 11:43:41 kraxel Exp $
  */
 
+#ifndef __DVB_PLL_H__
+#define __DVB_PLL_H__
+
 struct dvb_pll_desc {
        char *name;
        u32  min;
@@ -26,9 +29,4 @@
 int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
                      u32 freq, int bandwidth);
 
-/*
- * Local variables:
- * c-basic-offset: 8
- * compile-command: "make DVB=1"
- * End:
- */
+#endif
diff -urN linux/drivers/media/dvb/frontends/dvb_dummy_fe.c 
linux/drivers/media/dvb/frontends/dvb_dummy_fe.c
--- linux/drivers/media/dvb/frontends/dvb_dummy_fe.c    2005/04/08 18:58:16     
1.8
+++ linux/drivers/media/dvb/frontends/dvb_dummy_fe.c    2005/05/26 09:12:43     
1.9
@@ -100,7 +100,7 @@
 
 static void dvb_dummy_fe_release(struct dvb_frontend* fe)
 {
-       struct dvb_dummy_fe_state* state = (struct dvb_dummy_fe_state*) 
fe->demodulator_priv;
+       struct dvb_dummy_fe_state* state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -111,7 +111,7 @@
        struct dvb_dummy_fe_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = (struct dvb_dummy_fe_state*) kmalloc(sizeof(struct 
dvb_dummy_fe_state), GFP_KERNEL);
+       state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
@@ -134,7 +134,7 @@
        struct dvb_dummy_fe_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = (struct dvb_dummy_fe_state*) kmalloc(sizeof(struct 
dvb_dummy_fe_state), GFP_KERNEL);
+       state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
@@ -157,7 +157,7 @@
        struct dvb_dummy_fe_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = (struct dvb_dummy_fe_state*) kmalloc(sizeof(struct 
dvb_dummy_fe_state), GFP_KERNEL);
+       state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
diff -urN linux/drivers/media/dvb/frontends/l64781.c 
linux/drivers/media/dvb/frontends/l64781.c
--- linux/drivers/media/dvb/frontends/l64781.c  2005/04/08 18:58:16     1.3
+++ linux/drivers/media/dvb/frontends/l64781.c  2005/05/26 09:12:43     1.4
@@ -121,7 +121,7 @@
 
 static int apply_frontend_param (struct dvb_frontend* fe, struct 
dvb_frontend_parameters *param)
 {
-       struct l64781_state* state = (struct l64781_state*) 
fe->demodulator_priv;
+       struct l64781_state* state = fe->demodulator_priv;
        /* The coderates for FEC_NONE, FEC_4_5 and FEC_FEC_6_7 are arbitrary */
        static const u8 fec_tab[] = { 7, 0, 1, 2, 9, 3, 10, 4 };
        /* QPSK, QAM_16, QAM_64 */
@@ -234,7 +234,7 @@
 
 static int get_frontend(struct dvb_frontend* fe, struct 
dvb_frontend_parameters* param)
 {
-       struct l64781_state* state = (struct l64781_state*) 
fe->demodulator_priv;
+       struct l64781_state* state = fe->demodulator_priv;
        int tmp;
 
 
@@ -352,7 +352,7 @@
 
 static int l64781_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
-       struct l64781_state* state = (struct l64781_state*) 
fe->demodulator_priv;
+       struct l64781_state* state = fe->demodulator_priv;
        int sync = l64781_readreg (state, 0x32);
        int gain = l64781_readreg (state, 0x0e);
 
@@ -381,7 +381,7 @@
 
 static int l64781_read_ber(struct dvb_frontend* fe, u32* ber)
 {
-       struct l64781_state* state = (struct l64781_state*) 
fe->demodulator_priv;
+       struct l64781_state* state = fe->demodulator_priv;
 
        /*   XXX FIXME: set up counting period (reg 0x26...0x28)
         */
@@ -393,7 +393,7 @@
 
 static int l64781_read_signal_strength(struct dvb_frontend* fe, u16* 
signal_strength)
 {
-       struct l64781_state* state = (struct l64781_state*) 
fe->demodulator_priv;
+       struct l64781_state* state = fe->demodulator_priv;
 
        u8 gain = l64781_readreg (state, 0x0e);
        *signal_strength = (gain << 8) | gain;
@@ -403,7 +403,7 @@
 
 static int l64781_read_snr(struct dvb_frontend* fe, u16* snr)
 {
-       struct l64781_state* state = (struct l64781_state*) 
fe->demodulator_priv;
+       struct l64781_state* state = fe->demodulator_priv;
 
        u8 avg_quality = 0xff - l64781_readreg (state, 0x33);
        *snr = (avg_quality << 8) | avg_quality; /* not exact, but...*/
@@ -413,7 +413,7 @@
 
 static int l64781_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 {
-       struct l64781_state* state = (struct l64781_state*) 
fe->demodulator_priv;
+       struct l64781_state* state = fe->demodulator_priv;
 
        *ucblocks = l64781_readreg (state, 0x37)
           | (l64781_readreg (state, 0x38) << 8);
@@ -423,7 +423,7 @@
 
 static int l64781_sleep(struct dvb_frontend* fe)
 {
-       struct l64781_state* state = (struct l64781_state*) 
fe->demodulator_priv;
+       struct l64781_state* state = fe->demodulator_priv;
 
        /* Power down */
        return l64781_writereg (state, 0x3e, 0x5a);
@@ -431,7 +431,7 @@
 
 static int l64781_init(struct dvb_frontend* fe)
 {
-       struct l64781_state* state = (struct l64781_state*) 
fe->demodulator_priv;
+       struct l64781_state* state = fe->demodulator_priv;
 
         reset_and_configure (state);
 
@@ -484,7 +484,7 @@
 
 static void l64781_release(struct dvb_frontend* fe)
 {
-       struct l64781_state* state = (struct l64781_state*) 
fe->demodulator_priv;
+       struct l64781_state* state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -501,7 +501,7 @@
                           { .addr = config->demod_address, .flags = I2C_M_RD, 
.buf = b1, .len = 1 } };
 
        /* allocate memory for the internal state */
-       state = (struct l64781_state*) kmalloc(sizeof(struct l64781_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct l64781_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
diff -urN linux/drivers/media/dvb/frontends/mt312.c 
linux/drivers/media/dvb/frontends/mt312.c
--- linux/drivers/media/dvb/frontends/mt312.c   2005/04/08 18:58:16     1.10
+++ linux/drivers/media/dvb/frontends/mt312.c   2005/05/26 09:12:43     1.11
@@ -226,7 +226,7 @@
 
 static int mt312_initfe(struct dvb_frontend* fe)
 {
-       struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+       struct mt312_state *state = fe->demodulator_priv;
        int ret;
        u8 buf[2];
 
@@ -287,7 +287,7 @@
 static int mt312_send_master_cmd(struct dvb_frontend* fe,
                                 struct dvb_diseqc_master_cmd *c)
 {
-       struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+       struct mt312_state *state = fe->demodulator_priv;
        int ret;
        u8 diseqc_mode;
 
@@ -318,7 +318,7 @@
 
 static int mt312_send_burst(struct dvb_frontend* fe, const fe_sec_mini_cmd_t c)
 {
-       struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+       struct mt312_state *state = fe->demodulator_priv;
        const u8 mini_tab[2] = { 0x02, 0x03 };
 
        int ret;
@@ -340,7 +340,7 @@
 
 static int mt312_set_tone(struct dvb_frontend* fe, const fe_sec_tone_mode_t t)
 {
-       struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+       struct mt312_state *state = fe->demodulator_priv;
        const u8 tone_tab[2] = { 0x01, 0x00 };
 
        int ret;
@@ -362,7 +362,7 @@
 
 static int mt312_set_voltage(struct dvb_frontend* fe, const fe_sec_voltage_t v)
 {
-       struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+       struct mt312_state *state = fe->demodulator_priv;
        const u8 volt_tab[3] = { 0x00, 0x40, 0x00 };
 
        if (v > SEC_VOLTAGE_OFF)
@@ -373,7 +373,7 @@
 
 static int mt312_read_status(struct dvb_frontend* fe, fe_status_t *s)
 {
-       struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+       struct mt312_state *state = fe->demodulator_priv;
        int ret;
        u8 status[3];
 
@@ -400,7 +400,7 @@
 
 static int mt312_read_ber(struct dvb_frontend* fe, u32 *ber)
 {
-       struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+       struct mt312_state *state = fe->demodulator_priv;
        int ret;
        u8 buf[3];
 
@@ -414,7 +414,7 @@
 
 static int mt312_read_signal_strength(struct dvb_frontend* fe, u16 
*signal_strength)
 {
-       struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+       struct mt312_state *state = fe->demodulator_priv;
        int ret;
        u8 buf[3];
        u16 agc;
@@ -435,7 +435,7 @@
 
 static int mt312_read_snr(struct dvb_frontend* fe, u16 *snr)
 {
-       struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+       struct mt312_state *state = fe->demodulator_priv;
        int ret;
        u8 buf[2];
 
@@ -449,7 +449,7 @@
 
 static int mt312_read_ucblocks(struct dvb_frontend* fe, u32 *ubc)
 {
-       struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+       struct mt312_state *state = fe->demodulator_priv;
        int ret;
        u8 buf[2];
 
@@ -464,7 +464,7 @@
 static int mt312_set_frontend(struct dvb_frontend* fe,
                              struct dvb_frontend_parameters *p)
 {
-       struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+       struct mt312_state *state = fe->demodulator_priv;
        int ret;
        u8 buf[5], config_val;
        u16 sr;
@@ -560,7 +560,7 @@
 static int mt312_get_frontend(struct dvb_frontend* fe,
                              struct dvb_frontend_parameters *p)
 {
-       struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+       struct mt312_state *state = fe->demodulator_priv;
        int ret;
 
        if ((ret = mt312_get_inversion(state, &p->inversion)) < 0)
@@ -577,7 +577,7 @@
 
 static int mt312_sleep(struct dvb_frontend* fe)
 {
-       struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+       struct mt312_state *state = fe->demodulator_priv;
        int ret;
        u8 config;
 
@@ -605,7 +605,7 @@
 
 static void mt312_release(struct dvb_frontend* fe)
 {
-       struct mt312_state* state = (struct mt312_state*) fe->demodulator_priv;
+       struct mt312_state* state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -617,7 +617,7 @@
        struct mt312_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = (struct mt312_state*) kmalloc(sizeof(struct mt312_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL);
        if (state == NULL)
                goto error;
 
@@ -651,7 +651,7 @@
        struct mt312_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = (struct mt312_state*) kmalloc(sizeof(struct mt312_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL);
        if (state == NULL)
                goto error;
 
diff -urN linux/drivers/media/dvb/frontends/mt352.c 
linux/drivers/media/dvb/frontends/mt352.c
--- linux/drivers/media/dvb/frontends/mt352.c   2005/04/08 18:58:16     1.6
+++ linux/drivers/media/dvb/frontends/mt352.c   2005/05/26 09:12:43     1.7
@@ -46,7 +46,7 @@
        struct dvb_frontend_ops ops;
 
        /* configuration settings */
-       const struct mt352_config* config;
+       struct mt352_config config;
 };
 
 static int debug;
@@ -59,7 +59,7 @@
 {
        struct mt352_state* state = fe->demodulator_priv;
        u8 buf[2] = { reg, val };
-       struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0,
+       struct i2c_msg msg = { .addr = state->config.demod_address, .flags = 0,
                               .buf = buf, .len = 2 };
        int err = i2c_transfer(state->i2c, &msg, 1);
        if (err != 1) {
@@ -84,10 +84,10 @@
        int ret;
        u8 b0 [] = { reg };
        u8 b1 [] = { 0 };
-       struct i2c_msg msg [] = { { .addr = state->config->demod_address,
+       struct i2c_msg msg [] = { { .addr = state->config.demod_address,
                                    .flags = 0,
                                    .buf = b0, .len = 1 },
-                                 { .addr = state->config->demod_address,
+                                 { .addr = state->config.demod_address,
                                    .flags = I2C_M_RD,
                                    .buf = b1, .len = 1 } };
 
@@ -102,11 +102,6 @@
        return b1[0];
 }
 
-int mt352_read(struct dvb_frontend *fe, u8 reg)
-{
-       return mt352_read_register(fe->demodulator_priv,reg);
-}
-
 static int mt352_sleep(struct dvb_frontend* fe)
 {
        static u8 mt352_softdown[] = { CLOCK_CTL, 0x20, 0x08 };
@@ -134,8 +129,8 @@
                bw = 8;
                break;
        }
-       if (state->config->adc_clock)
-               adc_clock = state->config->adc_clock;
+       if (state->config.adc_clock)
+               adc_clock = state->config.adc_clock;
 
        value = 64 * bw * (1<<16) / (7 * 8);
        value = value * 1000 / adc_clock;
@@ -152,10 +147,10 @@
        int if2       = 36167; /* 36.166667 MHz */
        int ife,value;
 
-       if (state->config->adc_clock)
-               adc_clock = state->config->adc_clock;
-       if (state->config->if2)
-               if2 = state->config->if2;
+       if (state->config.adc_clock)
+               adc_clock = state->config.adc_clock;
+       if (state->config.if2)
+               if2 = state->config.if2;
 
        ife = (2*adc_clock - if2);
        value = -16374 * ife / adc_clock;
@@ -289,10 +284,10 @@
 
        mt352_calc_nominal_rate(state, op->bandwidth, buf+4);
        mt352_calc_input_freq(state, buf+6);
-       state->config->pll_set(fe, param, buf+8);
+       state->config.pll_set(fe, param, buf+8);
 
        mt352_write(fe, buf, sizeof(buf));
-       if (state->config->no_tuner) {
+       if (state->config.no_tuner) {
                /* start decoding */
                mt352_write(fe, fsm_go, 2);
        } else {
@@ -516,7 +511,7 @@
 
                /* Do a "hard" reset */
                mt352_write(fe, mt352_reset_attach, sizeof(mt352_reset_attach));
-               return state->config->demod_init(fe);
+               return state->config.demod_init(fe);
        }
 
        return 0;
@@ -541,8 +536,8 @@
        memset(state,0,sizeof(*state));
 
        /* setup the state */
-       state->config = config;
        state->i2c = i2c;
+       memcpy(&state->config,config,sizeof(struct mt352_config));
        memcpy(&state->ops, &mt352_ops, sizeof(struct dvb_frontend_ops));
 
        /* check if the demod is there */
@@ -601,10 +596,3 @@
 
 EXPORT_SYMBOL(mt352_attach);
 EXPORT_SYMBOL(mt352_write);
-EXPORT_SYMBOL(mt352_read);
-/*
- * Local variables:
- * c-basic-offset: 8
- * compile-command: "make DVB=1"
- * End:
- */
diff -urN linux/drivers/media/dvb/frontends/mt352.h 
linux/drivers/media/dvb/frontends/mt352.h
--- linux/drivers/media/dvb/frontends/mt352.h   2005/03/18 17:37:27     1.5
+++ linux/drivers/media/dvb/frontends/mt352.h   2005/05/26 09:12:43     1.6
@@ -61,12 +61,5 @@
                                         struct i2c_adapter* i2c);
 
 extern int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen);
-extern int mt352_read(struct dvb_frontend *fe, u8 reg);
 
 #endif // MT352_H
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff -urN linux/drivers/media/dvb/frontends/nxt2002.c 
linux/drivers/media/dvb/frontends/nxt2002.c
--- linux/drivers/media/dvb/frontends/nxt2002.c 2005/04/08 18:58:16     1.3
+++ linux/drivers/media/dvb/frontends/nxt2002.c 2005/05/26 09:12:43     1.4
@@ -241,7 +241,7 @@
 static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct 
firmware *fw)
 {
 
-       struct nxt2002_state* state = (struct nxt2002_state*) 
fe->demodulator_priv;
+       struct nxt2002_state* state = fe->demodulator_priv;
        u8 buf[256],written = 0,chunkpos = 0;
        u16 rambase,position,crc = 0;
 
@@ -309,7 +309,7 @@
 static int nxt2002_setup_frontend_parameters (struct dvb_frontend* fe,
                                             struct dvb_frontend_parameters *p)
 {
-       struct nxt2002_state* state = (struct nxt2002_state*) 
fe->demodulator_priv;
+       struct nxt2002_state* state = fe->demodulator_priv;
        u32 freq = 0;
        u16 tunerfreq = 0;
        u8 buf[4];
@@ -343,8 +343,6 @@
        /* reset the agc now that tuning has been completed */
        nxt2002_agc_reset(state);
 
-
-
        /* set target power level */
        switch (p->u.vsb.modulation) {
                case QAM_64:
@@ -453,7 +451,7 @@
 
 static int nxt2002_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
-       struct nxt2002_state* state = (struct nxt2002_state*) 
fe->demodulator_priv;
+       struct nxt2002_state* state = fe->demodulator_priv;
        u8 lock;
        i2c_readbytes(state,0x31,&lock,1);
 
@@ -470,7 +468,7 @@
 
 static int nxt2002_read_ber(struct dvb_frontend* fe, u32* ber)
 {
-       struct nxt2002_state* state = (struct nxt2002_state*) 
fe->demodulator_priv;
+       struct nxt2002_state* state = fe->demodulator_priv;
        u8 b[3];
 
        nxt2002_readreg_multibyte(state,0xE6,b,3);
@@ -482,7 +480,7 @@
 
 static int nxt2002_read_signal_strength(struct dvb_frontend* fe, u16* strength)
 {
-       struct nxt2002_state* state = (struct nxt2002_state*) 
fe->demodulator_priv;
+       struct nxt2002_state* state = fe->demodulator_priv;
        u8 b[2];
        u16 temp = 0;
 
@@ -502,7 +500,7 @@
 static int nxt2002_read_snr(struct dvb_frontend* fe, u16* snr)
 {
 
-       struct nxt2002_state* state = (struct nxt2002_state*) 
fe->demodulator_priv;
+       struct nxt2002_state* state = fe->demodulator_priv;
        u8 b[2];
        u16 temp = 0, temp2;
        u32 snrdb = 0;
@@ -536,7 +534,7 @@
 
 static int nxt2002_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 {
-       struct nxt2002_state* state = (struct nxt2002_state*) 
fe->demodulator_priv;
+       struct nxt2002_state* state = fe->demodulator_priv;
        u8 b[3];
 
        nxt2002_readreg_multibyte(state,0xE6,b,3);
@@ -552,7 +550,7 @@
 
 static int nxt2002_init(struct dvb_frontend* fe)
 {
-       struct nxt2002_state* state = (struct nxt2002_state*) 
fe->demodulator_priv;
+       struct nxt2002_state* state = fe->demodulator_priv;
        const struct firmware *fw;
        int ret;
        u8 buf[2];
@@ -624,7 +622,7 @@
 
 static void nxt2002_release(struct dvb_frontend* fe)
 {
-       struct nxt2002_state* state = (struct nxt2002_state*) 
fe->demodulator_priv;
+       struct nxt2002_state* state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -637,7 +635,7 @@
        u8 buf [] = {0,0,0,0,0};
 
        /* allocate memory for the internal state */
-       state = (struct nxt2002_state*) kmalloc(sizeof(struct nxt2002_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct nxt2002_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
diff -urN linux/drivers/media/dvb/frontends/nxt6000.c 
linux/drivers/media/dvb/frontends/nxt6000.c
--- linux/drivers/media/dvb/frontends/nxt6000.c 2005/04/08 18:58:16     1.12
+++ linux/drivers/media/dvb/frontends/nxt6000.c 2005/05/26 09:12:43     1.13
@@ -176,11 +176,16 @@
 
 static void nxt6000_setup(struct dvb_frontend* fe)
 {
-       struct nxt6000_state* state = (struct nxt6000_state*) 
fe->demodulator_priv;
+       struct nxt6000_state* state = fe->demodulator_priv;
 
        nxt6000_writereg(state, RS_COR_SYNC_PARAM, SYNC_PARAM);
        nxt6000_writereg(state, BER_CTRL, /*(1 << 2) | */ (0x01 << 1) | 0x01);
-       nxt6000_writereg(state, VIT_COR_CTL, VIT_COR_RESYNC);
+       nxt6000_writereg(state, VIT_BERTIME_2, 0x00);  // BER Timer = 0x000200 
* 256 = 131072 bits
+       nxt6000_writereg(state, VIT_BERTIME_1, 0x02);  //
+       nxt6000_writereg(state, VIT_BERTIME_0, 0x00);  //
+       nxt6000_writereg(state, VIT_COR_INTEN, 0x98); // Enable BER interrupts
+       nxt6000_writereg(state, VIT_COR_CTL, 0x82);   // Enable BER measurement
+       nxt6000_writereg(state, VIT_COR_CTL, VIT_COR_RESYNC | 0x02 );
        nxt6000_writereg(state, OFDM_COR_CTL, (0x01 << 5) | 
(nxt6000_readreg(state, OFDM_COR_CTL) & 0x0F));
        nxt6000_writereg(state, OFDM_COR_MODEGUARD, FORCEMODE8K | 0x02);
        nxt6000_writereg(state, OFDM_AGC_CTL, AGCLAST | INITIAL_AGC_BW);
@@ -422,7 +427,7 @@
 static int nxt6000_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
        u8 core_status;
-       struct nxt6000_state* state = (struct nxt6000_state*) 
fe->demodulator_priv;
+       struct nxt6000_state* state = fe->demodulator_priv;
 
        *status = 0;
 
@@ -451,7 +456,7 @@
 
 static int nxt6000_init(struct dvb_frontend* fe)
 {
-       struct nxt6000_state* state = (struct nxt6000_state*) 
fe->demodulator_priv;
+       struct nxt6000_state* state = fe->demodulator_priv;
 
        nxt6000_reset(state);
        nxt6000_setup(fe);
@@ -461,7 +466,7 @@
 
 static int nxt6000_set_frontend(struct dvb_frontend* fe, struct 
dvb_frontend_parameters *param)
 {
-       struct nxt6000_state* state = (struct nxt6000_state*) 
fe->demodulator_priv;
+       struct nxt6000_state* state = fe->demodulator_priv;
        int result;
 
        nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01);        /* open i2c bus 
switch */
@@ -482,10 +487,44 @@
 
 static void nxt6000_release(struct dvb_frontend* fe)
 {
-       struct nxt6000_state* state = (struct nxt6000_state*) 
fe->demodulator_priv;
+       struct nxt6000_state* state = fe->demodulator_priv;
        kfree(state);
 }
 
+static int nxt6000_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+       struct nxt6000_state* state = fe->demodulator_priv;
+
+       *snr = nxt6000_readreg( state, OFDM_CHC_SNR) / 8;
+
+       return 0;
+}
+
+static int nxt6000_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+       struct nxt6000_state* state = fe->demodulator_priv;
+
+       nxt6000_writereg( state, VIT_COR_INTSTAT, 0x18 );
+
+       *ber = (nxt6000_readreg( state, VIT_BER_1 ) << 8 ) |
+               nxt6000_readreg( state, VIT_BER_0 );
+
+       nxt6000_writereg( state, VIT_COR_INTSTAT, 0x18); // Clear BER Done 
interrupts
+
+       return 0;
+}
+
+static int nxt6000_read_signal_strength(struct dvb_frontend* fe, u16* 
signal_strength)
+{
+       struct nxt6000_state* state = fe->demodulator_priv;
+
+       *signal_strength = (short) (511 -
+               (nxt6000_readreg(state, AGC_GAIN_1) +
+               ((nxt6000_readreg(state, AGC_GAIN_2) & 0x03) << 8)));
+
+       return 0;
+}
+
 static struct dvb_frontend_ops nxt6000_ops;
 
 struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
@@ -494,7 +533,7 @@
        struct nxt6000_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = (struct nxt6000_state*) kmalloc(sizeof(struct nxt6000_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct nxt6000_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
@@ -542,6 +581,9 @@
        .set_frontend = nxt6000_set_frontend,
 
        .read_status = nxt6000_read_status,
+       .read_ber = nxt6000_read_ber,
+       .read_signal_strength = nxt6000_read_signal_strength,
+       .read_snr = nxt6000_read_snr,
 };
 
 module_param(debug, int, 0644);
diff -urN linux/drivers/media/dvb/frontends/nxt6000_priv.h 
linux/drivers/media/dvb/frontends/nxt6000_priv.h
--- linux/drivers/media/dvb/frontends/nxt6000_priv.h    2004/12/27 02:15:55     
1.1
+++ linux/drivers/media/dvb/frontends/nxt6000_priv.h    2005/05/26 09:12:43     
1.2
@@ -65,12 +65,27 @@
 #define BER_DONE               (0x08)
 #define BER_OVERFLOW           (0x10)
 
+/* 0x38 VIT_BERTIME_2 */
+#define VIT_BERTIME_2      (0x38)
+
+/* 0x39 VIT_BERTIME_1 */
+#define VIT_BERTIME_1      (0x39)
+
+/* 0x3A VIT_BERTIME_0 */
+#define VIT_BERTIME_0      (0x3a)
+
                             /* 0x38 OFDM_BERTimer *//* Use the alias registers 
*/
 #define A_VIT_BER_TIMER_0      (0x1D)
 
                             /* 0x3A VIT_BER_TIMER_0 *//* Use the alias 
registers */
 #define A_VIT_BER_0            (0x1B)
 
+/* 0x3B VIT_BER_1 */
+#define VIT_BER_1              (0x3b)
+
+/* 0x3C VIT_BER_0 */
+#define VIT_BER_0              (0x3c)
+
 /* 0x40 OFDM_COR_CTL */
 #define OFDM_COR_CTL           (0x40)
 #define COREACT                (0x20)
@@ -117,6 +132,12 @@
 #define OFDM_ITB_CTL           (0x4B)
 #define ITBINV                 (0x01)
 
+/* 0x49 AGC_GAIN_1 */
+#define AGC_GAIN_1             (0x49)
+
+/* 0x4A AGC_GAIN_2 */
+#define AGC_GAIN_2             (0x4A)
+
 /* 0x4C OFDM_ITB_FREQ_1 */
 #define OFDM_ITB_FREQ_1        (0x4C)
 
diff -urN linux/drivers/media/dvb/frontends/or51132.c 
linux/drivers/media/dvb/frontends/or51132.c
--- linux/drivers/media/dvb/frontends/or51132.c 2005/04/08 18:58:16     1.2
+++ linux/drivers/media/dvb/frontends/or51132.c 2005/05/26 09:12:43     1.3
@@ -102,7 +102,7 @@
 
 static int or51132_load_firmware (struct dvb_frontend* fe, const struct 
firmware *fw)
 {
-       struct or51132_state* state = (struct or51132_state*) 
fe->demodulator_priv;
+       struct or51132_state* state = fe->demodulator_priv;
        static u8 run_buf[] = {0x7F,0x01};
        static u8 get_ver_buf[] = {0x04,0x00,0x30,0x00,0x00};
        u8 rec_buf[14];
@@ -240,7 +240,7 @@
 
 static int or51132_setmode(struct dvb_frontend* fe)
 {
-       struct or51132_state* state = (struct or51132_state*) 
fe->demodulator_priv;
+       struct or51132_state* state = fe->demodulator_priv;
        unsigned char cmd_buf[4];
 
        dprintk("setmode %d\n",(int)state->current_modulation);
@@ -316,7 +316,7 @@
 {
        int ret;
        u8 buf[4];
-       struct or51132_state* state = (struct or51132_state*) 
fe->demodulator_priv;
+       struct or51132_state* state = fe->demodulator_priv;
        const struct firmware *fw;
 
        /* Change only if we are actually changing the modulation */
@@ -391,7 +391,7 @@
 
 static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
-       struct or51132_state* state = (struct or51132_state*) 
fe->demodulator_priv;
+       struct or51132_state* state = fe->demodulator_priv;
        unsigned char rec_buf[2];
        unsigned char snd_buf[2];
        *status = 0;
@@ -464,7 +464,7 @@
 
 static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength)
 {
-       struct or51132_state* state = (struct or51132_state*) 
fe->demodulator_priv;
+       struct or51132_state* state = fe->demodulator_priv;
        unsigned char rec_buf[2];
        unsigned char snd_buf[2];
        u8 rcvr_stat;
@@ -512,7 +512,7 @@
 
 static int or51132_read_snr(struct dvb_frontend* fe, u16* snr)
 {
-       struct or51132_state* state = (struct or51132_state*) 
fe->demodulator_priv;
+       struct or51132_state* state = fe->demodulator_priv;
        unsigned char rec_buf[2];
        unsigned char snd_buf[2];
        u16 snr_equ;
@@ -549,7 +549,7 @@
 
 static void or51132_release(struct dvb_frontend* fe)
 {
-       struct or51132_state* state = (struct or51132_state*) 
fe->demodulator_priv;
+       struct or51132_state* state = fe->demodulator_priv;
        kfree(state);
 }
 
diff -urN linux/drivers/media/dvb/frontends/sp8870.c 
linux/drivers/media/dvb/frontends/sp8870.c
--- linux/drivers/media/dvb/frontends/sp8870.c  2005/04/08 18:58:16     1.4
+++ linux/drivers/media/dvb/frontends/sp8870.c  2005/05/26 09:12:43     1.5
@@ -248,7 +248,7 @@
 static int sp8870_set_frontend_parameters (struct dvb_frontend* fe,
                                           struct dvb_frontend_parameters *p)
 {
-       struct sp8870_state* state = (struct sp8870_state*) 
fe->demodulator_priv;
+       struct sp8870_state* state = fe->demodulator_priv;
        int  err;
        u16 reg0xc05;
 
@@ -302,7 +302,7 @@
 
 static int sp8870_init (struct dvb_frontend* fe)
 {
-       struct sp8870_state* state = (struct sp8870_state*) 
fe->demodulator_priv;
+       struct sp8870_state* state = fe->demodulator_priv;
         const struct firmware *fw = NULL;
 
        sp8870_wake_up(state);
@@ -358,7 +358,7 @@
 
 static int sp8870_read_status (struct dvb_frontend* fe, fe_status_t * 
fe_status)
 {
-       struct sp8870_state* state = (struct sp8870_state*) 
fe->demodulator_priv;
+       struct sp8870_state* state = fe->demodulator_priv;
        int status;
        int signal;
 
@@ -384,7 +384,7 @@
 
 static int sp8870_read_ber (struct dvb_frontend* fe, u32 * ber)
 {
-       struct sp8870_state* state = (struct sp8870_state*) 
fe->demodulator_priv;
+       struct sp8870_state* state = fe->demodulator_priv;
        int ret;
        u32 tmp;
 
@@ -412,7 +412,7 @@
 
 static int sp8870_read_signal_strength(struct dvb_frontend* fe,  u16 * signal)
 {
-       struct sp8870_state* state = (struct sp8870_state*) 
fe->demodulator_priv;
+       struct sp8870_state* state = fe->demodulator_priv;
        int ret;
        u16 tmp;
 
@@ -438,7 +438,7 @@
 
 static int sp8870_read_uncorrected_blocks (struct dvb_frontend* fe, u32* 
ublocks)
 {
-       struct sp8870_state* state = (struct sp8870_state*) 
fe->demodulator_priv;
+       struct sp8870_state* state = fe->demodulator_priv;
        int ret;
 
        *ublocks = 0;
@@ -467,7 +467,7 @@
 
 static int sp8870_set_frontend (struct dvb_frontend* fe, struct 
dvb_frontend_parameters *p)
 {
-       struct sp8870_state* state = (struct sp8870_state*) 
fe->demodulator_priv;
+       struct sp8870_state* state = fe->demodulator_priv;
 
        /*
            The firmware of the sp8870 sometimes locks up after setting 
frontend parameters.
@@ -524,7 +524,7 @@
 
 static int sp8870_sleep(struct dvb_frontend* fe)
 {
-       struct sp8870_state* state = (struct sp8870_state*) 
fe->demodulator_priv;
+       struct sp8870_state* state = fe->demodulator_priv;
 
        // tristate TS output and disable interface pins
        return sp8870_writereg(state, 0xC18, 0x000);
@@ -540,7 +540,7 @@
 
 static void sp8870_release(struct dvb_frontend* fe)
 {
-       struct sp8870_state* state = (struct sp8870_state*) 
fe->demodulator_priv;
+       struct sp8870_state* state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -552,7 +552,7 @@
        struct sp8870_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = (struct sp8870_state*) kmalloc(sizeof(struct sp8870_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct sp8870_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
diff -urN linux/drivers/media/dvb/frontends/sp887x.c 
linux/drivers/media/dvb/frontends/sp887x.c
--- linux/drivers/media/dvb/frontends/sp887x.c  2005/04/08 18:58:16     1.13
+++ linux/drivers/media/dvb/frontends/sp887x.c  2005/05/26 09:12:43     1.14
@@ -135,7 +135,7 @@
  */
 static int sp887x_initial_setup (struct dvb_frontend* fe, const struct 
firmware *fw)
 {
-       struct sp887x_state* state = (struct sp887x_state*) 
fe->demodulator_priv;
+       struct sp887x_state* state = fe->demodulator_priv;
        u8 buf [BLOCKSIZE+2];
        int i;
        int fw_size = fw->size;
@@ -344,7 +344,7 @@
 static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
                                             struct dvb_frontend_parameters *p)
 {
-       struct sp887x_state* state = (struct sp887x_state*) 
fe->demodulator_priv;
+       struct sp887x_state* state = fe->demodulator_priv;
        int actual_freq, err;
        u16 val, reg0xc05;
 
@@ -405,7 +405,7 @@
 
 static int sp887x_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
-       struct sp887x_state* state = (struct sp887x_state*) 
fe->demodulator_priv;
+       struct sp887x_state* state = fe->demodulator_priv;
        u16 snr12 = sp887x_readreg(state, 0xf16);
        u16 sync0x200 = sp887x_readreg(state, 0x200);
        u16 sync0xf17 = sp887x_readreg(state, 0xf17);
@@ -439,7 +439,7 @@
 
 static int sp887x_read_ber(struct dvb_frontend* fe, u32* ber)
 {
-       struct sp887x_state* state = (struct sp887x_state*) 
fe->demodulator_priv;
+       struct sp887x_state* state = fe->demodulator_priv;
 
        *ber = (sp887x_readreg(state, 0xc08) & 0x3f) |
               (sp887x_readreg(state, 0xc07) << 6);
@@ -453,7 +453,7 @@
 
 static int sp887x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
 {
-       struct sp887x_state* state = (struct sp887x_state*) 
fe->demodulator_priv;
+       struct sp887x_state* state = fe->demodulator_priv;
 
        u16 snr12 = sp887x_readreg(state, 0xf16);
        u32 signal = 3 * (snr12 << 4);
@@ -464,7 +464,7 @@
 
 static int sp887x_read_snr(struct dvb_frontend* fe, u16* snr)
 {
-       struct sp887x_state* state = (struct sp887x_state*) 
fe->demodulator_priv;
+       struct sp887x_state* state = fe->demodulator_priv;
 
        u16 snr12 = sp887x_readreg(state, 0xf16);
        *snr = (snr12 << 4) | (snr12 >> 8);
@@ -474,7 +474,7 @@
 
 static int sp887x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 {
-       struct sp887x_state* state = (struct sp887x_state*) 
fe->demodulator_priv;
+       struct sp887x_state* state = fe->demodulator_priv;
 
        *ucblocks = sp887x_readreg(state, 0xc0c);
        if (*ucblocks == 0xfff)
@@ -485,7 +485,7 @@
 
 static int sp887x_sleep(struct dvb_frontend* fe)
 {
-       struct sp887x_state* state = (struct sp887x_state*) 
fe->demodulator_priv;
+       struct sp887x_state* state = fe->demodulator_priv;
 
        /* tristate TS output and disable interface pins */
        sp887x_writereg(state, 0xc18, 0x000);
@@ -495,7 +495,7 @@
 
 static int sp887x_init(struct dvb_frontend* fe)
 {
-       struct sp887x_state* state = (struct sp887x_state*) 
fe->demodulator_priv;
+       struct sp887x_state* state = fe->demodulator_priv;
         const struct firmware *fw = NULL;
        int ret;
 
@@ -534,7 +534,7 @@
 
 static void sp887x_release(struct dvb_frontend* fe)
 {
-       struct sp887x_state* state = (struct sp887x_state*) 
fe->demodulator_priv;
+       struct sp887x_state* state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -546,7 +546,7 @@
        struct sp887x_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = (struct sp887x_state*) kmalloc(sizeof(struct sp887x_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct sp887x_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
diff -urN linux/drivers/media/dvb/frontends/stv0297.c 
linux/drivers/media/dvb/frontends/stv0297.c
--- linux/drivers/media/dvb/frontends/stv0297.c 2005/04/08 18:58:16     1.4
+++ linux/drivers/media/dvb/frontends/stv0297.c 2005/05/26 09:12:43     1.5
@@ -365,7 +365,7 @@
 
 int stv0297_enable_plli2c(struct dvb_frontend *fe)
 {
-       struct stv0297_state *state = (struct stv0297_state *) 
fe->demodulator_priv;
+       struct stv0297_state *state = fe->demodulator_priv;
 
        stv0297_writereg(state, 0x87, 0x78);
        stv0297_writereg(state, 0x86, 0xc8);
@@ -375,7 +375,7 @@
 
 static int stv0297_init(struct dvb_frontend *fe)
 {
-       struct stv0297_state *state = (struct stv0297_state *) 
fe->demodulator_priv;
+       struct stv0297_state *state = fe->demodulator_priv;
        int i;
 
        /* soft reset */
@@ -416,7 +416,7 @@
 
 static int stv0297_sleep(struct dvb_frontend *fe)
 {
-       struct stv0297_state *state = (struct stv0297_state *) 
fe->demodulator_priv;
+       struct stv0297_state *state = fe->demodulator_priv;
 
        stv0297_writereg_mask(state, 0x80, 1, 1);
 
@@ -425,7 +425,7 @@
 
 static int stv0297_read_status(struct dvb_frontend *fe, fe_status_t * status)
 {
-       struct stv0297_state *state = (struct stv0297_state *) 
fe->demodulator_priv;
+       struct stv0297_state *state = fe->demodulator_priv;
 
        u8 sync = stv0297_readreg(state, 0xDF);
 
@@ -438,7 +438,7 @@
 
 static int stv0297_read_ber(struct dvb_frontend *fe, u32 * ber)
 {
-       struct stv0297_state *state = (struct stv0297_state *) 
fe->demodulator_priv;
+       struct stv0297_state *state = fe->demodulator_priv;
        u8 BER[3];
 
        stv0297_writereg(state, 0xA0, 0x80);    // Start Counting bit errors 
for 4096 Bytes
@@ -453,7 +453,7 @@
 
 static int stv0297_read_signal_strength(struct dvb_frontend *fe, u16 * 
strength)
 {
-       struct stv0297_state *state = (struct stv0297_state *) 
fe->demodulator_priv;
+       struct stv0297_state *state = fe->demodulator_priv;
        u8 STRENGTH[2];
 
        stv0297_readregs(state, 0x41, STRENGTH, 2);
@@ -464,7 +464,7 @@
 
 static int stv0297_read_snr(struct dvb_frontend *fe, u16 * snr)
 {
-       struct stv0297_state *state = (struct stv0297_state *) 
fe->demodulator_priv;
+       struct stv0297_state *state = fe->demodulator_priv;
        u8 SNR[2];
 
        stv0297_readregs(state, 0x07, SNR, 2);
@@ -475,7 +475,7 @@
 
 static int stv0297_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
 {
-       struct stv0297_state *state = (struct stv0297_state *) 
fe->demodulator_priv;
+       struct stv0297_state *state = fe->demodulator_priv;
 
        *ucblocks = (stv0297_readreg(state, 0xD5) << 8)
                | stv0297_readreg(state, 0xD4);
@@ -485,7 +485,7 @@
 
 static int stv0297_set_frontend(struct dvb_frontend *fe, struct 
dvb_frontend_parameters *p)
 {
-       struct stv0297_state *state = (struct stv0297_state *) 
fe->demodulator_priv;
+       struct stv0297_state *state = fe->demodulator_priv;
        int u_threshold;
        int initial_u;
        int blind_u;
@@ -689,7 +689,7 @@
 
 static int stv0297_get_frontend(struct dvb_frontend *fe, struct 
dvb_frontend_parameters *p)
 {
-       struct stv0297_state *state = (struct stv0297_state *) 
fe->demodulator_priv;
+       struct stv0297_state *state = fe->demodulator_priv;
        int reg_00, reg_83;
 
        reg_00 = stv0297_readreg(state, 0x00);
@@ -725,7 +725,7 @@
 
 static void stv0297_release(struct dvb_frontend *fe)
 {
-       struct stv0297_state *state = (struct stv0297_state *) 
fe->demodulator_priv;
+       struct stv0297_state *state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -737,7 +737,7 @@
        struct stv0297_state *state = NULL;
 
        /* allocate memory for the internal state */
-       state = (struct stv0297_state *) kmalloc(sizeof(struct stv0297_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct stv0297_state), GFP_KERNEL);
        if (state == NULL)
                goto error;
 
diff -urN linux/drivers/media/dvb/frontends/stv0299.c 
linux/drivers/media/dvb/frontends/stv0299.c
--- linux/drivers/media/dvb/frontends/stv0299.c 2005/04/08 18:58:16     1.17
+++ linux/drivers/media/dvb/frontends/stv0299.c 2005/05/26 09:12:43     1.18
@@ -70,6 +70,7 @@
 #define STATUS_UCBLOCKS 1
 
 static int debug;
+static int debug_legacy_dish_switch;
 #define dprintk(args...) \
        do { \
                if (debug) printk(KERN_DEBUG "stv0299: " args); \
@@ -93,7 +94,7 @@
 
 int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data)
 {
-        struct stv0299_state* state = (struct stv0299_state*) 
fe->demodulator_priv;
+        struct stv0299_state* state = fe->demodulator_priv;
 
        return stv0299_writeregI(state, reg, data);
 }
@@ -218,7 +219,7 @@
 
 static int stv0299_set_symbolrate (struct dvb_frontend* fe, u32 srate)
 {
-        struct stv0299_state* state = (struct stv0299_state*) 
fe->demodulator_priv;
+        struct stv0299_state* state = fe->demodulator_priv;
        u64 big = srate;
        u32 ratio;
 
@@ -269,7 +270,7 @@
 static int stv0299_send_diseqc_msg (struct dvb_frontend* fe,
                                    struct dvb_diseqc_master_cmd *m)
 {
-        struct stv0299_state* state = (struct stv0299_state*) 
fe->demodulator_priv;
+        struct stv0299_state* state = fe->demodulator_priv;
        u8 val;
        int i;
 
@@ -299,7 +300,7 @@
 
 static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, 
fe_sec_mini_cmd_t burst)
 {
-        struct stv0299_state* state = (struct stv0299_state*) 
fe->demodulator_priv;
+        struct stv0299_state* state = fe->demodulator_priv;
        u8 val;
 
        dprintk ("%s\n", __FUNCTION__);
@@ -326,7 +327,7 @@
 
 static int stv0299_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 {
-        struct stv0299_state* state = (struct stv0299_state*) 
fe->demodulator_priv;
+        struct stv0299_state* state = fe->demodulator_priv;
        u8 val;
 
        if (stv0299_wait_diseqc_idle (state, 100) < 0)
@@ -348,7 +349,7 @@
 
 static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t 
voltage)
 {
-        struct stv0299_state* state = (struct stv0299_state*) 
fe->demodulator_priv;
+        struct stv0299_state* state = fe->demodulator_priv;
        u8 reg0x08;
        u8 reg0x0c;
 
@@ -385,34 +386,84 @@
        };
 }
 
-static int stv0299_send_legacy_dish_cmd(struct dvb_frontend* fe, u32 cmd)
+static inline s32 stv0299_calc_usec_delay (struct timeval lasttime, struct 
timeval curtime)
 {
+       return ((curtime.tv_usec < lasttime.tv_usec) ?
+               1000000 - lasttime.tv_usec + curtime.tv_usec :
+               curtime.tv_usec - lasttime.tv_usec);
+}
+
+static void stv0299_sleep_until (struct timeval *waketime, u32 add_usec)
+{
+       struct timeval lasttime;
+       s32 delta, newdelta;
+
+       waketime->tv_usec += add_usec;
+       if (waketime->tv_usec >= 1000000) {
+               waketime->tv_usec -= 1000000;
+               waketime->tv_sec++;
+       }
+
+       do_gettimeofday (&lasttime);
+       delta = stv0299_calc_usec_delay (lasttime, *waketime);
+       if (delta > 2500) {
+               msleep ((delta - 1500) / 1000);
+               do_gettimeofday (&lasttime);
+               newdelta = stv0299_calc_usec_delay (lasttime, *waketime);
+               delta = (newdelta > delta) ? 0 : newdelta;
+       }
+       if (delta > 0)
+               udelay (delta);
+}
+
+static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
+{
+       struct stv0299_state* state = fe->demodulator_priv;
+       u8 reg0x08;
+       u8 reg0x0c;
+       u8 lv_mask = 0x40;
        u8 last = 1;
        int i;
+       struct timeval nexttime;
+       struct timeval tv[10];
 
-       /* reset voltage at the end
-       if((0x50 & stv0299_readreg (i2c, 0x0c)) == 0x50)
-               cmd |= 0x80;
-       else
-               cmd &= 0x7F;
-       */
+       reg0x08 = stv0299_readreg (state, 0x08);
+       reg0x0c = stv0299_readreg (state, 0x0c);
+       reg0x0c &= 0x0f;
+       stv0299_writeregI (state, 0x08, (reg0x08 & 0x3f) | 
(state->config->lock_output << 6));
+       if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0)
+               lv_mask = 0x10;
 
        cmd = cmd << 1;
-       dprintk("%s switch command: 0x%04x\n",__FUNCTION__, cmd);
+       if (debug_legacy_dish_switch)
+               printk ("%s switch command: 0x%04x\n",__FUNCTION__, cmd);
+
+       do_gettimeofday (&nexttime);
+       if (debug_legacy_dish_switch)
+               memcpy (&tv[0], &nexttime, sizeof (struct timeval));
+       stv0299_writeregI (state, 0x0c, reg0x0c | 0x50); /* set LNB to 18V */
 
-       stv0299_set_voltage(fe,SEC_VOLTAGE_18);
-       msleep(32);
+       stv0299_sleep_until (&nexttime, 32000);
 
        for (i=0; i<9; i++) {
+               if (debug_legacy_dish_switch)
+                       do_gettimeofday (&tv[i+1]);
                if((cmd & 0x01) != last) {
-                       stv0299_set_voltage(fe, last ? SEC_VOLTAGE_13 : 
SEC_VOLTAGE_18);
+                       /* set voltage to (last ? 13V : 18V) */
+                       stv0299_writeregI (state, 0x0c, reg0x0c | (last ? 
lv_mask : 0x50));
                        last = (last) ? 0 : 1;
                }
 
                cmd = cmd >> 1;
 
                if (i != 8)
-                       msleep(8);
+                       stv0299_sleep_until (&nexttime, 8000);
+       }
+       if (debug_legacy_dish_switch) {
+               printk ("%s(%d): switch delay (should be 32k followed by all 
8k\n",
+                       __FUNCTION__, fe->dvb->num);
+               for (i=1; i < 10; i++)
+                       printk ("%d: %d\n", i, stv0299_calc_usec_delay (tv[i-1] 
, tv[i]));
        }
 
        return 0;
@@ -420,7 +471,7 @@
 
 static int stv0299_init (struct dvb_frontend* fe)
 {
-        struct stv0299_state* state = (struct stv0299_state*) 
fe->demodulator_priv;
+        struct stv0299_state* state = fe->demodulator_priv;
        int i;
 
        dprintk("stv0299: init chip\n");
@@ -439,7 +490,7 @@
 
 static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
-        struct stv0299_state* state = (struct stv0299_state*) 
fe->demodulator_priv;
+        struct stv0299_state* state = fe->demodulator_priv;
 
        u8 signal = 0xff - stv0299_readreg (state, 0x18);
        u8 sync = stv0299_readreg (state, 0x1b);
@@ -467,7 +518,7 @@
 
 static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber)
 {
-        struct stv0299_state* state = (struct stv0299_state*) 
fe->demodulator_priv;
+        struct stv0299_state* state = fe->demodulator_priv;
 
        if (state->errmode != STATUS_BER) return 0;
        *ber = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 
0x1e);
@@ -477,7 +528,7 @@
 
 static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength)
 {
-        struct stv0299_state* state = (struct stv0299_state*) 
fe->demodulator_priv;
+        struct stv0299_state* state = fe->demodulator_priv;
 
        s32 signal =  0xffff - ((stv0299_readreg (state, 0x18) << 8)
                               | stv0299_readreg (state, 0x19));
@@ -494,7 +545,7 @@
 
 static int stv0299_read_snr(struct dvb_frontend* fe, u16* snr)
 {
-        struct stv0299_state* state = (struct stv0299_state*) 
fe->demodulator_priv;
+        struct stv0299_state* state = fe->demodulator_priv;
 
        s32 xsnr = 0xffff - ((stv0299_readreg (state, 0x24) << 8)
                           | stv0299_readreg (state, 0x25));
@@ -506,7 +557,7 @@
 
 static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 {
-        struct stv0299_state* state = (struct stv0299_state*) 
fe->demodulator_priv;
+        struct stv0299_state* state = fe->demodulator_priv;
 
        if (state->errmode != STATUS_UCBLOCKS) *ucblocks = 0;
        else *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg 
(state, 0x1e);
@@ -516,7 +567,7 @@
 
 static int stv0299_set_frontend(struct dvb_frontend* fe, struct 
dvb_frontend_parameters * p)
 {
-        struct stv0299_state* state = (struct stv0299_state*) 
fe->demodulator_priv;
+        struct stv0299_state* state = fe->demodulator_priv;
        int invval = 0;
 
        dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__);
@@ -584,7 +635,7 @@
 
 static int stv0299_get_frontend(struct dvb_frontend* fe, struct 
dvb_frontend_parameters * p)
 {
-        struct stv0299_state* state = (struct stv0299_state*) 
fe->demodulator_priv;
+        struct stv0299_state* state = fe->demodulator_priv;
        s32 derot_freq;
        int invval;
 
@@ -609,7 +660,7 @@
 
 static int stv0299_sleep(struct dvb_frontend* fe)
 {
-        struct stv0299_state* state = (struct stv0299_state*) 
fe->demodulator_priv;
+        struct stv0299_state* state = fe->demodulator_priv;
 
        stv0299_writeregI(state, 0x02, 0x80);
        state->initialised = 0;
@@ -619,7 +670,7 @@
 
 static int stv0299_get_tune_settings(struct dvb_frontend* fe, struct 
dvb_frontend_tune_settings* fesettings)
 {
-        struct stv0299_state* state = (struct stv0299_state*) 
fe->demodulator_priv;
+        struct stv0299_state* state = fe->demodulator_priv;
 
        fesettings->min_delay_ms = state->config->min_delay_ms;
        if (fesettings->parameters.u.qpsk.symbol_rate < 10000000) {
@@ -634,7 +685,7 @@
 
 static void stv0299_release(struct dvb_frontend* fe)
 {
-       struct stv0299_state* state = (struct stv0299_state*) 
fe->demodulator_priv;
+       struct stv0299_state* state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -647,7 +698,7 @@
        int id;
 
        /* allocate memory for the internal state */
-       state = (struct stv0299_state*) kmalloc(sizeof(struct stv0299_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct stv0299_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
@@ -719,6 +770,9 @@
        .dishnetwork_send_legacy_command = stv0299_send_legacy_dish_cmd,
 };
 
+module_param(debug_legacy_dish_switch, int, 0444);
+MODULE_PARM_DESC(debug_legacy_dish_switch, "Enable timing analysis for Dish 
Network legacy switches");
+
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
 
diff -urN linux/drivers/media/dvb/frontends/tda10021.c 
linux/drivers/media/dvb/frontends/tda10021.c
--- linux/drivers/media/dvb/frontends/tda10021.c        2005/04/08 18:58:16     
1.4
+++ linux/drivers/media/dvb/frontends/tda10021.c        2005/05/26 09:12:43     
1.5
@@ -205,7 +205,7 @@
 
 static int tda10021_init (struct dvb_frontend *fe)
 {
-       struct tda10021_state* state = (struct tda10021_state*) 
fe->demodulator_priv;
+       struct tda10021_state* state = fe->demodulator_priv;
        int i;
 
        dprintk("DVB: TDA10021(%d): init chip\n", fe->adapter->num);
@@ -238,7 +238,7 @@
 static int tda10021_set_parameters (struct dvb_frontend *fe,
                            struct dvb_frontend_parameters *p)
 {
-       struct tda10021_state* state = (struct tda10021_state*) 
fe->demodulator_priv;
+       struct tda10021_state* state = fe->demodulator_priv;
 
        //table for QAM4-QAM256 ready  QAM4  QAM16 QAM32 QAM64 QAM128 QAM256
        //CONF
@@ -278,7 +278,7 @@
 
 static int tda10021_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
-       struct tda10021_state* state = (struct tda10021_state*) 
fe->demodulator_priv;
+       struct tda10021_state* state = fe->demodulator_priv;
        int sync;
 
        *status = 0;
@@ -303,7 +303,7 @@
 
 static int tda10021_read_ber(struct dvb_frontend* fe, u32* ber)
 {
-       struct tda10021_state* state = (struct tda10021_state*) 
fe->demodulator_priv;
+       struct tda10021_state* state = fe->demodulator_priv;
 
        u32 _ber = tda10021_readreg(state, 0x14) |
                (tda10021_readreg(state, 0x15) << 8) |
@@ -315,7 +315,7 @@
 
 static int tda10021_read_signal_strength(struct dvb_frontend* fe, u16* 
strength)
 {
-       struct tda10021_state* state = (struct tda10021_state*) 
fe->demodulator_priv;
+       struct tda10021_state* state = fe->demodulator_priv;
 
        u8 gain = tda10021_readreg(state, 0x17);
        *strength = (gain << 8) | gain;
@@ -325,7 +325,7 @@
 
 static int tda10021_read_snr(struct dvb_frontend* fe, u16* snr)
 {
-       struct tda10021_state* state = (struct tda10021_state*) 
fe->demodulator_priv;
+       struct tda10021_state* state = fe->demodulator_priv;
 
        u8 quality = ~tda10021_readreg(state, 0x18);
        *snr = (quality << 8) | quality;
@@ -335,7 +335,7 @@
 
 static int tda10021_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 {
-       struct tda10021_state* state = (struct tda10021_state*) 
fe->demodulator_priv;
+       struct tda10021_state* state = fe->demodulator_priv;
 
        *ucblocks = tda10021_readreg (state, 0x13) & 0x7f;
        if (*ucblocks == 0x7f)
@@ -350,7 +350,7 @@
 
 static int tda10021_get_frontend(struct dvb_frontend* fe, struct 
dvb_frontend_parameters *p)
 {
-       struct tda10021_state* state = (struct tda10021_state*) 
fe->demodulator_priv;
+       struct tda10021_state* state = fe->demodulator_priv;
        int sync;
        s8 afc = 0;
 
@@ -378,7 +378,7 @@
 
 static int tda10021_sleep(struct dvb_frontend* fe)
 {
-       struct tda10021_state* state = (struct tda10021_state*) 
fe->demodulator_priv;
+       struct tda10021_state* state = fe->demodulator_priv;
 
        tda10021_writereg (state, 0x1b, 0x02);  /* pdown ADC */
        tda10021_writereg (state, 0x00, 0x80);  /* standby */
@@ -388,7 +388,7 @@
 
 static void tda10021_release(struct dvb_frontend* fe)
 {
-       struct tda10021_state* state = (struct tda10021_state*) 
fe->demodulator_priv;
+       struct tda10021_state* state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -401,7 +401,7 @@
        struct tda10021_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = (struct tda10021_state*) kmalloc(sizeof(struct tda10021_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct tda10021_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
diff -urN linux/drivers/media/dvb/frontends/tda1004x.c 
linux/drivers/media/dvb/frontends/tda1004x.c
--- linux/drivers/media/dvb/frontends/tda1004x.c        2005/04/08 18:58:16     
1.17
+++ linux/drivers/media/dvb/frontends/tda1004x.c        2005/05/26 09:12:43     
1.18
@@ -35,9 +35,10 @@
 #include "dvb_frontend.h"
 #include "tda1004x.h"
 
-#define TDA1004X_DEMOD_TDA10045 0
-#define TDA1004X_DEMOD_TDA10046 1
-
+enum tda1004x_demod {
+       TDA1004X_DEMOD_TDA10045,
+       TDA1004X_DEMOD_TDA10046,
+};
 
 struct tda1004x_state {
        struct i2c_adapter* i2c;
@@ -46,8 +47,9 @@
        struct dvb_frontend frontend;
 
        /* private demod data */
-       u8 initialised:1;
-       u8 demod_type;
+       u8 initialised;
+       enum tda1004x_demod demod_type;
+       u8 fw_version;
 };
 
 
@@ -139,7 +141,7 @@
 {
        int ret;
        u8 buf[] = { reg, data };
-       struct i2c_msg msg = { .addr=0, .flags=0, .buf=buf, .len=2 };
+       struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
 
        dprintk("%s: reg=0x%x, data=0x%x\n", __FUNCTION__, reg, data);
 
@@ -160,8 +162,8 @@
        int ret;
        u8 b0[] = { reg };
        u8 b1[] = { 0 };
-       struct i2c_msg msg[] = {{ .addr=0, .flags=0, .buf=b0, .len=1},
-                               { .addr=0, .flags=I2C_M_RD, .buf=b1, .len = 1}};
+       struct i2c_msg msg[] = {{ .flags = 0, .buf = b0, .len = 1 },
+                               { .flags = I2C_M_RD, .buf = b1, .len = 1 }};
 
        dprintk("%s: reg=0x%x\n", __FUNCTION__, reg);
 
@@ -294,7 +296,7 @@
                              u8 dspCodeCounterReg, u8 dspCodeInReg)
 {
        u8 buf[65];
-       struct i2c_msg fw_msg = {.addr = 0,.flags = 0,.buf = buf,.len = 0 };
+       struct i2c_msg fw_msg = { .flags = 0, .buf = buf, .len = 0 };
        int tx_size;
        int pos = 0;
 
@@ -304,12 +306,10 @@
 
        buf[0] = dspCodeInReg;
        while (pos != len) {
-
                // work out how much to send this time
                tx_size = len - pos;
-               if (tx_size > 0x10) {
+               if (tx_size > 0x10)
                        tx_size = 0x10;
-               }
 
                // send the chunk
                memcpy(buf + 1, mem + pos, tx_size);
@@ -322,6 +322,7 @@
 
                dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, pos);
        }
+
        return 0;
 }
 
@@ -335,9 +336,8 @@
 
        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 != dspVersion))
                return -EIO;
-       }
 
        return 0;
 }
@@ -348,9 +348,9 @@
        int ret;
        const struct firmware *fw;
 
-
        /* don't re-upload unless necessary */
-       if (tda1004x_check_upload_ok(state, 0x2c) == 0) return 0;
+       if (tda1004x_check_upload_ok(state, 0x2c) == 0)
+               return 0;
 
        /* request the firmware, this will block until someone uploads it */
        printk("tda1004x: waiting for firmware upload (%s)...\n", 
TDA10045_DEFAULT_FIRMWARE);
@@ -381,6 +381,25 @@
        return tda1004x_check_upload_ok(state, 0x2c);
 }
 
+static int tda10046_get_fw_version(struct tda1004x_state *state,
+                                  const struct firmware *fw)
+{
+       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;
+               }
+       }
+
+       return -EINVAL;
+}
+
 static int tda10046_fwupload(struct dvb_frontend* fe)
 {
        struct tda1004x_state* state = fe->demodulator_priv;
@@ -394,7 +413,8 @@
        msleep(100);
 
        /* don't re-upload unless necessary */
-       if (tda1004x_check_upload_ok(state, 0x20) == 0) return 0;
+       if (tda1004x_check_upload_ok(state, state->fw_version) == 0)
+               return 0;
 
        /* request the firmware, this will block until someone uploads it */
        printk("tda1004x: waiting for firmware upload (%s)...\n", 
TDA10046_DEFAULT_FIRMWARE);
@@ -404,9 +424,20 @@
                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, 0);
+       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);
@@ -419,7 +450,7 @@
 
        /* wait for DSP to initialise */
        timeout = jiffies + HZ;
-       while(!(tda1004x_read_byte(state, TDA1004X_STATUS_CD) & 0x20)) {
+       while (!(tda1004x_read_byte(state, TDA1004X_STATUS_CD) & 0x20)) {
                if (time_after(jiffies, timeout)) {
                        printk("tda1004x: DSP failed to initialised.\n");
                        return -EIO;
@@ -427,7 +458,7 @@
                msleep(1);
        }
 
-       return tda1004x_check_upload_ok(state, 0x20);
+       return tda1004x_check_upload_ok(state, state->fw_version);
 }
 
 static int tda1004x_encode_fec(int fec)
@@ -483,7 +514,8 @@
 
        dprintk("%s\n", __FUNCTION__);
 
-       if (state->initialised) return 0;
+       if (state->initialised)
+               return 0;
 
        if (tda10045_fwupload(fe)) {
                printk("tda1004x: firmware upload failed\n");
@@ -523,7 +555,8 @@
        struct tda1004x_state* state = fe->demodulator_priv;
        dprintk("%s\n", __FUNCTION__);
 
-       if (state->initialised) return 0;
+       if (state->initialised)
+               return 0;
 
        if (tda10046_fwupload(fe)) {
                printk("tda1004x: firmware upload failed\n");
@@ -545,7 +578,7 @@
        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, 0); // PLL P = N = 0
+       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); // }
@@ -621,12 +654,14 @@
 
                // set HP FEC
                tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_HP);
-               if (tmp < 0) return tmp;
+               if (tmp < 0)
+                       return tmp;
                tda1004x_write_mask(state, TDA1004X_IN_CONF2, 7, tmp);
 
                // set LP FEC
                tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_LP);
-               if (tmp < 0) return tmp;
+               if (tmp < 0)
+                       return tmp;
                tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x38, tmp << 3);
 
                // set constellation
@@ -671,7 +706,7 @@
        }
 
        // set bandwidth
-       switch(state->demod_type) {
+       switch (state->demod_type) {
        case TDA1004X_DEMOD_TDA10045:
                tda10045h_set_bandwidth(state, fe_params->u.ofdm.bandwidth);
                break;
@@ -683,7 +718,8 @@
 
        // set inversion
        inversion = fe_params->inversion;
-       if (state->config->invert) inversion = inversion ? INVERSION_OFF : 
INVERSION_ON;
+       if (state->config->invert)
+               inversion = inversion ? INVERSION_OFF : INVERSION_ON;
        switch (inversion) {
        case INVERSION_OFF:
                tda1004x_write_mask(state, TDA1004X_CONFC1, 0x20, 0);
@@ -750,19 +786,19 @@
        }
 
        // start the lock
-       switch(state->demod_type) {
+       switch (state->demod_type) {
        case TDA1004X_DEMOD_TDA10045:
                tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8);
                tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 0);
-               msleep(10);
                break;
 
        case TDA1004X_DEMOD_TDA10046:
                tda1004x_write_mask(state, TDA1004X_AUTO, 0x40, 0x40);
-               msleep(10);
                break;
        }
 
+       msleep(10);
+
        return 0;
 }
 
@@ -773,13 +809,13 @@
 
        // inversion status
        fe_params->inversion = INVERSION_OFF;
-       if (tda1004x_read_byte(state, TDA1004X_CONFC1) & 0x20) {
+       if (tda1004x_read_byte(state, TDA1004X_CONFC1) & 0x20)
                fe_params->inversion = INVERSION_ON;
-       }
-       if (state->config->invert) fe_params->inversion = fe_params->inversion 
? INVERSION_OFF : INVERSION_ON;
+       if (state->config->invert)
+               fe_params->inversion = fe_params->inversion ? INVERSION_OFF : 
INVERSION_ON;
 
        // bandwidth
-       switch(state->demod_type) {
+       switch (state->demod_type) {
        case TDA1004X_DEMOD_TDA10045:
                switch (tda1004x_read_byte(state, TDA10045H_WREF_LSB)) {
                case 0x14:
@@ -830,9 +866,8 @@
 
        // transmission mode
        fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
-       if (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x10) {
+       if (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x10)
                fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
-       }
 
        // guard interval
        switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x0c) >> 2) {
@@ -880,30 +915,33 @@
 
        // read status
        status = tda1004x_read_byte(state, TDA1004X_STATUS_CD);
-       if (status == -1) {
+       if (status == -1)
                return -EIO;
-       }
 
        // decode
        *fe_status = 0;
-       if (status & 4) *fe_status |= FE_HAS_SIGNAL;
-       if (status & 2) *fe_status |= FE_HAS_CARRIER;
-       if (status & 8) *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC | 
FE_HAS_LOCK;
+       if (status & 4)
+               *fe_status |= FE_HAS_SIGNAL;
+       if (status & 2)
+               *fe_status |= FE_HAS_CARRIER;
+       if (status & 8)
+               *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
 
        // if we don't already have VITERBI (i.e. not LOCKED), see if the 
viterbi
        // is getting anything valid
        if (!(*fe_status & FE_HAS_VITERBI)) {
                // read the CBER
                cber = tda1004x_read_byte(state, TDA1004X_CBER_LSB);
-               if (cber == -1) return -EIO;
+               if (cber == -1)
+                       return -EIO;
                status = tda1004x_read_byte(state, TDA1004X_CBER_MSB);
-               if (status == -1) return -EIO;
+               if (status == -1)
+                       return -EIO;
                cber |= (status << 8);
                tda1004x_read_byte(state, TDA1004X_CBER_RESET);
 
-               if (cber != 65535) {
+               if (cber != 65535)
                        *fe_status |= FE_HAS_VITERBI;
-               }
        }
 
        // if we DO have some valid VITERBI output, but don't already have SYNC
@@ -911,20 +949,22 @@
        if ((*fe_status & FE_HAS_VITERBI) && (!(*fe_status & FE_HAS_SYNC))) {
                // read the VBER
                vber = tda1004x_read_byte(state, TDA1004X_VBER_LSB);
-               if (vber == -1) return -EIO;
+               if (vber == -1)
+                       return -EIO;
                status = tda1004x_read_byte(state, TDA1004X_VBER_MID);
-               if (status == -1) return -EIO;
+               if (status == -1)
+                       return -EIO;
                vber |= (status << 8);
                status = tda1004x_read_byte(state, TDA1004X_VBER_MSB);
-               if (status == -1) return -EIO;
+               if (status == -1)
+                       return -EIO;
                vber |= ((status << 16) & 0x0f);
                tda1004x_read_byte(state, TDA1004X_CVBER_LUT);
 
                // if RS has passed some valid TS packets, then we must be
                // getting some SYNC bytes
-               if (vber < 16632) {
+               if (vber < 16632)
                        *fe_status |= FE_HAS_SYNC;
-               }
        }
 
        // success
@@ -941,7 +981,7 @@
        dprintk("%s\n", __FUNCTION__);
 
        // determine the register to use
-       switch(state->demod_type) {
+       switch (state->demod_type) {
        case TDA1004X_DEMOD_TDA10045:
                reg = TDA10045H_S_AGC;
                break;
@@ -972,9 +1012,8 @@
        tmp = tda1004x_read_byte(state, TDA1004X_SNR);
        if (tmp < 0)
                return -EIO;
-       if (tmp) {
+       if (tmp)
                tmp = 255 - tmp;
-       }
 
        *snr = ((tmp << 8) | tmp);
        dprintk("%s: snr=0x%x\n", __FUNCTION__, *snr);
@@ -1009,11 +1048,11 @@
                        break;
        }
 
-       if (tmp != 0x7f) {
+       if (tmp != 0x7f)
                *ucblocks = tmp;
-       } else {
+       else
                *ucblocks = 0xffffffff;
-       }
+
        dprintk("%s: ucblocks=0x%x\n", __FUNCTION__, *ucblocks);
        return 0;
 }
@@ -1027,10 +1066,12 @@
 
        // read it in
        tmp = tda1004x_read_byte(state, TDA1004X_CBER_LSB);
-       if (tmp < 0) return -EIO;
+       if (tmp < 0)
+               return -EIO;
        *ber = tmp << 1;
        tmp = tda1004x_read_byte(state, TDA1004X_CBER_MSB);
-       if (tmp < 0) return -EIO;
+       if (tmp < 0)
+               return -EIO;
        *ber |= (tmp << 9);
        tda1004x_read_byte(state, TDA1004X_CBER_RESET);
 
@@ -1042,7 +1083,7 @@
 {
        struct tda1004x_state* state = fe->demodulator_priv;
 
-       switch(state->demod_type) {
+       switch (state->demod_type) {
        case TDA1004X_DEMOD_TDA10045:
                tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0x10);
                break;
@@ -1066,74 +1107,11 @@
 
 static void tda1004x_release(struct dvb_frontend* fe)
 {
-       struct tda1004x_state* state = (struct tda1004x_state*) 
fe->demodulator_priv;
-       kfree(state);
-}
-
-static struct dvb_frontend_ops tda10045_ops;
-
-struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
-                                    struct i2c_adapter* i2c)
-{
-       struct tda1004x_state* state = NULL;
-
-       /* allocate memory for the internal state */
-       state = (struct tda1004x_state*) kmalloc(sizeof(struct tda1004x_state), 
GFP_KERNEL);
-       if (state == NULL) goto error;
-
-       /* setup the state */
-       state->config = config;
-       state->i2c = i2c;
-       memcpy(&state->ops, &tda10045_ops, sizeof(struct dvb_frontend_ops));
-       state->initialised = 0;
-       state->demod_type = TDA1004X_DEMOD_TDA10045;
-
-       /* check if the demod is there */
-       if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x25) goto error;
-
-       /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
-       state->frontend.demodulator_priv = state;
-       return &state->frontend;
-
-error:
+       struct tda1004x_state *state = fe->demodulator_priv;
        kfree(state);
-       return NULL;
-}
-
-static struct dvb_frontend_ops tda10046_ops;
-
-struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
-                                    struct i2c_adapter* i2c)
-{
-       struct tda1004x_state* state = NULL;
-
-       /* allocate memory for the internal state */
-       state = (struct tda1004x_state*) kmalloc(sizeof(struct tda1004x_state), 
GFP_KERNEL);
-       if (state == NULL) goto error;
-
-       /* setup the state */
-       state->config = config;
-       state->i2c = i2c;
-       memcpy(&state->ops, &tda10046_ops, sizeof(struct dvb_frontend_ops));
-       state->initialised = 0;
-       state->demod_type = TDA1004X_DEMOD_TDA10046;
-
-       /* check if the demod is there */
-       if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x46) goto error;
-
-       /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
-       state->frontend.demodulator_priv = state;
-       return &state->frontend;
-
-error:
-       if (state) kfree(state);
-       return NULL;
 }
 
 static struct dvb_frontend_ops tda10045_ops = {
-
        .info = {
                .name = "Philips TDA10045H DVB-T",
                .type = FE_OFDM,
@@ -1163,8 +1141,36 @@
        .read_ucblocks = tda1004x_read_ucblocks,
 };
 
-static struct dvb_frontend_ops tda10046_ops = {
+struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
+                                    struct i2c_adapter* i2c)
+{
+       struct tda1004x_state *state;
+
+       /* allocate memory for the internal state */
+       state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
+       if (!state)
+               return NULL;
 
+       /* setup the state */
+       state->config = config;
+       state->i2c = i2c;
+       memcpy(&state->ops, &tda10045_ops, sizeof(struct dvb_frontend_ops));
+       state->initialised = 0;
+       state->demod_type = TDA1004X_DEMOD_TDA10045;
+
+       /* check if the demod is there */
+       if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x25) {
+               kfree(state);
+               return NULL;
+       }
+
+       /* create dvb_frontend */
+       state->frontend.ops = &state->ops;
+       state->frontend.demodulator_priv = state;
+       return &state->frontend;
+}
+
+static struct dvb_frontend_ops tda10046_ops = {
        .info = {
                .name = "Philips TDA10046H DVB-T",
                .type = FE_OFDM,
@@ -1194,6 +1200,36 @@
        .read_ucblocks = tda1004x_read_ucblocks,
 };
 
+struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
+                                    struct i2c_adapter* i2c)
+{
+       struct tda1004x_state *state;
+
+       /* allocate memory for the internal state */
+       state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
+       if (!state)
+               return NULL;
+
+       /* setup the state */
+       state->config = config;
+       state->i2c = i2c;
+       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) {
+               kfree(state);
+               return NULL;
+       }
+
+       /* create dvb_frontend */
+       state->frontend.ops = &state->ops;
+       state->frontend.demodulator_priv = state;
+       return &state->frontend;
+}
+
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
 
diff -urN linux/drivers/media/dvb/frontends/tda1004x.h 
linux/drivers/media/dvb/frontends/tda1004x.h
--- linux/drivers/media/dvb/frontends/tda1004x.h        2004/12/27 02:15:55     
1.1
+++ linux/drivers/media/dvb/frontends/tda1004x.h        2005/05/26 09:12:43     
1.2
@@ -32,10 +32,13 @@
        u8 demod_address;
 
        /* does the "inversion" need inverted? */
-       u8 invert:1;
+       u8 invert;
 
        /* Does the OCLK signal need inverted? */
-       u8 invert_oclk:1;
+       u8 invert_oclk;
+
+       /* value of N_I2C of the CONF_PLL3 register */
+       u8 n_i2c;
 
        /* PLL maintenance */
        int (*pll_init)(struct dvb_frontend* fe);
diff -urN linux/drivers/media/dvb/frontends/tda8083.c 
linux/drivers/media/dvb/frontends/tda8083.c
--- linux/drivers/media/dvb/frontends/tda8083.c 2005/04/08 18:58:17     1.3
+++ linux/drivers/media/dvb/frontends/tda8083.c 2005/05/26 09:12:43     1.4
@@ -226,7 +226,7 @@
 static int tda8083_send_diseqc_msg (struct dvb_frontend* fe,
                                    struct dvb_diseqc_master_cmd *m)
 {
-       struct tda8083_state* state = (struct tda8083_state*) 
fe->demodulator_priv;
+       struct tda8083_state* state = fe->demodulator_priv;
        int i;
 
        tda8083_writereg (state, 0x29, (m->msg_len - 3) | (1 << 2)); /* enable 
*/
@@ -243,7 +243,7 @@
 
 static int tda8083_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
-       struct tda8083_state* state = (struct tda8083_state*) 
fe->demodulator_priv;
+       struct tda8083_state* state = fe->demodulator_priv;
 
        u8 signal = ~tda8083_readreg (state, 0x01);
        u8 sync = tda8083_readreg (state, 0x02);
@@ -270,7 +270,7 @@
 
 static int tda8083_read_signal_strength(struct dvb_frontend* fe, u16* strength)
 {
-       struct tda8083_state* state = (struct tda8083_state*) 
fe->demodulator_priv;
+       struct tda8083_state* state = fe->demodulator_priv;
 
        u8 signal = ~tda8083_readreg (state, 0x01);
        *strength = (signal << 8) | signal;
@@ -280,7 +280,7 @@
 
 static int tda8083_read_snr(struct dvb_frontend* fe, u16* snr)
 {
-       struct tda8083_state* state = (struct tda8083_state*) 
fe->demodulator_priv;
+       struct tda8083_state* state = fe->demodulator_priv;
 
        u8 _snr = tda8083_readreg (state, 0x08);
        *snr = (_snr << 8) | _snr;
@@ -290,7 +290,7 @@
 
 static int tda8083_set_frontend(struct dvb_frontend* fe, struct 
dvb_frontend_parameters *p)
 {
-       struct tda8083_state* state = (struct tda8083_state*) 
fe->demodulator_priv;
+       struct tda8083_state* state = fe->demodulator_priv;
 
        state->config->pll_set(fe, p);
        tda8083_set_inversion (state, p->inversion);
@@ -305,7 +305,7 @@
 
 static int tda8083_get_frontend(struct dvb_frontend* fe, struct 
dvb_frontend_parameters *p)
 {
-       struct tda8083_state* state = (struct tda8083_state*) 
fe->demodulator_priv;
+       struct tda8083_state* state = fe->demodulator_priv;
 
        /*  FIXME: get symbolrate & frequency offset...*/
        /*p->frequency = ???;*/
@@ -319,7 +319,7 @@
 
 static int tda8083_sleep(struct dvb_frontend* fe)
 {
-       struct tda8083_state* state = (struct tda8083_state*) 
fe->demodulator_priv;
+       struct tda8083_state* state = fe->demodulator_priv;
 
        tda8083_writereg (state, 0x00, 0x02);
        return 0;
@@ -327,7 +327,7 @@
 
 static int tda8083_init(struct dvb_frontend* fe)
 {
-       struct tda8083_state* state = (struct tda8083_state*) 
fe->demodulator_priv;
+       struct tda8083_state* state = fe->demodulator_priv;
        int i;
 
        for (i=0; i<44; i++)
@@ -343,7 +343,7 @@
 
 static int tda8083_diseqc_send_burst(struct dvb_frontend* fe, 
fe_sec_mini_cmd_t burst)
 {
-       struct tda8083_state* state = (struct tda8083_state*) 
fe->demodulator_priv;
+       struct tda8083_state* state = fe->demodulator_priv;
 
        tda8083_send_diseqc_burst (state, burst);
        tda8083_writereg (state, 0x00, 0x3c);
@@ -354,7 +354,7 @@
 
 static int tda8083_diseqc_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t 
tone)
 {
-       struct tda8083_state* state = (struct tda8083_state*) 
fe->demodulator_priv;
+       struct tda8083_state* state = fe->demodulator_priv;
 
        tda8083_set_tone (state, tone);
        tda8083_writereg (state, 0x00, 0x3c);
@@ -365,7 +365,7 @@
 
 static int tda8083_diseqc_set_voltage(struct dvb_frontend* fe, 
fe_sec_voltage_t voltage)
 {
-       struct tda8083_state* state = (struct tda8083_state*) 
fe->demodulator_priv;
+       struct tda8083_state* state = fe->demodulator_priv;
 
        tda8083_set_voltage (state, voltage);
        tda8083_writereg (state, 0x00, 0x3c);
@@ -376,7 +376,7 @@
 
 static void tda8083_release(struct dvb_frontend* fe)
 {
-       struct tda8083_state* state = (struct tda8083_state*) 
fe->demodulator_priv;
+       struct tda8083_state* state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -388,7 +388,7 @@
        struct tda8083_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = (struct tda8083_state*) kmalloc(sizeof(struct tda8083_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct tda8083_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
diff -urN linux/drivers/media/dvb/frontends/tda80xx.c 
linux/drivers/media/dvb/frontends/tda80xx.c
--- linux/drivers/media/dvb/frontends/tda80xx.c 2005/04/08 18:58:17     1.5
+++ linux/drivers/media/dvb/frontends/tda80xx.c 2005/05/26 09:12:43     1.6
@@ -27,7 +27,7 @@
 #include <linux/spinlock.h>
 #include <linux/threads.h>
 #include <linux/interrupt.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -400,7 +400,7 @@
 
 static int tda8044_init(struct dvb_frontend* fe)
 {
-       struct tda80xx_state* state = (struct tda80xx_state*) 
fe->demodulator_priv;
+       struct tda80xx_state* state = fe->demodulator_priv;
        int ret;
 
        /*
@@ -432,7 +432,7 @@
 
 static int tda8083_init(struct dvb_frontend* fe)
 {
-       struct tda80xx_state* state = (struct tda80xx_state*) 
fe->demodulator_priv;
+       struct tda80xx_state* state = fe->demodulator_priv;
 
        tda80xx_write(state, 0x00, tda8083_inittab, sizeof(tda8083_inittab));
 
@@ -447,7 +447,7 @@
 
 static int tda80xx_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t 
voltage)
 {
-       struct tda80xx_state* state = (struct tda80xx_state*) 
fe->demodulator_priv;
+       struct tda80xx_state* state = fe->demodulator_priv;
 
        switch (voltage) {
        case SEC_VOLTAGE_13:
@@ -463,7 +463,7 @@
 
 static int tda80xx_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 {
-       struct tda80xx_state* state = (struct tda80xx_state*) 
fe->demodulator_priv;
+       struct tda80xx_state* state = fe->demodulator_priv;
 
        switch (tone) {
        case SEC_TONE_OFF:
@@ -477,7 +477,7 @@
 
 static int tda80xx_send_diseqc_msg(struct dvb_frontend* fe, struct 
dvb_diseqc_master_cmd *cmd)
 {
-       struct tda80xx_state* state = (struct tda80xx_state*) 
fe->demodulator_priv;
+       struct tda80xx_state* state = fe->demodulator_priv;
 
        if (cmd->msg_len > 6)
                return -EINVAL;
@@ -492,7 +492,7 @@
 
 static int tda80xx_send_diseqc_burst(struct dvb_frontend* fe, 
fe_sec_mini_cmd_t cmd)
 {
-       struct tda80xx_state* state = (struct tda80xx_state*) 
fe->demodulator_priv;
+       struct tda80xx_state* state = fe->demodulator_priv;
 
        switch (cmd) {
        case SEC_MINI_A:
@@ -512,7 +512,7 @@
 
 static int tda80xx_sleep(struct dvb_frontend* fe)
 {
-       struct tda80xx_state* state = (struct tda80xx_state*) 
fe->demodulator_priv;
+       struct tda80xx_state* state = fe->demodulator_priv;
 
        tda80xx_writereg(state, 0x00, 0x02);    /* enter standby */
 
@@ -521,7 +521,7 @@
 
 static int tda80xx_set_frontend(struct dvb_frontend* fe, struct 
dvb_frontend_parameters *p)
 {
-       struct tda80xx_state* state = (struct tda80xx_state*) 
fe->demodulator_priv;
+       struct tda80xx_state* state = fe->demodulator_priv;
 
        tda80xx_writereg(state, 0x1c, 0x80);
        state->config->pll_set(fe, p);
@@ -537,7 +537,7 @@
 
 static int tda80xx_get_frontend(struct dvb_frontend* fe, struct 
dvb_frontend_parameters *p)
 {
-       struct tda80xx_state* state = (struct tda80xx_state*) 
fe->demodulator_priv;
+       struct tda80xx_state* state = fe->demodulator_priv;
 
        if (!state->config->irq)
                tda80xx_read_status_int(state);
@@ -550,7 +550,7 @@
 
 static int tda80xx_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
-       struct tda80xx_state* state = (struct tda80xx_state*) 
fe->demodulator_priv;
+       struct tda80xx_state* state = fe->demodulator_priv;
 
        if (!state->config->irq)
                tda80xx_read_status_int(state);
@@ -561,7 +561,7 @@
 
 static int tda80xx_read_ber(struct dvb_frontend* fe, u32* ber)
 {
-       struct tda80xx_state* state = (struct tda80xx_state*) 
fe->demodulator_priv;
+       struct tda80xx_state* state = fe->demodulator_priv;
        int ret;
        u8 buf[3];
 
@@ -575,7 +575,7 @@
 
 static int tda80xx_read_signal_strength(struct dvb_frontend* fe, u16* strength)
 {
-       struct tda80xx_state* state = (struct tda80xx_state*) 
fe->demodulator_priv;
+       struct tda80xx_state* state = fe->demodulator_priv;
 
        u8 gain = ~tda80xx_readreg(state, 0x01);
        *strength = (gain << 8) | gain;
@@ -585,7 +585,7 @@
 
 static int tda80xx_read_snr(struct dvb_frontend* fe, u16* snr)
 {
-       struct tda80xx_state* state = (struct tda80xx_state*) 
fe->demodulator_priv;
+       struct tda80xx_state* state = fe->demodulator_priv;
 
        u8 quality = tda80xx_readreg(state, 0x08);
        *snr = (quality << 8) | quality;
@@ -595,7 +595,7 @@
 
 static int tda80xx_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 {
-       struct tda80xx_state* state = (struct tda80xx_state*) 
fe->demodulator_priv;
+       struct tda80xx_state* state = fe->demodulator_priv;
 
        *ucblocks = tda80xx_readreg(state, 0x0f);
        if (*ucblocks == 0xff)
@@ -606,7 +606,7 @@
 
 static int tda80xx_init(struct dvb_frontend* fe)
 {
-       struct tda80xx_state* state = (struct tda80xx_state*) 
fe->demodulator_priv;
+       struct tda80xx_state* state = fe->demodulator_priv;
 
        switch(state->id) {
        case ID_TDA8044:
@@ -620,7 +620,7 @@
 
 static void tda80xx_release(struct dvb_frontend* fe)
 {
-       struct tda80xx_state* state = (struct tda80xx_state*) 
fe->demodulator_priv;
+       struct tda80xx_state* state = fe->demodulator_priv;
 
        if (state->config->irq)
                free_irq(state->config->irq, &state->worklet);
@@ -637,7 +637,7 @@
        int ret;
 
        /* allocate memory for the internal state */
-       state = (struct tda80xx_state*) kmalloc(sizeof(struct tda80xx_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct tda80xx_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
diff -urN linux/drivers/media/dvb/frontends/ves1820.c 
linux/drivers/media/dvb/frontends/ves1820.c
--- linux/drivers/media/dvb/frontends/ves1820.c 2005/04/08 18:58:17     1.17
+++ linux/drivers/media/dvb/frontends/ves1820.c 2005/05/26 09:12:43     1.18
@@ -70,7 +70,6 @@
                printk("ves1820: %s(): writereg error (reg == 0x%02x,"
                        "val == 0x%02x, ret == %i)\n", __FUNCTION__, reg, data, 
ret);
 
-       msleep(10);
        return (ret != 1) ? -EREMOTEIO : 0;
 }
 
@@ -193,7 +192,7 @@
 
 static int ves1820_init(struct dvb_frontend* fe)
 {
-       struct ves1820_state* state = (struct ves1820_state*) 
fe->demodulator_priv;
+       struct ves1820_state* state = fe->demodulator_priv;
        int i;
        int val;
 
@@ -214,7 +213,7 @@
 
 static int ves1820_set_parameters(struct dvb_frontend* fe, struct 
dvb_frontend_parameters *p)
 {
-       struct ves1820_state* state = (struct ves1820_state*) 
fe->demodulator_priv;
+       struct ves1820_state* state = fe->demodulator_priv;
        static const u8 reg0x00[] = { 0x00, 0x04, 0x08, 0x0c, 0x10 };
        static const u8 reg0x01[] = { 140, 140, 106, 100, 92 };
        static const u8 reg0x05[] = { 135, 100, 70, 54, 38 };
@@ -241,7 +240,7 @@
 
 static int ves1820_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
-       struct ves1820_state* state = (struct ves1820_state*) 
fe->demodulator_priv;
+       struct ves1820_state* state = fe->demodulator_priv;
        int sync;
 
        *status = 0;
@@ -267,7 +266,7 @@
 
 static int ves1820_read_ber(struct dvb_frontend* fe, u32* ber)
 {
-       struct ves1820_state* state = (struct ves1820_state*) 
fe->demodulator_priv;
+       struct ves1820_state* state = fe->demodulator_priv;
 
        u32 _ber = ves1820_readreg(state, 0x14) |
                        (ves1820_readreg(state, 0x15) << 8) |
@@ -279,7 +278,7 @@
 
 static int ves1820_read_signal_strength(struct dvb_frontend* fe, u16* strength)
 {
-       struct ves1820_state* state = (struct ves1820_state*) 
fe->demodulator_priv;
+       struct ves1820_state* state = fe->demodulator_priv;
 
        u8 gain = ves1820_readreg(state, 0x17);
        *strength = (gain << 8) | gain;
@@ -289,7 +288,7 @@
 
 static int ves1820_read_snr(struct dvb_frontend* fe, u16* snr)
 {
-       struct ves1820_state* state = (struct ves1820_state*) 
fe->demodulator_priv;
+       struct ves1820_state* state = fe->demodulator_priv;
 
        u8 quality = ~ves1820_readreg(state, 0x18);
        *snr = (quality << 8) | quality;
@@ -299,7 +298,7 @@
 
 static int ves1820_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 {
-       struct ves1820_state* state = (struct ves1820_state*) 
fe->demodulator_priv;
+       struct ves1820_state* state = fe->demodulator_priv;
 
        *ucblocks = ves1820_readreg(state, 0x13) & 0x7f;
        if (*ucblocks == 0x7f)
@@ -314,7 +313,7 @@
 
 static int ves1820_get_frontend(struct dvb_frontend* fe, struct 
dvb_frontend_parameters *p)
 {
-       struct ves1820_state* state = (struct ves1820_state*) 
fe->demodulator_priv;
+       struct ves1820_state* state = fe->demodulator_priv;
        int sync;
        s8 afc = 0;
 
@@ -345,7 +344,7 @@
 
 static int ves1820_sleep(struct dvb_frontend* fe)
 {
-       struct ves1820_state* state = (struct ves1820_state*) 
fe->demodulator_priv;
+       struct ves1820_state* state = fe->demodulator_priv;
 
        ves1820_writereg(state, 0x1b, 0x02);    /* pdown ADC */
        ves1820_writereg(state, 0x00, 0x80);    /* standby */
@@ -364,7 +363,7 @@
 
 static void ves1820_release(struct dvb_frontend* fe)
 {
-       struct ves1820_state* state = (struct ves1820_state*) 
fe->demodulator_priv;
+       struct ves1820_state* state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -377,7 +376,7 @@
        struct ves1820_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = (struct ves1820_state*) kmalloc(sizeof(struct ves1820_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct ves1820_state), GFP_KERNEL);
        if (state == NULL)
                goto error;
 
diff -urN linux/drivers/media/dvb/frontends/ves1x93.c 
linux/drivers/media/dvb/frontends/ves1x93.c
--- linux/drivers/media/dvb/frontends/ves1x93.c 2005/04/08 18:58:17     1.8
+++ linux/drivers/media/dvb/frontends/ves1x93.c 2005/05/26 09:12:43     1.9
@@ -263,7 +263,7 @@
 
 static int ves1x93_init (struct dvb_frontend* fe)
 {
-       struct ves1x93_state* state = (struct ves1x93_state*) 
fe->demodulator_priv;
+       struct ves1x93_state* state = fe->demodulator_priv;
        int i;
        int val;
 
@@ -289,7 +289,7 @@
 
 static int ves1x93_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t 
voltage)
 {
-       struct ves1x93_state* state = (struct ves1x93_state*) 
fe->demodulator_priv;
+       struct ves1x93_state* state = fe->demodulator_priv;
 
        switch (voltage) {
        case SEC_VOLTAGE_13:
@@ -305,7 +305,7 @@
 
 static int ves1x93_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
-       struct ves1x93_state* state = (struct ves1x93_state*) 
fe->demodulator_priv;
+       struct ves1x93_state* state = fe->demodulator_priv;
 
        u8 sync = ves1x93_readreg (state, 0x0e);
 
@@ -346,7 +346,7 @@
 
 static int ves1x93_read_ber(struct dvb_frontend* fe, u32* ber)
 {
-       struct ves1x93_state* state = (struct ves1x93_state*) 
fe->demodulator_priv;
+       struct ves1x93_state* state = fe->demodulator_priv;
 
        *ber = ves1x93_readreg (state, 0x15);
        *ber |= (ves1x93_readreg (state, 0x16) << 8);
@@ -358,7 +358,7 @@
 
 static int ves1x93_read_signal_strength(struct dvb_frontend* fe, u16* strength)
 {
-       struct ves1x93_state* state = (struct ves1x93_state*) 
fe->demodulator_priv;
+       struct ves1x93_state* state = fe->demodulator_priv;
 
        u8 signal = ~ves1x93_readreg (state, 0x0b);
        *strength = (signal << 8) | signal;
@@ -368,7 +368,7 @@
 
 static int ves1x93_read_snr(struct dvb_frontend* fe, u16* snr)
 {
-       struct ves1x93_state* state = (struct ves1x93_state*) 
fe->demodulator_priv;
+       struct ves1x93_state* state = fe->demodulator_priv;
 
        u8 _snr = ~ves1x93_readreg (state, 0x1c);
        *snr = (_snr << 8) | _snr;
@@ -378,7 +378,7 @@
 
 static int ves1x93_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 {
-       struct ves1x93_state* state = (struct ves1x93_state*) 
fe->demodulator_priv;
+       struct ves1x93_state* state = fe->demodulator_priv;
 
        *ucblocks = ves1x93_readreg (state, 0x18) & 0x7f;
 
@@ -393,7 +393,7 @@
 
 static int ves1x93_set_frontend(struct dvb_frontend* fe, struct 
dvb_frontend_parameters *p)
 {
-       struct ves1x93_state* state = (struct ves1x93_state*) 
fe->demodulator_priv;
+       struct ves1x93_state* state = fe->demodulator_priv;
 
        ves1x93_writereg(state, 0x00, 0x11);
        state->config->pll_set(fe, p);
@@ -408,7 +408,7 @@
 
 static int ves1x93_get_frontend(struct dvb_frontend* fe, struct 
dvb_frontend_parameters *p)
 {
-       struct ves1x93_state* state = (struct ves1x93_state*) 
fe->demodulator_priv;
+       struct ves1x93_state* state = fe->demodulator_priv;
        int afc;
 
        afc = ((int)((char)(ves1x93_readreg (state, 0x0a) << 1)))/2;
@@ -431,14 +431,14 @@
 
 static int ves1x93_sleep(struct dvb_frontend* fe)
 {
-       struct ves1x93_state* state = (struct ves1x93_state*) 
fe->demodulator_priv;
+       struct ves1x93_state* state = fe->demodulator_priv;
 
        return ves1x93_writereg (state, 0x00, 0x08);
 }
 
 static void ves1x93_release(struct dvb_frontend* fe)
 {
-       struct ves1x93_state* state = (struct ves1x93_state*) 
fe->demodulator_priv;
+       struct ves1x93_state* state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -451,7 +451,7 @@
        u8 identity;
 
        /* allocate memory for the internal state */
-       state = (struct ves1x93_state*) kmalloc(sizeof(struct ves1x93_state), 
GFP_KERNEL);
+       state = kmalloc(sizeof(struct ves1x93_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
diff -urN linux/drivers/media/dvb/ttpci/av7110.c 
linux/drivers/media/dvb/ttpci/av7110.c
--- linux/drivers/media/dvb/ttpci/av7110.c      2005/04/08 18:58:17     1.17
+++ linux/drivers/media/dvb/ttpci/av7110.c      2005/05/26 09:12:43     1.18
@@ -130,7 +130,7 @@
        av7110->current_input = 0;
        if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
                printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
-                       av7110->dvb_adapter->num);
+                       av7110->dvb_adapter.num);
                av7110->adac_type = DVB_ADAC_CRYSTAL;
                i2c_writereg(av7110, 0x20, 0x01, 0xd2);
                i2c_writereg(av7110, 0x20, 0x02, 0x49);
@@ -145,13 +145,13 @@
        }
        else if (dev->pci->subsystem_vendor == 0x110a) {
                printk("dvb-ttpci: DVB-C w/o analog module @ card %d 
detected\n",
-                       av7110->dvb_adapter->num);
+                       av7110->dvb_adapter.num);
                av7110->adac_type = DVB_ADAC_NONE;
        }
        else {
                av7110->adac_type = adac;
                printk("dvb-ttpci: adac type set to %d @ card %d\n",
-                       av7110->dvb_adapter->num, av7110->adac_type);
+                       av7110->dvb_adapter.num, av7110->adac_type);
        }
 
        if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == 
DVB_ADAC_MSP) {
@@ -231,7 +231,7 @@
 
                if (newloops == av7110->arm_loops) {
                        printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
-                              av7110->dvb_adapter->num);
+                              av7110->dvb_adapter.num);
 
                        arm_error(av7110);
                        av7710_set_video_mode(av7110, vidmode);
@@ -1282,7 +1282,7 @@
        av7110->dmxdev.demux = &dvbdemux->dmx;
        av7110->dmxdev.capabilities = 0;
 
-       dvb_dmxdev_init(&av7110->dmxdev, av7110->dvb_adapter);
+       dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter);
 
        av7110->hw_frontend.source = DMX_FRONTEND_0;
 
@@ -1307,11 +1307,11 @@
        av7110_ca_register(av7110);
 
 #ifdef CONFIG_DVB_AV7110_OSD
-       dvb_register_device(av7110->dvb_adapter, &av7110->osd_dev,
+       dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
                            &dvbdev_osd, av7110, DVB_DEVICE_OSD);
 #endif
 
-       dvb_net_init(av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
+       dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
 
        if (budgetpatch) {
                /* initialize software demux1 without its own frontend
@@ -1334,9 +1334,9 @@
                av7110->dmxdev1.demux = &dvbdemux1->dmx;
                av7110->dmxdev1.capabilities = 0;
 
-               dvb_dmxdev_init(&av7110->dmxdev1, av7110->dvb_adapter);
+               dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter);
 
-               dvb_net_init(av7110->dvb_adapter, &av7110->dvb_net1, 
&dvbdemux1->dmx);
+               dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, 
&dvbdemux1->dmx);
                printk("dvb-ttpci: additional demux1 for budget-patch 
registered\n");
        }
        return 0;
@@ -1673,6 +1673,106 @@
 };
 
 
+static u8 alps_bsbe1_inittab[] = {
+       0x01, 0x15,
+       0x02, 0x30,
+       0x03, 0x00,
+       0x04, 0x7d,   /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
+       0x05, 0x35,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
+       0x06, 0x40,   /* DAC not used, set to high impendance mode */
+       0x07, 0x00,   /* DAC LSB */
+       0x08, 0x40,   /* DiSEqC off, LNB power on OP2/LOCK pin on */
+       0x09, 0x00,   /* FIFO */
+       0x0c, 0x51,   /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
+       0x0d, 0x82,   /* DC offset compensation = ON, beta_agc1 = 2 */
+       0x0e, 0x23,   /* alpha_tmg = 2, beta_tmg = 3 */
+       0x10, 0x3f,   // AGC2  0x3d
+       0x11, 0x84,
+       0x12, 0xb5,   // Lock detect: -64  Carrier freq detect:on
+       0x15, 0xc9,   // lock detector threshold
+       0x16, 0x00,
+       0x17, 0x00,
+       0x18, 0x00,
+       0x19, 0x00,
+       0x1a, 0x00,
+       0x1f, 0x50,
+       0x20, 0x00,
+       0x21, 0x00,
+       0x22, 0x00,
+       0x23, 0x00,
+       0x28, 0x00,  // out imp: normal  out type: parallel FEC mode:0
+       0x29, 0x1e,  // 1/2 threshold
+       0x2a, 0x14,  // 2/3 threshold
+       0x2b, 0x0f,  // 3/4 threshold
+       0x2c, 0x09,  // 5/6 threshold
+       0x2d, 0x05,  // 7/8 threshold
+       0x2e, 0x01,
+       0x31, 0x1f,  // test all FECs
+       0x32, 0x19,  // viterbi and synchro search
+       0x33, 0xfc,  // rs control
+       0x34, 0x93,  // error control
+       0x0f, 0x92,
+       0xff, 0xff
+};
+
+static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct 
dvb_frontend_parameters* params)
+{
+       struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
+       int ret;
+       u8 data[4];
+       u32 div;
+       struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = 
sizeof(data) };
+
+       if ((params->frequency < 950000) || (params->frequency > 2150000))
+               return -EINVAL;
+
+       div = (params->frequency + (125 - 1)) / 125; // round correctly
+       data[0] = (div >> 8) & 0x7f;
+       data[1] = div & 0xff;
+       data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
+       data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
+
+       ret = i2c_transfer(&av7110->i2c_adap, &msg, 1);
+       return (ret != 1) ? -EIO : 0;
+}
+
+static struct stv0299_config alps_bsbe1_config = {
+       .demod_address = 0x68,
+       .inittab = alps_bsbe1_inittab,
+       .mclk = 88000000UL,
+       .invert = 1,
+       .enhanced_tuning = 0,
+       .skip_reinit = 0,
+       .min_delay_ms = 100,
+       .set_symbol_rate = alps_bsru6_set_symbol_rate,
+       .pll_set = alps_bsbe1_pll_set,
+};
+
+static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t 
voltage)
+{
+       struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
+       int ret;
+       u8 data[1];
+       struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = data, .len = 
sizeof(data) };
+
+       switch(voltage) {
+       case SEC_VOLTAGE_OFF:
+               data[0] = 0x00;
+               break;
+       case SEC_VOLTAGE_13:
+               data[0] = 0x44;
+               break;
+       case SEC_VOLTAGE_18:
+               data[0] = 0x4c;
+               break;
+       default:
+               return -EINVAL;
+       };
+
+       ret = i2c_transfer(&av7110->i2c_adap, &msg, 1);
+       return (ret != 1) ? -EIO : 0;
+}
+
 
 static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct 
dvb_frontend_parameters* params)
 {
@@ -2116,6 +2216,14 @@
                                av7110->dev->i2c_bitrate = 
SAA7146_I2C_BUS_BIT_RATE_240;
                                break;
                        }
+                       break;
+
+               case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
+                       /* ALPS BSBE1 */
+                       av7110->fe = stv0299_attach(&alps_bsbe1_config, 
&av7110->i2c_adap);
+                       if (av7110->fe)
+                               av7110->fe->ops->set_voltage = 
lnbp21_set_voltage;
+                       break;
                }
        }
 
@@ -2138,7 +2246,7 @@
                
FE_FUNC_OVERRIDE(av7110->fe->ops->dishnetwork_send_legacy_command, 
av7110->fe_dishnetwork_send_legacy_command, 
av7110_fe_dishnetwork_send_legacy_command);
                FE_FUNC_OVERRIDE(av7110->fe->ops->set_frontend, 
av7110->fe_set_frontend, av7110_fe_set_frontend);
 
-               ret = dvb_register_frontend(av7110->dvb_adapter, av7110->fe);
+               ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
                if (ret < 0) {
                        printk("av7110: Frontend registration failed!\n");
                        if (av7110->fe->ops->release)
@@ -2352,7 +2460,7 @@
                goto err_dvb_unregister_adapter_2;
 
        ttpci_eeprom_parse_mac(&av7110->i2c_adap,
-                              av7110->dvb_adapter->proposed_mac);
+                              av7110->dvb_adapter.proposed_mac);
        ret = -ENOMEM;
 
        if (budgetpatch) {
@@ -2523,7 +2631,7 @@
        if (ret < 0)
                goto err_av7110_unregister_11;
 
-       av7110->dvb_adapter->priv = av7110;
+       av7110->dvb_adapter.priv = av7110;
        ret = frontend_init(av7110);
        if (ret < 0)
                goto err_av7110_exit_v4l_12;
@@ -2558,7 +2666,7 @@
 err_i2c_del_3:
        i2c_del_adapter(&av7110->i2c_adap);
 err_dvb_unregister_adapter_2:
-       dvb_unregister_adapter(av7110->dvb_adapter);
+       dvb_unregister_adapter(&av7110->dvb_adapter);
 err_put_firmware_1:
        put_firmware(av7110);
 err_kfree_0:
@@ -2604,7 +2712,7 @@
 
        i2c_del_adapter(&av7110->i2c_adap);
 
-       dvb_unregister_adapter (av7110->dvb_adapter);
+       dvb_unregister_adapter (&av7110->dvb_adapter);
 
        av7110_num--;
 
@@ -2672,21 +2780,23 @@
 MAKE_AV7110_INFO(ttc_1_X,    "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
 MAKE_AV7110_INFO(ttc_2_X,    "Technotrend/Hauppauge WinTV DVB-C rev2.X");
 MAKE_AV7110_INFO(tts_2_X,    "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
+MAKE_AV7110_INFO(tts_2_3,    "Technotrend/Hauppauge WinTV Nexus-S rev2.3");
 MAKE_AV7110_INFO(tts_1_3se,  "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
 MAKE_AV7110_INFO(ttt,        "Technotrend/Hauppauge DVB-T");
 MAKE_AV7110_INFO(fsc,        "Fujitsu Siemens DVB-C");
 MAKE_AV7110_INFO(fss,        "Fujitsu Siemens DVB-S rev1.6");
 
 static struct pci_device_id pci_tbl[] = {
+       MAKE_EXTENSION_PCI(fsc,       0x110a, 0x0000),
        MAKE_EXTENSION_PCI(tts_1_X,   0x13c2, 0x0000),
        MAKE_EXTENSION_PCI(ttt_1_X,   0x13c2, 0x0001),
        MAKE_EXTENSION_PCI(ttc_2_X,   0x13c2, 0x0002),
        MAKE_EXTENSION_PCI(tts_2_X,   0x13c2, 0x0003),
-       MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
-       MAKE_EXTENSION_PCI(fsc,       0x110a, 0x0000),
-       MAKE_EXTENSION_PCI(ttc_1_X,   0x13c2, 0x000a),
        MAKE_EXTENSION_PCI(fss,       0x13c2, 0x0006),
        MAKE_EXTENSION_PCI(ttt,       0x13c2, 0x0008),
+       MAKE_EXTENSION_PCI(ttc_1_X,   0x13c2, 0x000a),
+       MAKE_EXTENSION_PCI(tts_2_3,   0x13c2, 0x000e),
+       MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
 
 /*     MAKE_EXTENSION_PCI(???, 0x13c2, 0x0004), UNDEFINED CARD */ // Galaxis 
DVB PC-Sat-Carte
 /*     MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat 
SkyStar1
diff -urN linux/drivers/media/dvb/ttpci/av7110.h 
linux/drivers/media/dvb/ttpci/av7110.h
--- linux/drivers/media/dvb/ttpci/av7110.h      2005/04/08 18:58:17     1.13
+++ linux/drivers/media/dvb/ttpci/av7110.h      2005/05/26 09:12:43     1.14
@@ -220,7 +220,7 @@
 
        struct audio_mixer      mixer;
 
-       struct dvb_adapter       *dvb_adapter;
+       struct dvb_adapter       dvb_adapter;
        struct dvb_device        *video_dev;
        struct dvb_device        *audio_dev;
        struct dvb_device        *ca_dev;
@@ -274,7 +274,6 @@
 extern int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val);
 extern u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg);
 extern int msp_writereg(struct av7110 *av7110, u8 dev, u16 reg, u16 val);
-extern int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val);
 
 
 extern int av7110_init_analog_module(struct av7110 *av7110);
diff -urN linux/drivers/media/dvb/ttpci/av7110_av.c 
linux/drivers/media/dvb/ttpci/av7110_av.c
--- linux/drivers/media/dvb/ttpci/av7110_av.c   2005/04/08 18:58:17     1.7
+++ linux/drivers/media/dvb/ttpci/av7110_av.c   2005/05/26 09:12:43     1.8
@@ -1075,7 +1075,7 @@
                }
                if (ret < 0)
                        break;
-               av7110->videostate.video_format = format;
+               av7110->videostate.display_format = format;
                ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetPanScanType,
                                    1, (u16) val);
                break;
@@ -1230,14 +1230,20 @@
                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);
                        break;
 
                case AUDIO_MONO_LEFT:
                        audcom(av7110, AUDIO_CMD_MONO_L);
+                       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);
                        break;
 
                default:
@@ -1409,10 +1415,10 @@
        av7110->video_events.overflow = 0;
        memset(&av7110->video_size, 0, sizeof (video_size_t));
 
-       dvb_register_device(av7110->dvb_adapter, &av7110->video_dev,
+       dvb_register_device(&av7110->dvb_adapter, &av7110->video_dev,
                            &dvbdev_video, av7110, DVB_DEVICE_VIDEO);
 
-       dvb_register_device(av7110->dvb_adapter, &av7110->audio_dev,
+       dvb_register_device(&av7110->dvb_adapter, &av7110->audio_dev,
                            &dvbdev_audio, av7110, DVB_DEVICE_AUDIO);
 
        return 0;
diff -urN linux/drivers/media/dvb/ttpci/av7110_ca.c 
linux/drivers/media/dvb/ttpci/av7110_ca.c
--- linux/drivers/media/dvb/ttpci/av7110_ca.c   2005/04/08 18:58:17     1.6
+++ linux/drivers/media/dvb/ttpci/av7110_ca.c   2005/05/26 09:12:43     1.7
@@ -123,7 +123,7 @@
 }
 
 static int ci_ll_reset(struct dvb_ringbuffer *cibuf, struct file *file,
-               int slots, ca_slot_info_t *slot)
+                      int slots, ca_slot_info_t *slot)
 {
        int i;
        int len = 0;
@@ -370,7 +370,7 @@
 
 int av7110_ca_register(struct av7110 *av7110)
 {
-       return dvb_register_device(av7110->dvb_adapter, &av7110->ca_dev,
+       return dvb_register_device(&av7110->dvb_adapter, &av7110->ca_dev,
                                   &dvbdev_ca, av7110, DVB_DEVICE_CA);
 }
 
diff -urN linux/drivers/media/dvb/ttpci/av7110_hw.c 
linux/drivers/media/dvb/ttpci/av7110_hw.c
--- linux/drivers/media/dvb/ttpci/av7110_hw.c   2005/03/18 17:37:27     1.11
+++ linux/drivers/media/dvb/ttpci/av7110_hw.c   2005/05/26 09:12:43     1.12
@@ -104,7 +104,7 @@
 
 
 /* av7110 ARM core boot stuff */
-
+#if 0
 void av7110_reset_arm(struct av7110 *av7110)
 {
        saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO);
@@ -124,7 +124,7 @@
        av7110->arm_ready = 1;
        dprintk(1, "reset ARM\n");
 }
-
+#endif  /*  0  */
 
 static int waitdebi(struct av7110 *av7110, int adr, int state)
 {
@@ -335,7 +335,7 @@
        return 0;
 }
 
-int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
+static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
 {
        int i;
        unsigned long start;
@@ -455,7 +455,7 @@
        return 0;
 }
 
-int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
+static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
 {
        int ret;
 
@@ -500,6 +500,7 @@
        return ret;
 }
 
+#if 0
 int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len)
 {
        int i, ret;
@@ -521,6 +522,7 @@
                printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", 
ret);
        return ret;
 }
+#endif  /*  0  */
 
 int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
                      int request_buf_len, u16 *reply_buf, int reply_buf_len)
@@ -593,7 +595,7 @@
        return 0;
 }
 
-int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length)
+static int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 
length)
 {
        int ret;
        ret = av7110_fw_request(av7110, &tag, 0, buf, length);
@@ -617,7 +619,7 @@
 
        if (av7110_fw_query(av7110, tag, buf, 16)) {
                printk("dvb-ttpci: failed to boot firmware @ card %d\n",
-                      av7110->dvb_adapter->num);
+                      av7110->dvb_adapter.num);
                return -EIO;
        }
 
@@ -628,16 +630,16 @@
        av7110->avtype = (buf[8] << 16) + buf[9];
 
        printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app 
%08x\n",
-              av7110->dvb_adapter->num, av7110->arm_fw,
+              av7110->dvb_adapter.num, av7110->arm_fw,
               av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app);
 
        /* print firmware capabilities */
        if (FW_CI_LL_SUPPORT(av7110->arm_app))
                printk("dvb-ttpci: firmware @ card %d supports CI link layer 
interface\n",
-                      av7110->dvb_adapter->num);
+                      av7110->dvb_adapter.num);
        else
                printk("dvb-ttpci: no firmware support for CI link layer 
interface @ card %d\n",
-                      av7110->dvb_adapter->num);
+                      av7110->dvb_adapter.num);
 
        return 0;
 }
diff -urN linux/drivers/media/dvb/ttpci/av7110_hw.h 
linux/drivers/media/dvb/ttpci/av7110_hw.h
--- linux/drivers/media/dvb/ttpci/av7110_hw.h   2004/12/27 02:15:57     1.5
+++ linux/drivers/media/dvb/ttpci/av7110_hw.h   2005/05/26 09:12:43     1.6
@@ -364,7 +364,6 @@
 
 
 
-extern void av7110_reset_arm(struct av7110 *av7110);
 extern int av7110_bootarm(struct av7110 *av7110);
 extern int av7110_firmversion(struct av7110 *av7110);
 #define FW_CI_LL_SUPPORT(arm_app) ((arm_app) & 0x80000000)
@@ -373,12 +372,8 @@
 
 extern int av7110_wait_msgstate(struct av7110 *av7110, u16 flags);
 extern int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, 
...);
-extern int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length);
-extern int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length);
-extern int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 
len);
 extern int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
                             int request_buf_len, u16 *reply_buf, int 
reply_buf_len);
-extern int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* Buff, s16 
length);
 
 
 /* DEBI (saa7146 data extension bus interface) access */
diff -urN linux/drivers/media/dvb/ttpci/av7110_ir.c 
linux/drivers/media/dvb/ttpci/av7110_ir.c
--- linux/drivers/media/dvb/ttpci/av7110_ir.c   2005/04/08 18:58:17     1.8
+++ linux/drivers/media/dvb/ttpci/av7110_ir.c   2005/05/26 09:12:43     1.9
@@ -10,7 +10,7 @@
 
 #define UP_TIMEOUT (HZ/4)
 
-/* enable ir debugging by or'ing av7110_debug with 16 */
+/* enable ir debugging by or'ing debug with 16 */
 
 static int ir_initialized;
 static struct input_dev input_dev;
diff -urN linux/drivers/media/dvb/ttpci/av7110_v4l.c 
linux/drivers/media/dvb/ttpci/av7110_v4l.c
--- linux/drivers/media/dvb/ttpci/av7110_v4l.c  2005/03/18 17:37:27     1.8
+++ linux/drivers/media/dvb/ttpci/av7110_v4l.c  2005/05/26 09:12:43     1.9
@@ -46,13 +46,13 @@
 
        if (i2c_transfer(&av7110->i2c_adap, &msgs, 1) != 1) {
                dprintk(1, "dvb-ttpci: failed @ card %d, %u = %u\n",
-                      av7110->dvb_adapter->num, reg, val);
+                      av7110->dvb_adapter.num, reg, val);
                return -EIO;
        }
        return 0;
 }
 
-int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val)
+static int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val)
 {
        u8 msg1[3] = { dev, reg >> 8, reg & 0xff };
        u8 msg2[2];
@@ -63,7 +63,7 @@
 
        if (i2c_transfer(&av7110->i2c_adap, &msgs[0], 2) != 2) {
                dprintk(1, "dvb-ttpci: failed @ card %d, %u\n",
-                      av7110->dvb_adapter->num, reg);
+                      av7110->dvb_adapter.num, reg);
                return -EIO;
        }
        *val = (msg2[0] << 8) | msg2[1];
@@ -552,13 +552,13 @@
                return -ENODEV;
 
        printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing 
MSP3400\n",
-               av7110->dvb_adapter->num);
+               av7110->dvb_adapter.num);
        av7110->adac_type = DVB_ADAC_MSP;
        msleep(100); // the probing above resets the msp...
        msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);
        msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);
        dprintk(1, "dvb-ttpci: @ card %d MSP3400 version 0x%04x 0x%04x\n",
-               av7110->dvb_adapter->num, version1, version2);
+               av7110->dvb_adapter.num, version1, version2);
        msp_writereg(av7110, MSP_WR_DSP, 0x0013, 0x0c00);
        msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + 
headphone
        msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source
@@ -596,7 +596,7 @@
                /* init the saa7113 */
                while (*i != 0xff) {
                        if (i2c_writereg(av7110, 0x48, i[0], i[1]) != 1) {
-                               dprintk(1, "saa7113 initialization failed @ 
card %d", av7110->dvb_adapter->num);
+                               dprintk(1, "saa7113 initialization failed @ 
card %d", av7110->dvb_adapter.num);
                                break;
                        }
                        i += 2;
@@ -726,11 +726,11 @@
 {
        struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
 
-       if (std->id == V4L2_STD_PAL) {
+       if (std->id & V4L2_STD_PAL) {
                av7110->vidmode = VIDEO_MODE_PAL;
                av7110_set_vidmode(av7110, av7110->vidmode);
        }
-       else if (std->id == V4L2_STD_NTSC) {
+       else if (std->id & V4L2_STD_NTSC) {
                av7110->vidmode = VIDEO_MODE_NTSC;
                av7110_set_vidmode(av7110, av7110->vidmode);
        }
diff -urN linux/drivers/media/dvb/ttpci/budget-av.c 
linux/drivers/media/dvb/ttpci/budget-av.c
--- linux/drivers/media/dvb/ttpci/budget-av.c   2005/04/08 18:58:17     1.11
+++ linux/drivers/media/dvb/ttpci/budget-av.c   2005/05/26 09:12:43     1.12
@@ -59,8 +59,12 @@
        struct dvb_ca_en50221 ca;
 };
 
-static int enable_ci = 0;
-
+/* GPIO CI Connections:
+ * 0 - Vcc/Reset (Reset is controlled by capacitor)
+ * 1 - Attribute Memory
+ * 2 - Card Enable (Active Low)
+ * 3 - Card Detect
+ */
 
 /****************************************************************************
  * INITIALIZATION
@@ -188,22 +192,35 @@
 {
        struct budget_av *budget_av = (struct budget_av *) ca->data;
        struct saa7146_dev *saa = budget_av->budget.dev;
-       int max = 20;
+       int timeout = 50; // 5 seconds (4.4.6 Ready)
 
        if (slot != 0)
                return -EINVAL;
 
        dprintk(1, "ciintf_slot_reset\n");
 
-       /* reset the card */
-       saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
-       msleep(100);
-       saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
+       saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
 
-       while (--max > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d)
+       saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
+       msleep(2);
+       saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); /* Vcc on */
+       msleep(20); /* 20 ms Vcc settling time */
+
+       saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */
+
+       /* This should have been based on pin 16 READY of the pcmcia port,
+        * but AFAICS it is not routed to the saa7146 */
+       while (--timeout > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d)
                msleep(100);
 
-       ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
+       if (timeout <= 0)
+       {
+               printk(KERN_ERR "budget-av: cam reset failed (timeout).\n");
+               saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
+               saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
+               return -ETIMEDOUT;
+       }
+
        return 0;
 }
 
@@ -240,7 +257,6 @@
 {
        struct budget_av *budget_av = (struct budget_av *) ca->data;
        struct saa7146_dev *saa = budget_av->budget.dev;
-       int cam = 0;
 
        if (slot != 0)
                return -EINVAL;
@@ -248,15 +264,21 @@
        if (!budget_av->slot_status) {
                saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
                udelay(1);
-               cam = saa7146_read(saa, PSR) & MASK_06;
-               saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
-
-               if (cam)
+               if (saa7146_read(saa, PSR) & MASK_06)
+               {
+                       printk(KERN_INFO "budget-av: cam inserted\n");
                        budget_av->slot_status = 1;
+               }
+               saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
        } else if (!open) {
                saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
                if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 
0, 1) == -ETIMEDOUT)
+               {
+                       printk(KERN_INFO "budget-av: cam ejected\n");
+                       saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable 
card */
+                       saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off 
*/
                        budget_av->slot_status = 0;
+               }
        }
 
        if (budget_av->slot_status == 1)
@@ -272,17 +294,11 @@
 
        memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221));
 
-       /* setup GPIOs */
-       saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
+       saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
+       saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
        saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO);
        saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
 
-       /* Reset the card */
-       saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
-       msleep(50);
-       saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
-       msleep(100);
-
        /* Enable DEBI pins */
        saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
 
@@ -297,13 +313,14 @@
        budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable;
        budget_av->ca.poll_slot_status = ciintf_poll_slot_status;
        budget_av->ca.data = budget_av;
-       if ((result = dvb_ca_en50221_init(budget_av->budget.dvb_adapter,
+
+       if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
                                          &budget_av->ca, 0, 1)) != 0) {
-               printk("budget_av: CI interface detected, but initialisation 
failed.\n");
+               printk(KERN_ERR "budget-av: ci initialisation failed.\n");
                goto error;
        }
-       // success!
-       printk("ciintf_init: CI interface initialised\n");
+
+       printk(KERN_INFO "budget-av: ci interface initialised.\n");
        budget_av->budget.ci_present = 1;
        return 0;
 
@@ -361,8 +378,12 @@
 static int saa7113_init(struct budget_av *budget_av)
 {
        struct budget *budget = &budget_av->budget;
+       struct saa7146_dev *saa = budget->dev;
        const u8 *data = saa7113_tab;
 
+       saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
+       msleep(200);
+
        if (i2c_writereg(&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) {
                dprintk(1, "saa7113 not found on KNC card\n");
                return -ENODEV;
@@ -697,75 +718,90 @@
        return pwm;
 }
 
+#define SUBID_DVBS_KNC1                0x0010
+#define SUBID_DVBS_KNC1_PLUS   0x0011
+#define SUBID_DVBS_TYPHOON     0x4f56
+#define SUBID_DVBS_CINERGY1200 0x1154
+
+#define SUBID_DVBC_KNC1                0x0020
+#define SUBID_DVBC_KNC1_PLUS   0x0021
+#define SUBID_DVBC_CINERGY1200 0x1156
+
+#define SUBID_DVBT_KNC1_PLUS   0x0031
+#define SUBID_DVBT_KNC1                0x0030
+#define SUBID_DVBT_CINERGY1200 0x1157
 
 static void frontend_init(struct budget_av *budget_av)
 {
-       switch (budget_av->budget.dev->pci->subsystem_device) {
-       case 0x4f56:            // Typhoon/KNC1 DVB-S budget (stv0299/Philips 
SU1278(tsa5059))
-               budget_av->budget.dvb_frontend =
-                       stv0299_attach(&typhoon_config, 
&budget_av->budget.i2c_adap);
-               if (budget_av->budget.dvb_frontend != NULL) {
+       struct saa7146_dev * saa = budget_av->budget.dev;
+       struct dvb_frontend * fe = NULL;
+
+       switch (saa->pci->subsystem_device) {
+               case SUBID_DVBS_KNC1_PLUS:
+               case SUBID_DVBC_KNC1_PLUS:
+               case SUBID_DVBT_KNC1_PLUS:
+                       // Enable / PowerON Frontend
+                       saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
                        break;
-               }
+       }
+
+       switch (saa->pci->subsystem_device) {
+
+       case SUBID_DVBS_KNC1:
+       case SUBID_DVBS_KNC1_PLUS:
+       case SUBID_DVBS_TYPHOON:
+               fe = stv0299_attach(&typhoon_config,
+                                   &budget_av->budget.i2c_adap);
                break;
 
-       case 0x0020:            // KNC1 DVB-C budget (tda10021/Philips 
CU1216(tua6034))
-               budget_av->budget.dvb_frontend =
-                       tda10021_attach(&philips_cu1216_config,
-                                       &budget_av->budget.i2c_adap, 
read_pwm(budget_av));
-               if (budget_av->budget.dvb_frontend != NULL) {
-                       break;
-               }
+       case SUBID_DVBS_CINERGY1200:
+               fe = stv0299_attach(&cinergy_1200s_config,
+                                   &budget_av->budget.i2c_adap);
                break;
 
-       case 0x0030:            // KNC1 DVB-T budget (tda10046/Philips 
TU1216(tda6651tt))
-               budget_av->budget.dvb_frontend =
-                       tda10046_attach(&philips_tu1216_config, 
&budget_av->budget.i2c_adap);
-               if (budget_av->budget.dvb_frontend != NULL) {
-                       break;
-               }
+       case SUBID_DVBC_KNC1:
+       case SUBID_DVBC_KNC1_PLUS:
+               fe = tda10021_attach(&philips_cu1216_config,
+                                    &budget_av->budget.i2c_adap,
+                                    read_pwm(budget_av));
                break;
 
-       case 0x1154:            // TerraTec Cinergy 1200 DVB-S (stv0299/Philips 
SU1278(tsa5059))
-               budget_av->budget.dvb_frontend =
-                       stv0299_attach(&cinergy_1200s_config, 
&budget_av->budget.i2c_adap);
-               if (budget_av->budget.dvb_frontend != NULL) {
-                       break;
-               }
+       case SUBID_DVBT_KNC1:
+       case SUBID_DVBT_KNC1_PLUS:
+               fe = tda10046_attach(&philips_tu1216_config,
+                                    &budget_av->budget.i2c_adap);
                break;
 
-       case 0x1156:            // Terratec Cinergy 1200 DVB-C 
(tda10021/Philips CU1216(tua6034))
-               budget_av->budget.dvb_frontend =
-                       tda10021_attach(&philips_cu1216_config,
-                                       &budget_av->budget.i2c_adap, 
read_pwm(budget_av));
-               if (budget_av->budget.dvb_frontend) {
-                       break;
-               }
+       case SUBID_DVBC_CINERGY1200:
+               fe = tda10021_attach(&philips_cu1216_config,
+                                    &budget_av->budget.i2c_adap,
+                                    read_pwm(budget_av));
                break;
 
-       case 0x1157:            // Terratec Cinergy 1200 DVB-T 
(tda10046/Philips TU1216(tda6651tt))
-               budget_av->budget.dvb_frontend =
-                       tda10046_attach(&philips_tu1216_config, 
&budget_av->budget.i2c_adap);
-               if (budget_av->budget.dvb_frontend) {
-                       break;
-               }
+       case SUBID_DVBT_CINERGY1200:
+               fe = tda10046_attach(&philips_tu1216_config,
+                                    &budget_av->budget.i2c_adap);
                break;
        }
 
-       if (budget_av->budget.dvb_frontend == NULL) {
-               printk("budget_av: A frontend driver was not found for device 
%04x/%04x subsystem %04x/%04x\n",
-                      budget_av->budget.dev->pci->vendor,
-                      budget_av->budget.dev->pci->device,
-                      budget_av->budget.dev->pci->subsystem_vendor,
-                      budget_av->budget.dev->pci->subsystem_device);
-       } else {
-               if (dvb_register_frontend
-                   (budget_av->budget.dvb_adapter, 
budget_av->budget.dvb_frontend)) {
-                       printk("budget-av: Frontend registration failed!\n");
-                       if (budget_av->budget.dvb_frontend->ops->release)
-                               
budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend);
-                       budget_av->budget.dvb_frontend = NULL;
-               }
+       if (fe == NULL) {
+               printk(KERN_ERR "budget-av: A frontend driver was not found "
+                               "for device %04x/%04x subsystem %04x/%04x\n",
+                      saa->pci->vendor,
+                      saa->pci->device,
+                      saa->pci->subsystem_vendor,
+                      saa->pci->subsystem_device);
+               return;
+       }
+
+       budget_av->budget.dvb_frontend = fe;
+
+       if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
+                                 budget_av->budget.dvb_frontend)) {
+               printk(KERN_ERR "budget-av: Frontend registration failed!\n");
+               if (budget_av->budget.dvb_frontend->ops->release)
+                       
budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend);
+               budget_av->budget.dvb_frontend = NULL;
        }
 }
 
@@ -822,6 +858,7 @@
 
        memset(budget_av, 0, sizeof(struct budget_av));
 
+       budget_av->has_saa7113 = 0;
        budget_av->budget.ci_present = 0;
 
        dev->ext_priv = budget_av;
@@ -836,10 +873,7 @@
        saa7146_write(dev, DD1_INIT, 0x07000600);
        saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26);
 
-       saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI);
-       msleep(500);
-
-       if (0 == saa7113_init(budget_av)) {
+       if (saa7113_init(budget_av) == 0) {
                budget_av->has_saa7113 = 1;
 
                if (0 != saa7146_vv_init(dev, &vv_data)) {
@@ -860,31 +894,26 @@
 
                saa7113_setinput(budget_av, 0);
        } else {
-               budget_av->has_saa7113 = 0;
-
-               saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
+               ciintf_init(budget_av);
        }
 
        /* fixme: find some sane values here... */
        saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
 
-       mac = budget_av->budget.dvb_adapter->proposed_mac;
+       mac = budget_av->budget.dvb_adapter.proposed_mac;
        if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) {
-               printk("KNC1-%d: Could not read MAC from KNC1 card\n",
-                      budget_av->budget.dvb_adapter->num);
+               printk(KERN_ERR "KNC1-%d: Could not read MAC from KNC1 card\n",
+                      budget_av->budget.dvb_adapter.num);
                memset(mac, 0, 6);
        } else {
-               printk("KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
-                      budget_av->budget.dvb_adapter->num,
+               printk(KERN_INFO "KNC1-%d: MAC addr = 
%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
+                      budget_av->budget.dvb_adapter.num,
                       mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
        }
 
-       budget_av->budget.dvb_adapter->priv = budget_av;
+       budget_av->budget.dvb_adapter.priv = budget_av;
        frontend_init(budget_av);
 
-       if (enable_ci)
-               ciintf_init(budget_av);
-
        return 0;
 }
 
@@ -963,14 +992,21 @@
 MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
 MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
 MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
+MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
+MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
+MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
 MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
 MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C);
 MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T);
 
 static struct pci_device_id pci_tbl[] = {
        MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
+       MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
+       MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
        MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
+       MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
        MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
+       MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031),
        MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154),
        MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156),
        MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157),
@@ -1010,5 +1046,3 @@
 MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
 MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
                   "budget PCI DVB w/ analog input and CI-module (e.g. the KNC 
cards)");
-module_param_named(enable_ci, enable_ci, int, 0644);
-MODULE_PARM_DESC(enable_ci, "Turn on/off CI module (default:off).");
diff -urN linux/drivers/media/dvb/ttpci/budget-ci.c 
linux/drivers/media/dvb/ttpci/budget-ci.c
--- linux/drivers/media/dvb/ttpci/budget-ci.c   2005/03/18 17:37:27     1.10
+++ linux/drivers/media/dvb/ttpci/budget-ci.c   2005/05/26 09:12:43     1.11
@@ -395,7 +395,7 @@
        budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
        budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
        budget_ci->ca.data = budget_ci;
-       if ((result = dvb_ca_en50221_init(budget_ci->budget.dvb_adapter,
+       if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
                                          &budget_ci->ca,
                                          DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
                                          DVB_CA_EN50221_FLAG_IRQ_FR |
@@ -881,7 +881,7 @@
                       budget_ci->budget.dev->pci->subsystem_device);
        } else {
                if (dvb_register_frontend
-                   (budget_ci->budget.dvb_adapter, 
budget_ci->budget.dvb_frontend)) {
+                   (&budget_ci->budget.dvb_adapter, 
budget_ci->budget.dvb_frontend)) {
                        printk("budget-ci: Frontend registration failed!\n");
                        if (budget_ci->budget.dvb_frontend->ops->release)
                                
budget_ci->budget.dvb_frontend->ops->release(budget_ci->budget.dvb_frontend);
@@ -916,7 +916,7 @@
 
        ciintf_init(budget_ci);
 
-       budget_ci->budget.dvb_adapter->priv = budget_ci;
+       budget_ci->budget.dvb_adapter.priv = budget_ci;
        frontend_init(budget_ci);
 
        return 0;
diff -urN linux/drivers/media/dvb/ttpci/budget-core.c 
linux/drivers/media/dvb/ttpci/budget-core.c
--- linux/drivers/media/dvb/ttpci/budget-core.c 2005/04/08 18:58:17     1.11
+++ linux/drivers/media/dvb/ttpci/budget-core.c 2005/05/26 09:12:43     1.12
@@ -298,7 +298,7 @@
        budget->dmxdev.demux = &dvbdemux->dmx;
        budget->dmxdev.capabilities = 0;
 
-       dvb_dmxdev_init(&budget->dmxdev, budget->dvb_adapter);
+       dvb_dmxdev_init(&budget->dmxdev, &budget->dvb_adapter);
 
        budget->hw_frontend.source = DMX_FRONTEND_0;
 
@@ -316,7 +316,7 @@
        if (ret < 0)
                return ret;
 
-       dvb_net_init(budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx);
+       dvb_net_init(&budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx);
 
        return 0;
 }
@@ -385,11 +385,11 @@
        strcpy(budget->i2c_adap.name, budget->card->name);
 
        if (i2c_add_adapter(&budget->i2c_adap) < 0) {
-               dvb_unregister_adapter(budget->dvb_adapter);
+               dvb_unregister_adapter(&budget->dvb_adapter);
                return -ENOMEM;
        }
 
-       ttpci_eeprom_parse_mac(&budget->i2c_adap, 
budget->dvb_adapter->proposed_mac);
+       ttpci_eeprom_parse_mac(&budget->i2c_adap, 
budget->dvb_adapter.proposed_mac);
 
        if (NULL ==
            (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, length, 
&budget->pt))) {
@@ -417,7 +417,7 @@
 
        vfree(budget->grabbing);
 
-       dvb_unregister_adapter(budget->dvb_adapter);
+       dvb_unregister_adapter(&budget->dvb_adapter);
 
        return ret;
 }
@@ -432,7 +432,7 @@
 
        i2c_del_adapter(&budget->i2c_adap);
 
-       dvb_unregister_adapter(budget->dvb_adapter);
+       dvb_unregister_adapter(&budget->dvb_adapter);
 
        tasklet_kill(&budget->vpe_tasklet);
 
diff -urN linux/drivers/media/dvb/ttpci/budget-patch.c 
linux/drivers/media/dvb/ttpci/budget-patch.c
--- linux/drivers/media/dvb/ttpci/budget-patch.c        2005/04/08 18:58:17     
1.11
+++ linux/drivers/media/dvb/ttpci/budget-patch.c        2005/05/26 09:12:43     
1.12
@@ -453,7 +453,7 @@
                       budget->dev->pci->subsystem_vendor,
                       budget->dev->pci->subsystem_device);
        } else {
-               if (dvb_register_frontend(budget->dvb_adapter, 
budget->dvb_frontend)) {
+               if (dvb_register_frontend(&budget->dvb_adapter, 
budget->dvb_frontend)) {
                        printk("budget-av: Frontend registration failed!\n");
                        if (budget->dvb_frontend->ops->release)
                                
budget->dvb_frontend->ops->release(budget->dvb_frontend);
@@ -702,7 +702,7 @@
 
         dev->ext_priv = budget;
 
-       budget->dvb_adapter->priv = budget;
+       budget->dvb_adapter.priv = budget;
        frontend_init(budget);
 
         return 0;
diff -urN linux/drivers/media/dvb/ttpci/budget.c 
linux/drivers/media/dvb/ttpci/budget.c
--- linux/drivers/media/dvb/ttpci/budget.c      2005/04/08 18:58:17     1.11
+++ linux/drivers/media/dvb/ttpci/budget.c      2005/05/26 09:12:43     1.12
@@ -468,7 +468,7 @@
                       budget->dev->pci->subsystem_vendor,
                       budget->dev->pci->subsystem_device);
        } else {
-               if (dvb_register_frontend(budget->dvb_adapter, 
budget->dvb_frontend)) {
+               if (dvb_register_frontend(&budget->dvb_adapter, 
budget->dvb_frontend)) {
                        printk("budget: Frontend registration failed!\n");
                        if (budget->dvb_frontend->ops->release)
                                
budget->dvb_frontend->ops->release(budget->dvb_frontend);
@@ -497,7 +497,7 @@
                return err;
        }
 
-       budget->dvb_adapter->priv = budget;
+       budget->dvb_adapter.priv = budget;
        frontend_init(budget);
 
        return 0;
diff -urN linux/drivers/media/dvb/ttpci/budget.h 
linux/drivers/media/dvb/ttpci/budget.h
--- linux/drivers/media/dvb/ttpci/budget.h      2005/03/18 17:37:27     1.8
+++ linux/drivers/media/dvb/ttpci/budget.h      2005/05/26 09:12:43     1.9
@@ -64,7 +64,7 @@
 
        spinlock_t debilock;
 
-       struct dvb_adapter *dvb_adapter;
+       struct dvb_adapter dvb_adapter;
        struct dvb_frontend *dvb_frontend;
        void *priv;
 };
@@ -92,6 +92,9 @@
 #define BUDGET_KNC1S              8
 #define BUDGET_KNC1C              9
 #define BUDGET_KNC1T              10
+#define BUDGET_KNC1SP             11
+#define BUDGET_KNC1CP             12
+#define BUDGET_KNC1TP             13
 
 #define BUDGET_VIDEO_PORTA         0
 #define BUDGET_VIDEO_PORTB         1
diff -urN linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c 
linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
--- linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c     2005/04/08 
18:58:17     1.15
+++ linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c     2005/05/26 
09:12:44     1.16
@@ -84,7 +84,7 @@
        struct semaphore semi2c;
        struct semaphore semusb;
 
-       struct dvb_adapter *adapter;
+       struct dvb_adapter adapter;
        struct usb_device *dev;
 
        struct i2c_adapter i2c_adap;
@@ -1065,7 +1065,7 @@
        return 0;
 }
 
-struct cx22700_config alps_tdmb7_config = {
+static struct cx22700_config alps_tdmb7_config = {
        .demod_address = 0x43,
        .pll_set = alps_tdmb7_pll_set,
 };
@@ -1412,7 +1412,7 @@
                       le16_to_cpu(ttusb->dev->descriptor.idVendor),
                       le16_to_cpu(ttusb->dev->descriptor.idProduct));
        } else {
-               if (dvb_register_frontend(ttusb->adapter, ttusb->fe)) {
+               if (dvb_register_frontend(&ttusb->adapter, ttusb->fe)) {
                        printk("dvb-ttusb-budget: Frontend registration 
failed!\n");
                        if (ttusb->fe->ops->release)
                                ttusb->fe->ops->release(ttusb->fe);
@@ -1462,7 +1462,7 @@
        up(&ttusb->semi2c);
 
        dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", 
THIS_MODULE);
-       ttusb->adapter->priv = ttusb;
+       ttusb->adapter.priv = ttusb;
 
        /* i2c */
        memset(&ttusb->i2c_adap, 0, sizeof(struct i2c_adapter));
@@ -1481,7 +1481,7 @@
 
        result = i2c_add_adapter(&ttusb->i2c_adap);
        if (result) {
-               dvb_unregister_adapter (ttusb->adapter);
+               dvb_unregister_adapter (&ttusb->adapter);
                return result;
        }
 
@@ -1503,7 +1503,7 @@
        if ((result = dvb_dmx_init(&ttusb->dvb_demux)) < 0) {
                printk("ttusb_dvb: dvb_dmx_init failed (errno = %d)\n", result);
                i2c_del_adapter(&ttusb->i2c_adap);
-               dvb_unregister_adapter (ttusb->adapter);
+               dvb_unregister_adapter (&ttusb->adapter);
                return -ENODEV;
        }
 //FIXME dmxdev (nur WAS?)
@@ -1511,21 +1511,21 @@
        ttusb->dmxdev.demux = &ttusb->dvb_demux.dmx;
        ttusb->dmxdev.capabilities = 0;
 
-       if ((result = dvb_dmxdev_init(&ttusb->dmxdev, ttusb->adapter)) < 0) {
+       if ((result = dvb_dmxdev_init(&ttusb->dmxdev, &ttusb->adapter)) < 0) {
                printk("ttusb_dvb: dvb_dmxdev_init failed (errno = %d)\n",
                       result);
                dvb_dmx_release(&ttusb->dvb_demux);
                i2c_del_adapter(&ttusb->i2c_adap);
-               dvb_unregister_adapter (ttusb->adapter);
+               dvb_unregister_adapter (&ttusb->adapter);
                return -ENODEV;
        }
 
-       if (dvb_net_init(ttusb->adapter, &ttusb->dvbnet, 
&ttusb->dvb_demux.dmx)) {
+       if (dvb_net_init(&ttusb->adapter, &ttusb->dvbnet, 
&ttusb->dvb_demux.dmx)) {
                printk("ttusb_dvb: dvb_net_init failed!\n");
                dvb_dmxdev_release(&ttusb->dmxdev);
                dvb_dmx_release(&ttusb->dvb_demux);
                i2c_del_adapter(&ttusb->i2c_adap);
-               dvb_unregister_adapter (ttusb->adapter);
+               dvb_unregister_adapter (&ttusb->adapter);
                return -ENODEV;
        }
 
@@ -1559,7 +1559,7 @@
        dvb_dmx_release(&ttusb->dvb_demux);
        if (ttusb->fe != NULL) dvb_unregister_frontend(ttusb->fe);
        i2c_del_adapter(&ttusb->i2c_adap);
-       dvb_unregister_adapter(ttusb->adapter);
+       dvb_unregister_adapter(&ttusb->adapter);
 
        ttusb_free_iso_urbs(ttusb);
 
diff -urN linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c 
linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c
--- linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c       2005/04/08 18:58:18     
1.19
+++ linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c       2005/05/26 09:12:44     
1.20
@@ -98,7 +98,7 @@
        int                             can_playback;
 
        /* DVB bits */
-       struct dvb_adapter              *adapter;
+       struct dvb_adapter              adapter;
        struct dmxdev                   dmxdev;
        struct dvb_demux                demux;
        struct dmx_frontend             frontend;
@@ -1435,7 +1435,7 @@
                printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
                       result);
 
-               dvb_unregister_adapter(dec->adapter);
+               dvb_unregister_adapter(&dec->adapter);
 
                return result;
        }
@@ -1444,12 +1444,12 @@
        dec->dmxdev.demux = &dec->demux.dmx;
        dec->dmxdev.capabilities = 0;
 
-       if ((result = dvb_dmxdev_init(&dec->dmxdev, dec->adapter)) < 0) {
+       if ((result = dvb_dmxdev_init(&dec->dmxdev, &dec->adapter)) < 0) {
                printk("%s: dvb_dmxdev_init failed: error %d\n",
                       __FUNCTION__, result);
 
                dvb_dmx_release(&dec->demux);
-               dvb_unregister_adapter(dec->adapter);
+               dvb_unregister_adapter(&dec->adapter);
 
                return result;
        }
@@ -1463,7 +1463,7 @@
 
                dvb_dmxdev_release(&dec->dmxdev);
                dvb_dmx_release(&dec->demux);
-               dvb_unregister_adapter(dec->adapter);
+               dvb_unregister_adapter(&dec->adapter);
 
                return result;
        }
@@ -1476,12 +1476,12 @@
                dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
                dvb_dmxdev_release(&dec->dmxdev);
                dvb_dmx_release(&dec->demux);
-               dvb_unregister_adapter(dec->adapter);
+               dvb_unregister_adapter(&dec->adapter);
 
                return result;
        }
 
-       dvb_net_init(dec->adapter, &dec->dvb_net, &dec->demux.dmx);
+       dvb_net_init(&dec->adapter, &dec->dvb_net, &dec->demux.dmx);
 
        return 0;
 }
@@ -1496,7 +1496,7 @@
        dvb_dmxdev_release(&dec->dmxdev);
        dvb_dmx_release(&dec->demux);
        if (dec->fe) dvb_unregister_frontend(dec->fe);
-       dvb_unregister_adapter(dec->adapter);
+       dvb_unregister_adapter(&dec->adapter);
 }
 
 static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
@@ -1565,15 +1565,15 @@
        }
 }
 
-int fe_send_command(struct dvb_frontend* fe, const u8 command,
-                   int param_length, const u8 params[],
-                   int *result_length, u8 cmd_result[])
+static int fe_send_command(struct dvb_frontend* fe, const u8 command,
+                          int param_length, const u8 params[],
+                          int *result_length, u8 cmd_result[])
 {
        struct ttusb_dec* dec = (struct ttusb_dec*) fe->dvb->priv;
        return ttusb_dec_send_command(dec, command, param_length, params, 
result_length, cmd_result);
 }
 
-struct ttusbdecfe_config fe_config = {
+static struct ttusbdecfe_config fe_config = {
        .send_command = fe_send_command
 };
 
@@ -1620,7 +1620,7 @@
        }
        ttusb_dec_init_dvb(dec);
 
-       dec->adapter->priv = dec;
+       dec->adapter.priv = dec;
        switch (le16_to_cpu(id->idProduct)) {
        case 0x1006:
                dec->fe = ttusbdecfe_dvbs_attach(&fe_config);
@@ -1637,7 +1637,7 @@
                       le16_to_cpu(dec->udev->descriptor.idVendor),
                       le16_to_cpu(dec->udev->descriptor.idProduct));
        } else {
-               if (dvb_register_frontend(dec->adapter, dec->fe)) {
+               if (dvb_register_frontend(&dec->adapter, dec->fe)) {
                        printk("budget-ci: Frontend registration failed!\n");
                        if (dec->fe->ops->release)
                                dec->fe->ops->release(dec->fe);
diff -urN linux/drivers/media/video/Kconfig linux/drivers/media/video/Kconfig
--- linux/drivers/media/video/Kconfig   2005/05/19 12:08:24     1.29
+++ linux/drivers/media/video/Kconfig   2005/05/26 09:12:44     1.30
@@ -248,6 +248,7 @@
        select VIDEO_BUF
        select VIDEO_IR
        select VIDEO_TUNER
+       select CRC32
        ---help---
          This is a video4linux driver for Philips SAA7130/7134 based
          TV cards.
diff -urN linux/drivers/media/video/bttv-cards.c 
linux/drivers/media/video/bttv-cards.c
--- linux/drivers/media/video/bttv-cards.c      2005/04/29 11:15:07     1.35
+++ linux/drivers/media/video/bttv-cards.c      2005/05/26 09:12:44     1.36
@@ -1946,7 +1946,6 @@
         .no_tda9875     = 1,
         .no_tda7432     = 1,
         .tuner_type     = TUNER_ABSENT,
-        .no_video       = 1,
        .pll            = PLL_28,
 },{
        .name           = "Teppro TEV-560/InterVision IV-560",
diff -urN linux/drivers/media/video/video-buf-dvb.c 
linux/drivers/media/video/video-buf-dvb.c
--- linux/drivers/media/video/video-buf-dvb.c   2005/02/07 02:54:48     1.2
+++ linux/drivers/media/video/video-buf-dvb.c   2005/05/26 09:12:44     1.3
@@ -149,10 +149,10 @@
                       dvb->name, result);
                goto fail_adapter;
        }
-       dvb->adapter->priv = adapter_priv;
+       dvb->adapter.priv = adapter_priv;
 
        /* register frontend */
-       result = dvb_register_frontend(dvb->adapter, dvb->frontend);
+       result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
        if (result < 0) {
                printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = 
%d)\n",
                       dvb->name, result);
@@ -178,7 +178,7 @@
        dvb->dmxdev.filternum    = 256;
        dvb->dmxdev.demux        = &dvb->demux.dmx;
        dvb->dmxdev.capabilities = 0;
-       result = dvb_dmxdev_init(&dvb->dmxdev, dvb->adapter);
+       result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
        if (result < 0) {
                printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
                       dvb->name, result);
@@ -209,7 +209,7 @@
        }
 
        /* register network adapter */
-       dvb_net_init(dvb->adapter, &dvb->net, &dvb->demux.dmx);
+       dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
        return 0;
 
 fail_fe_conn:
@@ -223,7 +223,7 @@
 fail_dmx:
        dvb_unregister_frontend(dvb->frontend);
 fail_frontend:
-       dvb_unregister_adapter(dvb->adapter);
+       dvb_unregister_adapter(&dvb->adapter);
 fail_adapter:
        return result;
 }
@@ -236,7 +236,7 @@
        dvb_dmxdev_release(&dvb->dmxdev);
        dvb_dmx_release(&dvb->demux);
        dvb_unregister_frontend(dvb->frontend);
-       dvb_unregister_adapter(dvb->adapter);
+       dvb_unregister_adapter(&dvb->adapter);
 }
 
 EXPORT_SYMBOL(videobuf_dvb_register);
diff -urN linux/drivers/media/video/saa7134/saa6752hs.c 
linux/drivers/media/video/saa7134/saa6752hs.c
--- linux/drivers/media/video/saa7134/saa6752hs.c       2005/05/19 12:08:25     
1.9
+++ linux/drivers/media/video/saa7134/saa6752hs.c       2005/05/26 09:12:44     
1.10
@@ -43,15 +43,15 @@
 static const struct v4l2_format v4l2_format_table[] =
 {
        [SAA6752HS_VF_D1] = {
-               .fmt.pix.width = 720, .fmt.pix.height = 576 },
+               .fmt = { .pix = { .width = 720, .height = 576 }, }, },
        [SAA6752HS_VF_2_3_D1] = {
-               .fmt.pix.width = 480, .fmt.pix.height = 576 },
+               .fmt = { .pix = { .width = 480, .height = 576 }, }, },
        [SAA6752HS_VF_1_2_D1] = {
-               .fmt.pix.width = 352, .fmt.pix.height = 576 },
+               .fmt = { .pix = { .width = 352, .height = 576 }, }, },
        [SAA6752HS_VF_SIF] = {
-               .fmt.pix.width = 352, .fmt.pix.height = 288 },
+               .fmt = { .pix = { .width = 352, .height = 288 }, }, },
        [SAA6752HS_VF_UNKNOWN] = {
-               .fmt.pix.width = 0, .fmt.pix.height = 0},
+               .fmt = { .pix = { .width = 0, .height = 0 }, }, },
 };
 
 struct saa6752hs_state {
diff -urN linux/drivers/mmc/Kconfig linux/drivers/mmc/Kconfig
--- linux/drivers/mmc/Kconfig   2005/05/19 12:08:25     1.4
+++ linux/drivers/mmc/Kconfig   2005/05/26 09:12:44     1.5
@@ -51,7 +51,7 @@
 
 config MMC_WBSD
        tristate "Winbond W83L51xD SD/MMC Card Interface support"
-       depends on MMC && ISA && ISA_DMA_API
+       depends on MMC && ISA_DMA_API
        help
          This selects the Winbond(R) W83L51xD Secure digital and
           Multimedia card Interface.
diff -urN linux/drivers/mmc/mmc_block.c linux/drivers/mmc/mmc_block.c
--- linux/drivers/mmc/mmc_block.c       2005/04/08 18:58:18     1.7
+++ linux/drivers/mmc/mmc_block.c       2005/05/26 09:12:44     1.8
@@ -383,7 +383,10 @@
        struct mmc_blk_data *md;
        int err;
 
-       if (card->csd.cmdclass & ~0x1ff)
+       /*
+        * Check that the card supports the command class(es) we need.
+        */
+       if (!(card->csd.cmdclass & CCC_BLOCK_READ))
                return -ENODEV;
 
        if (card->csd.read_blkbits < 9) {
diff -urN linux/drivers/mmc/wbsd.c linux/drivers/mmc/wbsd.c
--- linux/drivers/mmc/wbsd.c    2005/04/29 11:15:08     1.4
+++ linux/drivers/mmc/wbsd.c    2005/05/26 09:12:44     1.5
@@ -28,7 +28,9 @@
 #include <linux/ioport.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
 #include <linux/delay.h>
+#include <linux/pnp.h>
 #include <linux/highmem.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/protocol.h>
@@ -40,7 +42,7 @@
 #include "wbsd.h"
 
 #define DRIVER_NAME "wbsd"
-#define DRIVER_VERSION "1.1"
+#define DRIVER_VERSION "1.2"
 
 #ifdef CONFIG_MMC_DEBUG
 #define DBG(x...) \
@@ -52,10 +54,6 @@
 #define DBGF(x...)     do { } while (0)
 #endif
 
-static unsigned int io = 0x248;
-static unsigned int irq = 6;
-static int dma = 2;
-
 #ifdef CONFIG_MMC_DEBUG
 void DBG_REG(int reg, u8 value)
 {
@@ -79,28 +77,61 @@
 #endif
 
 /*
+ * Device resources
+ */
+
+#ifdef CONFIG_PNP
+
+static const struct pnp_device_id pnp_dev_table[] = {
+       { "WEC0517", 0 },
+       { "WEC0518", 0 },
+       { "", 0 },
+};
+
+MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
+
+#endif /* CONFIG_PNP */
+
+#ifdef CONFIG_PNP
+static unsigned int nopnp = 0;
+#else
+static const unsigned int nopnp = 1;
+#endif
+static unsigned int io = 0x248;
+static unsigned int irq = 6;
+static int dma = 2;
+
+/*
  * Basic functions
  */
 
 static inline void wbsd_unlock_config(struct wbsd_host* host)
 {
+       BUG_ON(host->config == 0);
+       
        outb(host->unlock_code, host->config);
        outb(host->unlock_code, host->config);
 }
 
 static inline void wbsd_lock_config(struct wbsd_host* host)
 {
+       BUG_ON(host->config == 0);
+       
        outb(LOCK_CODE, host->config);
 }
 
 static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value)
 {
+       BUG_ON(host->config == 0);
+       
        outb(reg, host->config);
        outb(value, host->config + 1);
 }
 
 static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg)
 {
+       BUG_ON(host->config == 0);
+       
        outb(reg, host->config);
        return inb(host->config + 1);
 }
@@ -133,6 +164,13 @@
        wbsd_write_index(host, WBSD_IDX_SETUP, setup);
        
        /*
+        * Set DAT3 to input
+        */
+       setup &= ~WBSD_DAT3_H;
+       wbsd_write_index(host, WBSD_IDX_SETUP, setup);
+       host->flags &= ~WBSD_FIGNORE_DETECT;
+       
+       /*
         * Read back default clock.
         */
        host->clk = wbsd_read_index(host, WBSD_IDX_CLK);
@@ -148,6 +186,14 @@
        wbsd_write_index(host, WBSD_IDX_TAAC, 0x7F);
        
        /*
+        * Test for card presence
+        */
+       if (inb(host->base + WBSD_CSR) & WBSD_CARDPRESENT)
+               host->flags |= WBSD_FCARD_PRESENT;
+       else
+               host->flags &= ~WBSD_FCARD_PRESENT;
+       
+       /*
         * Enable interesting interrupts.
         */
        ier = 0;
@@ -407,8 +453,6 @@
        }
 }
 
-static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs);
-
 static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
 {
        int i;
@@ -646,6 +690,13 @@
        }
        
        wbsd_kunmap_sg(host);
+       
+       /*
+        * The controller stops sending interrupts for
+        * 'FIFO empty' under certain conditions. So we
+        * need to be a bit more pro-active.
+        */
+       tasklet_schedule(&host->fifo_tasklet);
 }
 
 static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
@@ -850,9 +901,11 @@
        wbsd_request_end(host, host->mrq);
 }
 
-/*
- * MMC Callbacks
- */
+/*****************************************************************************\
+ *                                                                           *
+ * MMC layer callbacks                                                       *
+ *                                                                           *
+\*****************************************************************************/
 
 static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
 {
@@ -874,7 +927,7 @@
         * If there is no card in the slot then
         * timeout immediatly.
         */
-       if (!(inb(host->base + WBSD_CSR) & WBSD_CARDPRESENT))
+       if (!(host->flags & WBSD_FCARD_PRESENT))
        {
                cmd->error = MMC_ERR_TIMEOUT;
                goto done;
@@ -953,33 +1006,50 @@
                host->clk = clk;
        }
 
+       /*
+        * Power up card.
+        */
        if (ios->power_mode != MMC_POWER_OFF)
        {
-               /*
-                * Power up card.
-                */
                pwr = inb(host->base + WBSD_CSR);
                pwr &= ~WBSD_POWER_N;
                outb(pwr, host->base + WBSD_CSR);
-
-               /*
-                * This behaviour is stolen from the
-                * Windows driver. Don't know why, but
-                * it is needed.
-                */
-               setup = wbsd_read_index(host, WBSD_IDX_SETUP);
-               if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
-                       setup |= WBSD_DAT3_H;
-               else
-                       setup &= ~WBSD_DAT3_H;
-               wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-
-               mdelay(1);
        }
 
+       /*
+        * MMC cards need to have pin 1 high during init.
+        * Init time corresponds rather nicely with the bus mode.
+        * It wreaks havoc with the card detection though so
+        * that needs to be disabed.
+        */
+       setup = wbsd_read_index(host, WBSD_IDX_SETUP);
+       if ((ios->power_mode == MMC_POWER_ON) &&
+               (ios->bus_mode == MMC_BUSMODE_OPENDRAIN))
+       {
+               setup |= WBSD_DAT3_H;
+               host->flags |= WBSD_FIGNORE_DETECT;
+       }
+       else
+       {
+               setup &= ~WBSD_DAT3_H;
+               host->flags &= ~WBSD_FIGNORE_DETECT;
+       }
+       wbsd_write_index(host, WBSD_IDX_SETUP, setup);
+       
        spin_unlock_bh(&host->lock);
 }
 
+static struct mmc_host_ops wbsd_ops = {
+       .request        = wbsd_request,
+       .set_ios        = wbsd_set_ios,
+};
+
+/*****************************************************************************\
+ *                                                                           *
+ * Interrupt handling                                                        *
+ *                                                                           *
+\*****************************************************************************/
+
 /*
  * Tasklets
  */
@@ -1005,17 +1075,33 @@
 {
        struct wbsd_host* host = (struct wbsd_host*)param;
        u8 csr;
+       int change = 0;
        
        spin_lock(&host->lock);
        
+       if (host->flags & WBSD_FIGNORE_DETECT)
+       {
+               spin_unlock(&host->lock);
+               return;
+       }
+       
        csr = inb(host->base + WBSD_CSR);
        WARN_ON(csr == 0xff);
        
        if (csr & WBSD_CARDPRESENT)
-               DBG("Card inserted\n");
-       else
+       {
+               if (!(host->flags & WBSD_FCARD_PRESENT))
+               {
+                       DBG("Card inserted\n");
+                       host->flags |= WBSD_FCARD_PRESENT;
+                       change = 1;
+               }
+       }
+       else if (host->flags & WBSD_FCARD_PRESENT)
        {
                DBG("Card removed\n");
+               host->flags &= ~WBSD_FCARD_PRESENT;
+               change = 1;
                
                if (host->mrq)
                {
@@ -1033,7 +1119,8 @@
         */
        spin_unlock(&host->lock);
 
-       mmc_detect_change(host->mmc);
+       if (change)
+               mmc_detect_change(host->mmc);
 }
 
 static void wbsd_tasklet_fifo(unsigned long param)
@@ -1200,11 +1287,85 @@
        return IRQ_HANDLED;
 }
 
+/*****************************************************************************\
+ *                                                                           *
+ * Device initialisation and shutdown                                        *
+ *                                                                           *
+\*****************************************************************************/
+
 /*
- * Support functions for probe
+ * Allocate/free MMC structure.
  */
 
-static int wbsd_scan(struct wbsd_host* host)
+static int __devinit wbsd_alloc_mmc(struct device* dev)
+{
+       struct mmc_host* mmc;
+       struct wbsd_host* host;
+       
+       /*
+        * Allocate MMC structure.
+        */
+       mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev);
+       if (!mmc)
+               return -ENOMEM;
+       
+       host = mmc_priv(mmc);
+       host->mmc = mmc;
+
+       host->dma = -1;
+
+       /*
+        * Set host parameters.
+        */
+       mmc->ops = &wbsd_ops;
+       mmc->f_min = 375000;
+       mmc->f_max = 24000000;
+       mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
+       
+       spin_lock_init(&host->lock);
+       
+       /*
+        * Maximum number of segments. Worst case is one sector per segment
+        * so this will be 64kB/512.
+        */
+       mmc->max_hw_segs = 128;
+       mmc->max_phys_segs = 128;
+       
+       /*
+        * Maximum number of sectors in one transfer. Also limited by 64kB
+        * buffer.
+        */
+       mmc->max_sectors = 128;
+       
+       /*
+        * Maximum segment size. Could be one segment with the maximum number
+        * of segments.
+        */
+       mmc->max_seg_size = mmc->max_sectors * 512;
+       
+       dev_set_drvdata(dev, mmc);
+       
+       return 0;
+}
+
+static void __devexit wbsd_free_mmc(struct device* dev)
+{
+       struct mmc_host* mmc;
+       
+       mmc = dev_get_drvdata(dev);
+       if (!mmc)
+               return;
+       
+       mmc_free_host(mmc);
+       
+       dev_set_drvdata(dev, NULL);
+}
+
+/*
+ * Scan for known chip id:s
+ */
+
+static int __devinit wbsd_scan(struct wbsd_host* host)
 {
        int i, j, k;
        int id;
@@ -1258,12 +1419,16 @@
        return -ENODEV;
 }
 
-static int wbsd_request_regions(struct wbsd_host* host)
+/*
+ * Allocate/free io port ranges
+ */
+
+static int __devinit wbsd_request_region(struct wbsd_host* host, int base)
 {
        if (io & 0x7)
                return -EINVAL;
        
-       if (!request_region(io, 8, DRIVER_NAME))
+       if (!request_region(base, 8, DRIVER_NAME))
                return -EIO;
        
        host->base = io;
@@ -1271,19 +1436,25 @@
        return 0;
 }
 
-static void wbsd_release_regions(struct wbsd_host* host)
+static void __devexit wbsd_release_regions(struct wbsd_host* host)
 {
        if (host->base)
                release_region(host->base, 8);
+       
+       host->base = 0;
 
        if (host->config)
                release_region(host->config, 2);
+       
+       host->config = 0;
 }
 
-static void wbsd_init_dma(struct wbsd_host* host)
+/*
+ * Allocate/free DMA port and buffer
+ */
+
+static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
 {
-       host->dma = -1;
-       
        if (dma < 0)
                return;
        
@@ -1294,7 +1465,7 @@
         * We need to allocate a special buffer in
         * order for ISA to be able to DMA to it.
         */
-       host->dma_buffer = kmalloc(65536,
+       host->dma_buffer = kmalloc(WBSD_DMA_SIZE,
                GFP_NOIO | GFP_DMA | __GFP_REPEAT | __GFP_NOWARN);
        if (!host->dma_buffer)
                goto free;
@@ -1302,7 +1473,8 @@
        /*
         * Translate the address to a physical address.
         */
-       host->dma_addr = isa_virt_to_bus(host->dma_buffer);
+       host->dma_addr = dma_map_single(host->mmc->dev, host->dma_buffer,
+               WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
                        
        /*
         * ISA DMA must be aligned on a 64k basis.
@@ -1325,6 +1497,10 @@
         */
        BUG_ON(1);
        
+       dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE,
+               DMA_BIDIRECTIONAL);
+       host->dma_addr = (dma_addr_t)NULL;
+       
        kfree(host->dma_buffer);
        host->dma_buffer = NULL;
 
@@ -1336,60 +1512,122 @@
                "Falling back on FIFO.\n", dma);
 }
 
-static struct mmc_host_ops wbsd_ops = {
-       .request        = wbsd_request,
-       .set_ios        = wbsd_set_ios,
-};
+static void __devexit wbsd_release_dma(struct wbsd_host* host)
+{
+       if (host->dma_addr)
+               dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE,
+                       DMA_BIDIRECTIONAL);
+       if (host->dma_buffer)
+               kfree(host->dma_buffer);
+       if (host->dma >= 0)
+               free_dma(host->dma);
+       
+       host->dma = -1;
+       host->dma_buffer = NULL;
+       host->dma_addr = (dma_addr_t)NULL;
+}
 
 /*
- * Device probe
+ * Allocate/free IRQ.
  */
 
-static int wbsd_probe(struct device* dev)
+static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
 {
-       struct wbsd_host* host = NULL;
-       struct mmc_host* mmc = NULL;
        int ret;
        
        /*
-        * Allocate MMC structure.
+        * Allocate interrupt.
         */
-       mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev);
-       if (!mmc)
-               return -ENOMEM;
-       
-       host = mmc_priv(mmc);
-       host->mmc = mmc;
+
+       ret = request_irq(irq, wbsd_irq, SA_SHIRQ, DRIVER_NAME, host);
+       if (ret)
+               return ret;
        
+       host->irq = irq;
+
        /*
-        * Scan for hardware.
+        * Set up tasklets.
         */
-       ret = wbsd_scan(host);
-       if (ret)
-               goto freemmc;
+       tasklet_init(&host->card_tasklet, wbsd_tasklet_card, (unsigned 
long)host);
+       tasklet_init(&host->fifo_tasklet, wbsd_tasklet_fifo, (unsigned 
long)host);
+       tasklet_init(&host->crc_tasklet, wbsd_tasklet_crc, (unsigned long)host);
+       tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout, (unsigned 
long)host);
+       tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned 
long)host);
+       tasklet_init(&host->block_tasklet, wbsd_tasklet_block, (unsigned 
long)host);
+       
+       return 0;
+}
 
-       /*
-        * Reset the chip.
-        */     
-       wbsd_write_config(host, WBSD_CONF_SWRST, 1);
-       wbsd_write_config(host, WBSD_CONF_SWRST, 0);
+static void __devexit wbsd_release_irq(struct wbsd_host* host)
+{
+       if (!host->irq)
+               return;
 
+       free_irq(host->irq, host);
+       
+       host->irq = 0;
+               
+       tasklet_kill(&host->card_tasklet);
+       tasklet_kill(&host->fifo_tasklet);
+       tasklet_kill(&host->crc_tasklet);
+       tasklet_kill(&host->timeout_tasklet);
+       tasklet_kill(&host->finish_tasklet);
+       tasklet_kill(&host->block_tasklet);
+}
+
+/*
+ * Allocate all resources for the host.
+ */
+
+static int __devinit wbsd_request_resources(struct wbsd_host* host,
+       int base, int irq, int dma)
+{
+       int ret;
+       
        /*
         * Allocate I/O ports.
         */
-       ret = wbsd_request_regions(host);
+       ret = wbsd_request_region(host, base);
        if (ret)
-               goto release;
+               return ret;
 
        /*
-        * Set host parameters.
+        * Allocate interrupt.
         */
-       mmc->ops = &wbsd_ops;
-       mmc->f_min = 375000;
-       mmc->f_max = 24000000;
-       mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
+       ret = wbsd_request_irq(host, irq);
+       if (ret)
+               return ret;
+
+       /*
+        * Allocate DMA.
+        */
+       wbsd_request_dma(host, dma);
        
-       spin_lock_init(&host->lock);
+       return 0;
+}
+
+/*
+ * Release all resources for the host.
+ */
+
+static void __devexit wbsd_release_resources(struct wbsd_host* host)
+{
+       wbsd_release_dma(host);
+       wbsd_release_irq(host);
+       wbsd_release_regions(host);
+}
+
+/*
+ * Configure the resources the chip should use.
+ */
+
+static void __devinit wbsd_chip_config(struct wbsd_host* host)
+{
+       /*
+        * Reset the chip.
+        */     
+       wbsd_write_config(host, WBSD_CONF_SWRST, 1);
+       wbsd_write_config(host, WBSD_CONF_SWRST, 0);
 
        /*
         * Select SD/MMC function.
@@ -1399,165 +1637,241 @@
        /*
         * Set up card detection.
         */
-       wbsd_write_config(host, WBSD_CONF_PINS, 0x02);
+       wbsd_write_config(host, WBSD_CONF_PINS, WBSD_PINS_DETECT_GP11);
        
        /*
-        * Configure I/O port.
+        * Configure chip
         */
        wbsd_write_config(host, WBSD_CONF_PORT_HI, host->base >> 8);
        wbsd_write_config(host, WBSD_CONF_PORT_LO, host->base & 0xff);
-
-       /*
-        * Allocate interrupt.
-        */
-       ret = request_irq(irq, wbsd_irq, SA_SHIRQ, DRIVER_NAME, host);
-       if (ret)
-               goto release;
        
-       host->irq = irq;
+       wbsd_write_config(host, WBSD_CONF_IRQ, host->irq);
        
-       /*
-        * Set up tasklets.
-        */
-       tasklet_init(&host->card_tasklet, wbsd_tasklet_card, (unsigned 
long)host);
-       tasklet_init(&host->fifo_tasklet, wbsd_tasklet_fifo, (unsigned 
long)host);
-       tasklet_init(&host->crc_tasklet, wbsd_tasklet_crc, (unsigned long)host);
-       tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout, (unsigned 
long)host);
-       tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned 
long)host);
-       tasklet_init(&host->block_tasklet, wbsd_tasklet_block, (unsigned 
long)host);
+       if (host->dma >= 0)
+               wbsd_write_config(host, WBSD_CONF_DRQ, host->dma);
        
        /*
-        * Configure interrupt.
+        * Enable and power up chip.
         */
-       wbsd_write_config(host, WBSD_CONF_IRQ, host->irq);
+       wbsd_write_config(host, WBSD_CONF_ENABLE, 1);
+       wbsd_write_config(host, WBSD_CONF_POWER, 0x20);
+}
+
+/*
+ * Check that configured resources are correct.
+ */
+ 
+static int __devinit wbsd_chip_validate(struct wbsd_host* host)
+{
+       int base, irq, dma;
        
        /*
-        * Allocate DMA.
+        * Select SD/MMC function.
         */
-       wbsd_init_dma(host);
+       wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
        
        /*
-        * If all went well, then configure DMA.
+        * Read configuration.
         */
-       if (host->dma >= 0)
-               wbsd_write_config(host, WBSD_CONF_DRQ, host->dma);
+       base = wbsd_read_config(host, WBSD_CONF_PORT_HI) << 8;
+       base |= wbsd_read_config(host, WBSD_CONF_PORT_LO);
        
-       /*
-        * Maximum number of segments. Worst case is one sector per segment
-        * so this will be 64kB/512.
-        */
-       mmc->max_hw_segs = 128;
-       mmc->max_phys_segs = 128;
+       irq = wbsd_read_config(host, WBSD_CONF_IRQ);
+       
+       dma = wbsd_read_config(host, WBSD_CONF_DRQ);
        
        /*
-        * Maximum number of sectors in one transfer. Also limited by 64kB
-        * buffer.
+        * Validate against given configuration.
         */
-       mmc->max_sectors = 128;
+       if (base != host->base)
+               return 0;
+       if (irq != host->irq)
+               return 0;
+       if ((dma != host->dma) && (host->dma != -1))
+               return 0;
+       
+       return 1;
+}
+
+/*****************************************************************************\
+ *                                                                           *
+ * Devices setup and shutdown                                                *
+ *                                                                           *
+\*****************************************************************************/
+
+static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
+       int pnp)
+{
+       struct wbsd_host* host = NULL;
+       struct mmc_host* mmc = NULL;
+       int ret;
+       
+       ret = wbsd_alloc_mmc(dev);
+       if (ret)
+               return ret;
+       
+       mmc = dev_get_drvdata(dev);
+       host = mmc_priv(mmc);
        
        /*
-        * Maximum segment size. Could be one segment with the maximum number
-        * of segments.
+        * Scan for hardware.
         */
-       mmc->max_seg_size = mmc->max_sectors * 512;
+       ret = wbsd_scan(host);
+       if (ret)
+       {
+               if (pnp && (ret == -ENODEV))
+               {
+                       printk(KERN_WARNING DRIVER_NAME
+                               ": Unable to confirm device presence. You may "
+                               "experience lock-ups.\n");
+               }
+               else
+               {
+                       wbsd_free_mmc(dev);
+                       return ret;
+               }
+       }
        
        /*
-        * Enable chip.
+        * Request resources.
         */
-       wbsd_write_config(host, WBSD_CONF_ENABLE, 1);
+       ret = wbsd_request_resources(host, io, irq, dma);
+       if (ret)
+       {
+               wbsd_release_resources(host);
+               wbsd_free_mmc(dev);
+               return ret;
+       }
        
        /*
-        * Power up chip.
+        * See if chip needs to be configured.
         */
-       wbsd_write_config(host, WBSD_CONF_POWER, 0x20);
+       if (pnp && (host->config != 0))
+       {
+               if (!wbsd_chip_validate(host))
+               {
+                       printk(KERN_WARNING DRIVER_NAME
+                               ": PnP active but chip not configured! "
+                               "You probably have a buggy BIOS. "
+                               "Configuring chip manually.\n");
+                       wbsd_chip_config(host);
+               }
+       }
+       else
+               wbsd_chip_config(host);
        
        /*
         * Power Management stuff. No idea how this works.
         * Not tested.
         */
 #ifdef CONFIG_PM
-       wbsd_write_config(host, WBSD_CONF_PME, 0xA0);
+       if (host->config)
+               wbsd_write_config(host, WBSD_CONF_PME, 0xA0);
 #endif
+       /*
+        * Allow device to initialise itself properly.
+        */
+       mdelay(5);
 
        /*
         * Reset the chip into a known state.
         */
        wbsd_init_device(host);
        
-       dev_set_drvdata(dev, mmc);
-       
-       /*
-        * Add host to MMC layer.
-        */
        mmc_add_host(mmc);
 
-       printk(KERN_INFO "%s: W83L51xD id %x at 0x%x irq %d dma %d\n",
-               mmc->host_name, (int)host->chip_id, (int)host->base,
-               (int)host->irq, (int)host->dma);
+       printk(KERN_INFO "%s: W83L51xD", mmc->host_name);
+       if (host->chip_id != 0)
+               printk(" id %x", (int)host->chip_id);
+       printk(" at 0x%x irq %d", (int)host->base, (int)host->irq);
+       if (host->dma >= 0)
+               printk(" dma %d", (int)host->dma);
+       else
+               printk(" FIFO");
+       if (pnp)
+               printk(" PnP");
+       printk("\n");
 
        return 0;
-
-release:
-       wbsd_release_regions(host);
-
-freemmc:
-       mmc_free_host(mmc);
-
-       return ret;
 }
 
-/*
- * Device remove
- */
-
-static int wbsd_remove(struct device* dev)
+static void __devexit wbsd_shutdown(struct device* dev, int pnp)
 {
        struct mmc_host* mmc = dev_get_drvdata(dev);
        struct wbsd_host* host;
        
        if (!mmc)
-               return 0;
+               return;
 
        host = mmc_priv(mmc);
        
-       /*
-        * Unregister host with MMC layer.
-        */
        mmc_remove_host(mmc);
 
-       /*
-        * Power down the SD/MMC function.
-        */
-       wbsd_unlock_config(host);
-       wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
-       wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
-       wbsd_lock_config(host);
+       if (!pnp)
+       {
+               /*
+                * Power down the SD/MMC function.
+                */
+               wbsd_unlock_config(host);
+               wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
+               wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
+               wbsd_lock_config(host);
+       }
        
-       /*
-        * Free resources.
-        */
-       if (host->dma_buffer)
-               kfree(host->dma_buffer);
+       wbsd_release_resources(host);
        
-       if (host->dma >= 0)
-               free_dma(host->dma);
+       wbsd_free_mmc(dev);
+}
 
-       free_irq(host->irq, host);
+/*
+ * Non-PnP
+ */
+
+static int __devinit wbsd_probe(struct device* dev)
+{
+       return wbsd_init(dev, io, irq, dma, 0);
+}
+
+static int __devexit wbsd_remove(struct device* dev)
+{
+       wbsd_shutdown(dev, 0);
+
+       return 0;
+}
+
+/*
+ * PnP
+ */
+
+#ifdef CONFIG_PNP
+
+static int __devinit
+wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id)
+{
+       int io, irq, dma;
        
-       tasklet_kill(&host->card_tasklet);
-       tasklet_kill(&host->fifo_tasklet);
-       tasklet_kill(&host->crc_tasklet);
-       tasklet_kill(&host->timeout_tasklet);
-       tasklet_kill(&host->finish_tasklet);
-       tasklet_kill(&host->block_tasklet);
+       /*
+        * Get resources from PnP layer.
+        */
+       io = pnp_port_start(pnpdev, 0);
+       irq = pnp_irq(pnpdev, 0);
+       if (pnp_dma_valid(pnpdev, 0))
+               dma = pnp_dma(pnpdev, 0);
+       else
+               dma = -1;
        
-       wbsd_release_regions(host);
+       DBGF("PnP resources: port %3x irq %d dma %d\n", io, irq, dma);
        
-       mmc_free_host(mmc);
+       return wbsd_init(&pnpdev->dev, io, irq, dma, 1);
+}
 
-       return 0;
+static void __devexit wbsd_pnp_remove(struct pnp_dev * dev)
+{
+       wbsd_shutdown(&dev->dev, 1);
 }
 
+#endif /* CONFIG_PNP */
+
 /*
  * Power management
  */
@@ -1581,17 +1895,7 @@
 #define wbsd_resume NULL
 #endif
 
-static void wbsd_release(struct device *dev)
-{
-}
-
-static struct platform_device wbsd_device = {
-       .name           = DRIVER_NAME,
-       .id                     = -1,
-       .dev            = {
-               .release = wbsd_release,
-       },
-};
+static struct platform_device *wbsd_device;
 
 static struct device_driver wbsd_driver = {
        .name           = DRIVER_NAME,
@@ -1603,6 +1907,17 @@
        .resume         = wbsd_resume,
 };
 
+#ifdef CONFIG_PNP
+
+static struct pnp_driver wbsd_pnp_driver = {
+       .name           = DRIVER_NAME,
+       .id_table       = pnp_dev_table,
+       .probe          = wbsd_pnp_probe,
+       .remove         = wbsd_pnp_remove,
+};
+
+#endif /* CONFIG_PNP */
+
 /*
  * Module loading/unloading
  */
@@ -1615,29 +1930,57 @@
                ": Winbond W83L51xD SD/MMC card interface driver, "
                DRIVER_VERSION "\n");
        printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
+
+#ifdef CONFIG_PNP
+
+       if (!nopnp)
+       {
+               result = pnp_register_driver(&wbsd_pnp_driver);
+               if (result < 0)
+                       return result;
+       }
+
+#endif /* CONFIG_PNP */        
        
-       result = driver_register(&wbsd_driver);
-       if (result < 0)
-               return result;
-
-       result = platform_device_register(&wbsd_device);
-       if (result < 0)
-               return result;
+       if (nopnp)
+       {
+               result = driver_register(&wbsd_driver);
+               if (result < 0)
+                       return result;
+
+               wbsd_device = platform_device_register_simple(DRIVER_NAME, -1,
+                       NULL, 0);
+               if (IS_ERR(wbsd_device))
+                       return PTR_ERR(wbsd_device);
+       }
 
        return 0;
 }
 
 static void __exit wbsd_drv_exit(void)
 {
-       platform_device_unregister(&wbsd_device);
+#ifdef CONFIG_PNP
+
+       if (!nopnp)
+               pnp_unregister_driver(&wbsd_pnp_driver);
        
-       driver_unregister(&wbsd_driver);
+#endif /* CONFIG_PNP */        
+
+       if (nopnp)
+       {
+               platform_device_unregister(wbsd_device);
+       
+               driver_unregister(&wbsd_driver);
+       }
 
        DBG("unloaded\n");
 }
 
 module_init(wbsd_drv_init);
 module_exit(wbsd_drv_exit);
+#ifdef CONFIG_PNP
+module_param(nopnp, uint, 0444);
+#endif
 module_param(io, uint, 0444);
 module_param(irq, uint, 0444);
 module_param(dma, int, 0444);
@@ -1646,6 +1989,9 @@
 MODULE_DESCRIPTION("Winbond W83L51xD SD/MMC card interface driver");
 MODULE_VERSION(DRIVER_VERSION);
 
+#ifdef CONFIG_PNP
+MODULE_PARM_DESC(nopnp, "Scan for device instead of relying on PNP. (default 
0)");
+#endif
 MODULE_PARM_DESC(io, "I/O base to allocate. Must be 8 byte aligned. (default 
0x248)");
 MODULE_PARM_DESC(irq, "IRQ to allocate. (default 6)");
 MODULE_PARM_DESC(dma, "DMA channel to allocate. -1 for no DMA. (default 2)");
diff -urN linux/drivers/mmc/wbsd.h linux/drivers/mmc/wbsd.h
--- linux/drivers/mmc/wbsd.h    2005/01/25 04:28:22     1.2
+++ linux/drivers/mmc/wbsd.h    2005/05/26 09:12:44     1.3
@@ -35,6 +35,12 @@
 
 #define DEVICE_SD              0x03
 
+#define WBSD_PINS_DAT3_HI      0x20
+#define WBSD_PINS_DAT3_OUT     0x10
+#define WBSD_PINS_GP11_HI      0x04
+#define WBSD_PINS_DETECT_GP11  0x02
+#define WBSD_PINS_DETECT_DAT3  0x01
+
 #define WBSD_CMDR              0x00
 #define WBSD_DFR               0x01
 #define WBSD_EIR               0x02
@@ -133,6 +139,7 @@
 #define WBSD_CRC_OK            0x05 /* S010E (00101) */
 #define WBSD_CRC_FAIL          0x0B /* S101E (01011) */
 
+#define WBSD_DMA_SIZE          65536
 
 struct wbsd_host
 {
@@ -140,6 +147,11 @@
        
        spinlock_t              lock;           /* Mutex */
 
+       int                     flags;          /* Driver states */
+
+#define WBSD_FCARD_PRESENT     (1<<0)          /* Card is present */
+#define WBSD_FIGNORE_DETECT    (1<<1)          /* Ignore card detection */
+       
        struct mmc_request*     mrq;            /* Current request */
        
        u8                      isr;            /* Accumulated ISR */
diff -urN linux/drivers/net/Makefile linux/drivers/net/Makefile
--- linux/drivers/net/Makefile  2005/04/08 18:58:19     1.110
+++ linux/drivers/net/Makefile  2005/05/26 09:12:44     1.111
@@ -192,7 +192,7 @@
 obj-$(CONFIG_WAN) += wan/
 obj-$(CONFIG_ARCNET) += arcnet/
 obj-$(CONFIG_NET_PCMCIA) += pcmcia/
-obj-$(CONFIG_NET_WIRELESS) += wireless/
+obj-$(CONFIG_NET_RADIO) += wireless/
 obj-$(CONFIG_NET_TULIP) += tulip/
 obj-$(CONFIG_HAMRADIO) += hamradio/
 obj-$(CONFIG_IRDA) += irda/
diff -urN linux/drivers/net/tg3.c linux/drivers/net/tg3.c
--- linux/drivers/net/tg3.c     2005/05/19 12:08:26     1.59
+++ linux/drivers/net/tg3.c     2005/05/26 09:12:44     1.60
@@ -61,8 +61,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.27"
-#define DRV_MODULE_RELDATE     "May 5, 2005"
+#define DRV_MODULE_VERSION     "3.29"
+#define DRV_MODULE_RELDATE     "May 23, 2005"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -206,6 +206,8 @@
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
        { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
        { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
        { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M,
@@ -420,7 +422,8 @@
 {
        tw32(TG3PCI_MISC_HOST_CTRL,
             (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
-       tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000);
+       tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+                    (tp->last_tag << 24));
        tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
 
        tg3_cond_int(tp);
@@ -455,10 +458,16 @@
 {
        tw32(TG3PCI_MISC_HOST_CTRL,
                (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
-       tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000);
+       tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+                    tp->last_tag << 24);
        mmiowb();
 
-       if (tg3_has_work(tp))
+       /* When doing tagged status, this work check is unnecessary.
+        * The last_tag we write above tells the chip which piece of
+        * work we've completed.
+        */
+       if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) &&
+           tg3_has_work(tp))
                tw32(HOSTCC_MODE, tp->coalesce_mode |
                     (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
 }
@@ -2500,7 +2509,7 @@
        if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
                if (netif_carrier_ok(tp->dev)) {
                        tw32(HOSTCC_STAT_COAL_TICKS,
-                            DEFAULT_STAT_COAL_TICKS);
+                            tp->coal.stats_block_coalesce_usecs);
                } else {
                        tw32(HOSTCC_STAT_COAL_TICKS, 0);
                }
@@ -2886,7 +2895,6 @@
         * All RX "locking" is done by ensuring outside
         * code synchronizes with dev->poll()
         */
-       done = 1;
        if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr) {
                int orig_budget = *budget;
                int work_done;
@@ -2898,12 +2906,14 @@
 
                *budget -= work_done;
                netdev->quota -= work_done;
-
-               if (work_done >= orig_budget)
-                       done = 0;
        }
 
+       if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+               tp->last_tag = sblk->status_tag;
+       rmb();
+
        /* if no more work, tell net stack and NIC we're done */
+       done = !tg3_has_work(tp);
        if (done) {
                spin_lock_irqsave(&tp->lock, flags);
                __netif_rx_complete(netdev);
@@ -2928,22 +2938,21 @@
        spin_lock_irqsave(&tp->lock, flags);
 
        /*
-        * writing any value to intr-mbox-0 clears PCI INTA# and
+        * Writing any value to intr-mbox-0 clears PCI INTA# and
         * chip-internal interrupt pending events.
-        * writing non-zero to intr-mbox-0 additional tells the
+        * Writing non-zero to intr-mbox-0 additional tells the
         * NIC to stop sending us irqs, engaging "in-intr-handler"
         * event coalescing.
         */
        tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+       tp->last_tag = sblk->status_tag;
        sblk->status &= ~SD_STATUS_UPDATED;
-
        if (likely(tg3_has_work(tp)))
                netif_rx_schedule(dev);         /* schedule NAPI poll */
        else {
-               /* no work, re-enable interrupts
-                */
+               /* No work, re-enable interrupts.  */
                tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
-                            0x00000000);
+                            tp->last_tag << 24);
        }
 
        spin_unlock_irqrestore(&tp->lock, flags);
@@ -2969,21 +2978,62 @@
        if ((sblk->status & SD_STATUS_UPDATED) ||
            !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
                /*
-                * writing any value to intr-mbox-0 clears PCI INTA# and
+                * Writing any value to intr-mbox-0 clears PCI INTA# and
                 * chip-internal interrupt pending events.
-                * writing non-zero to intr-mbox-0 additional tells the
+                * Writing non-zero to intr-mbox-0 additional tells the
                 * NIC to stop sending us irqs, engaging "in-intr-handler"
                 * event coalescing.
                 */
                tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
                             0x00000001);
+               sblk->status &= ~SD_STATUS_UPDATED;
+               if (likely(tg3_has_work(tp)))
+                       netif_rx_schedule(dev);         /* schedule NAPI poll */
+               else {
+                       /* No work, shared interrupt perhaps?  re-enable
+                        * interrupts, and flush that PCI write
+                        */
+                       tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+                               0x00000000);
+                       tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+               }
+       } else {        /* shared interrupt */
+               handled = 0;
+       }
+
+       spin_unlock_irqrestore(&tp->lock, flags);
+
+       return IRQ_RETVAL(handled);
+}
+
+static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs 
*regs)
+{
+       struct net_device *dev = dev_id;
+       struct tg3 *tp = netdev_priv(dev);
+       struct tg3_hw_status *sblk = tp->hw_status;
+       unsigned long flags;
+       unsigned int handled = 1;
+
+       spin_lock_irqsave(&tp->lock, flags);
+
+       /* In INTx mode, it is possible for the interrupt to arrive at
+        * the CPU before the status block posted prior to the interrupt.
+        * Reading the PCI State register will confirm whether the
+        * interrupt is ours and will flush the status block.
+        */
+       if ((sblk->status & SD_STATUS_UPDATED) ||
+           !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
                /*
-                * Flush PCI write.  This also guarantees that our
-                * status block has been flushed to host memory.
+                * writing any value to intr-mbox-0 clears PCI INTA# and
+                * chip-internal interrupt pending events.
+                * writing non-zero to intr-mbox-0 additional tells the
+                * NIC to stop sending us irqs, engaging "in-intr-handler"
+                * event coalescing.
                 */
-               tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+               tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+                            0x00000001);
+               tp->last_tag = sblk->status_tag;
                sblk->status &= ~SD_STATUS_UPDATED;
-
                if (likely(tg3_has_work(tp)))
                        netif_rx_schedule(dev);         /* schedule NAPI poll */
                else {
@@ -2991,7 +3041,7 @@
                         * interrupts, and flush that PCI write
                         */
                        tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
-                               0x00000000);
+                                    tp->last_tag << 24);
                        tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
                }
        } else {        /* shared interrupt */
@@ -5044,6 +5094,27 @@
 }
 
 static void __tg3_set_rx_mode(struct net_device *);
+static void tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
+{
+       tw32(HOSTCC_RXCOL_TICKS, ec->rx_coalesce_usecs);
+       tw32(HOSTCC_TXCOL_TICKS, ec->tx_coalesce_usecs);
+       tw32(HOSTCC_RXMAX_FRAMES, ec->rx_max_coalesced_frames);
+       tw32(HOSTCC_TXMAX_FRAMES, ec->tx_max_coalesced_frames);
+       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
+               tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq);
+               tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq);
+       }
+       tw32(HOSTCC_RXCOAL_MAXF_INT, ec->rx_max_coalesced_frames_irq);
+       tw32(HOSTCC_TXCOAL_MAXF_INT, ec->tx_max_coalesced_frames_irq);
+       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
+               u32 val = ec->stats_block_coalesce_usecs;
+
+               if (!netif_carrier_ok(tp->dev))
+                       val = 0;
+
+               tw32(HOSTCC_STAT_COAL_TICKS, val);
+       }
+}
 
 /* tp->lock is held. */
 static int tg3_reset_hw(struct tg3 *tp)
@@ -5366,16 +5437,7 @@
                udelay(10);
        }
 
-       tw32(HOSTCC_RXCOL_TICKS, 0);
-       tw32(HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS);
-       tw32(HOSTCC_RXMAX_FRAMES, 1);
-       tw32(HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES);
-       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
-               tw32(HOSTCC_RXCOAL_TICK_INT, 0);
-               tw32(HOSTCC_TXCOAL_TICK_INT, 0);
-       }
-       tw32(HOSTCC_RXCOAL_MAXF_INT, 1);
-       tw32(HOSTCC_TXCOAL_MAXF_INT, 0);
+       tg3_set_coalesce(tp, &tp->coal);
 
        /* set status block DMA address */
        tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH,
@@ -5388,8 +5450,6 @@
                 * the tg3_periodic_fetch_stats call there, and
                 * tg3_get_stats to see how this works for 5705/5750 chips.
                 */
-               tw32(HOSTCC_STAT_COAL_TICKS,
-                    DEFAULT_STAT_COAL_TICKS);
                tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH,
                     ((u64) tp->stats_mapping >> 32));
                tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
@@ -5445,7 +5505,8 @@
        udelay(100);
 
        tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0);
-       tr32(MAILBOX_INTERRUPT_0);
+       tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+       tp->last_tag = 0;
 
        if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
                tw32_f(DMAC_MODE, DMAC_MODE_ENABLE);
@@ -5723,31 +5784,33 @@
        spin_lock_irqsave(&tp->lock, flags);
        spin_lock(&tp->tx_lock);
 
-       /* All of this garbage is because when using non-tagged
-        * IRQ status the mailbox/status_block protocol the chip
-        * uses with the cpu is race prone.
-        */
-       if (tp->hw_status->status & SD_STATUS_UPDATED) {
-               tw32(GRC_LOCAL_CTRL,
-                    tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
-       } else {
-               tw32(HOSTCC_MODE, tp->coalesce_mode |
-                    (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
-       }
+       if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
+               /* All of this garbage is because when using non-tagged
+                * IRQ status the mailbox/status_block protocol the chip
+                * uses with the cpu is race prone.
+                */
+               if (tp->hw_status->status & SD_STATUS_UPDATED) {
+                       tw32(GRC_LOCAL_CTRL,
+                            tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
+               } else {
+                       tw32(HOSTCC_MODE, tp->coalesce_mode |
+                            (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
+               }
 
-       if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
-               tp->tg3_flags2 |= TG3_FLG2_RESTART_TIMER;
-               spin_unlock(&tp->tx_lock);
-               spin_unlock_irqrestore(&tp->lock, flags);
-               schedule_work(&tp->reset_task);
-               return;
+               if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
+                       tp->tg3_flags2 |= TG3_FLG2_RESTART_TIMER;
+                       spin_unlock(&tp->tx_lock);
+                       spin_unlock_irqrestore(&tp->lock, flags);
+                       schedule_work(&tp->reset_task);
+                       return;
+               }
        }
 
-       if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
-               tg3_periodic_fetch_stats(tp);
-
        /* This part only runs once per second. */
        if (!--tp->timer_counter) {
+               if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
+                       tg3_periodic_fetch_stats(tp);
+
                if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) {
                        u32 mac_stat;
                        int phy_event;
@@ -5846,9 +5909,13 @@
        if (tp->tg3_flags2 & TG3_FLG2_USING_MSI)
                err = request_irq(tp->pdev->irq, tg3_msi,
                                  SA_SAMPLE_RANDOM, dev->name, dev);
-       else
-               err = request_irq(tp->pdev->irq, tg3_interrupt,
+       else {
+               irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt;
+               if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+                       fn = tg3_interrupt_tagged;
+               err = request_irq(tp->pdev->irq, fn,
                                  SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+       }
 
        if (err)
                return err;
@@ -5900,9 +5967,14 @@
 
        tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
 
-       err = request_irq(tp->pdev->irq, tg3_interrupt,
-                         SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+       {
+               irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt;
+               if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+                       fn = tg3_interrupt_tagged;
 
+               err = request_irq(tp->pdev->irq, fn,
+                                 SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+       }
        if (err)
                return err;
 
@@ -5948,7 +6020,13 @@
        if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
            (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_AX) &&
            (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX)) {
-               if (pci_enable_msi(tp->pdev) == 0) {
+               /* All MSI supporting chips should support tagged
+                * status.  Assert that this is the case.
+                */
+               if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
+                       printk(KERN_WARNING PFX "%s: MSI without TAGGED? "
+                              "Not using MSI.\n", tp->dev->name);
+               } else if (pci_enable_msi(tp->pdev) == 0) {
                        u32 msi_mode;
 
                        msi_mode = tr32(MSGINT_MODE);
@@ -5959,9 +6037,14 @@
        if (tp->tg3_flags2 & TG3_FLG2_USING_MSI)
                err = request_irq(tp->pdev->irq, tg3_msi,
                                  SA_SAMPLE_RANDOM, dev->name, dev);
-       else
-               err = request_irq(tp->pdev->irq, tg3_interrupt,
+       else {
+               irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt;
+               if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+                       fn = tg3_interrupt_tagged;
+
+               err = request_irq(tp->pdev->irq, fn,
                                  SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+       }
 
        if (err) {
                if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
@@ -5980,9 +6063,16 @@
                tg3_halt(tp, 1);
                tg3_free_rings(tp);
        } else {
-               tp->timer_offset = HZ / 10;
-               tp->timer_counter = tp->timer_multiplier = 10;
-               tp->asf_counter = tp->asf_multiplier = (10 * 120);
+               if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+                       tp->timer_offset = HZ;
+               else
+                       tp->timer_offset = HZ / 10;
+
+               BUG_ON(tp->timer_offset > HZ);
+               tp->timer_counter = tp->timer_multiplier =
+                       (HZ / tp->timer_offset);
+               tp->asf_counter = tp->asf_multiplier =
+                       ((HZ / tp->timer_offset) * 120);
 
                init_timer(&tp->timer);
                tp->timer.expires = jiffies + tp->timer_offset;
@@ -6005,6 +6095,7 @@
 
        if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
                err = tg3_test_msi(tp);
+
                if (err) {
                        spin_lock_irq(&tp->lock);
                        spin_lock(&tp->tx_lock);
@@ -7203,6 +7294,14 @@
 }
 #endif
 
+static int tg3_get_coalesce(struct net_device *dev, struct ethtool_coalesce 
*ec)
+{
+       struct tg3 *tp = netdev_priv(dev);
+
+       memcpy(ec, &tp->coal, sizeof(*ec));
+       return 0;
+}
+
 static struct ethtool_ops tg3_ethtool_ops = {
        .get_settings           = tg3_get_settings,
        .set_settings           = tg3_set_settings,
@@ -7235,6 +7334,7 @@
        .get_strings            = tg3_get_strings,
        .get_stats_count        = tg3_get_stats_count,
        .get_ethtool_stats      = tg3_get_ethtool_stats,
+       .get_coalesce           = tg3_get_coalesce,
 };
 
 static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
@@ -8422,15 +8522,7 @@
        if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
                tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
 
-       /* Only 5701 and later support tagged irq status mode.
-        * Also, 5788 chips cannot use tagged irq status.
-        *
-        * However, since we are using NAPI avoid tagged irq status
-        * because the interrupt condition is more difficult to
-        * fully clear in that mode.
-        */
        tp->coalesce_mode = 0;
-
        if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX &&
            GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX)
                tp->coalesce_mode |= HOSTCC_MODE_32BYTE;
@@ -8494,6 +8586,18 @@
             grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M))
                tp->tg3_flags2 |= TG3_FLG2_IS_5788;
 
+       if (!(tp->tg3_flags2 & TG3_FLG2_IS_5788) &&
+           (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700))
+               tp->tg3_flags |= TG3_FLAG_TAGGED_STATUS;
+       if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
+               tp->coalesce_mode |= (HOSTCC_MODE_CLRTICK_RXBD |
+                                     HOSTCC_MODE_CLRTICK_TXBD);
+
+               tp->misc_host_ctrl |= MISC_HOST_CTRL_TAGGED_STATUS;
+               pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+                                      tp->misc_host_ctrl);
+       }
+
        /* these are limited to 10/100 only */
        if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
             (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
@@ -8671,6 +8775,146 @@
        return 0;
 }
 
+#define BOUNDARY_SINGLE_CACHELINE      1
+#define BOUNDARY_MULTI_CACHELINE       2
+
+static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
+{
+       int cacheline_size;
+       u8 byte;
+       int goal;
+
+       pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, &byte);
+       if (byte == 0)
+               cacheline_size = 1024;
+       else
+               cacheline_size = (int) byte * 4;
+
+       /* On 5703 and later chips, the boundary bits have no
+        * effect.
+        */
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 &&
+           !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
+               goto out;
+
+#if defined(CONFIG_PPC64) || defined(CONFIG_IA64) || defined(CONFIG_PARISC)
+       goal = BOUNDARY_MULTI_CACHELINE;
+#else
+#if defined(CONFIG_SPARC64) || defined(CONFIG_ALPHA)
+       goal = BOUNDARY_SINGLE_CACHELINE;
+#else
+       goal = 0;
+#endif
+#endif
+
+       if (!goal)
+               goto out;
+
+       /* PCI controllers on most RISC systems tend to disconnect
+        * when a device tries to burst across a cache-line boundary.
+        * Therefore, letting tg3 do so just wastes PCI bandwidth.
+        *
+        * Unfortunately, for PCI-E there are only limited
+        * write-side controls for this, and thus for reads
+        * we will still get the disconnects.  We'll also waste
+        * these PCI cycles for both read and write for chips
+        * other than 5700 and 5701 which do not implement the
+        * boundary bits.
+        */
+       if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
+           !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
+               switch (cacheline_size) {
+               case 16:
+               case 32:
+               case 64:
+               case 128:
+                       if (goal == BOUNDARY_SINGLE_CACHELINE) {
+                               val |= (DMA_RWCTRL_READ_BNDRY_128_PCIX |
+                                       DMA_RWCTRL_WRITE_BNDRY_128_PCIX);
+                       } else {
+                               val |= (DMA_RWCTRL_READ_BNDRY_384_PCIX |
+                                       DMA_RWCTRL_WRITE_BNDRY_384_PCIX);
+                       }
+                       break;
+
+               case 256:
+                       val |= (DMA_RWCTRL_READ_BNDRY_256_PCIX |
+                               DMA_RWCTRL_WRITE_BNDRY_256_PCIX);
+                       break;
+
+               default:
+                       val |= (DMA_RWCTRL_READ_BNDRY_384_PCIX |
+                               DMA_RWCTRL_WRITE_BNDRY_384_PCIX);
+                       break;
+               };
+       } else if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
+               switch (cacheline_size) {
+               case 16:
+               case 32:
+               case 64:
+                       if (goal == BOUNDARY_SINGLE_CACHELINE) {
+                               val &= ~DMA_RWCTRL_WRITE_BNDRY_DISAB_PCIE;
+                               val |= DMA_RWCTRL_WRITE_BNDRY_64_PCIE;
+                               break;
+                       }
+                       /* fallthrough */
+               case 128:
+               default:
+                       val &= ~DMA_RWCTRL_WRITE_BNDRY_DISAB_PCIE;
+                       val |= DMA_RWCTRL_WRITE_BNDRY_128_PCIE;
+                       break;
+               };
+       } else {
+               switch (cacheline_size) {
+               case 16:
+                       if (goal == BOUNDARY_SINGLE_CACHELINE) {
+                               val |= (DMA_RWCTRL_READ_BNDRY_16 |
+                                       DMA_RWCTRL_WRITE_BNDRY_16);
+                               break;
+                       }
+                       /* fallthrough */
+               case 32:
+                       if (goal == BOUNDARY_SINGLE_CACHELINE) {
+                               val |= (DMA_RWCTRL_READ_BNDRY_32 |
+                                       DMA_RWCTRL_WRITE_BNDRY_32);
+                               break;
+                       }
+                       /* fallthrough */
+               case 64:
+                       if (goal == BOUNDARY_SINGLE_CACHELINE) {
+                               val |= (DMA_RWCTRL_READ_BNDRY_64 |
+                                       DMA_RWCTRL_WRITE_BNDRY_64);
+                               break;
+                       }
+                       /* fallthrough */
+               case 128:
+                       if (goal == BOUNDARY_SINGLE_CACHELINE) {
+                               val |= (DMA_RWCTRL_READ_BNDRY_128 |
+                                       DMA_RWCTRL_WRITE_BNDRY_128);
+                               break;
+                       }
+                       /* fallthrough */
+               case 256:
+                       val |= (DMA_RWCTRL_READ_BNDRY_256 |
+                               DMA_RWCTRL_WRITE_BNDRY_256);
+                       break;
+               case 512:
+                       val |= (DMA_RWCTRL_READ_BNDRY_512 |
+                               DMA_RWCTRL_WRITE_BNDRY_512);
+                       break;
+               case 1024:
+               default:
+                       val |= (DMA_RWCTRL_READ_BNDRY_1024 |
+                               DMA_RWCTRL_WRITE_BNDRY_1024);
+                       break;
+               };
+       }
+
+out:
+       return val;
+}
+
 static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t 
buf_dma, int size, int to_device)
 {
        struct tg3_internal_buffer_desc test_desc;
@@ -8752,12 +8996,12 @@
        return ret;
 }
 
-#define TEST_BUFFER_SIZE       0x400
+#define TEST_BUFFER_SIZE       0x2000
 
 static int __devinit tg3_test_dma(struct tg3 *tp)
 {
        dma_addr_t buf_dma;
-       u32 *buf;
+       u32 *buf, saved_dma_rwctrl;
        int ret;
 
        buf = pci_alloc_consistent(tp->pdev, TEST_BUFFER_SIZE, &buf_dma);
@@ -8769,46 +9013,7 @@
        tp->dma_rwctrl = ((0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
                          (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT));
 
-#ifndef CONFIG_X86
-       {
-               u8 byte;
-               int cacheline_size;
-               pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, &byte);
-
-               if (byte == 0)
-                       cacheline_size = 1024;
-               else
-                       cacheline_size = (int) byte * 4;
-
-               switch (cacheline_size) {
-               case 16:
-               case 32:
-               case 64:
-               case 128:
-                       if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
-                           !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
-                               tp->dma_rwctrl |=
-                                       DMA_RWCTRL_WRITE_BNDRY_384_PCIX;
-                               break;
-                       } else if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
-                               tp->dma_rwctrl &=
-                                       ~(DMA_RWCTRL_PCI_WRITE_CMD);
-                               tp->dma_rwctrl |=
-                                       DMA_RWCTRL_WRITE_BNDRY_128_PCIE;
-                               break;
-                       }
-                       /* fallthrough */
-               case 256:
-                       if (!(tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
-                           !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
-                               tp->dma_rwctrl |=
-                                       DMA_RWCTRL_WRITE_BNDRY_256;
-                       else if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
-                               tp->dma_rwctrl |=
-                                       DMA_RWCTRL_WRITE_BNDRY_256_PCIX;
-               };
-       }
-#endif
+       tp->dma_rwctrl = tg3_calc_dma_bndry(tp, tp->dma_rwctrl);
 
        if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
                /* DMA read watermark not used on PCIE */
@@ -8827,7 +9032,7 @@
                        if (ccval == 0x6 || ccval == 0x7)
                                tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
 
-                       /* Set bit 23 to renable PCIX hw bug fix */
+                       /* Set bit 23 to enable PCIX hw bug fix */
                        tp->dma_rwctrl |= 0x009f0000;
                } else {
                        tp->dma_rwctrl |= 0x001b000f;
@@ -8868,6 +9073,13 @@
            GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701)
                goto out;
 
+       /* It is best to perform DMA test with maximum write burst size
+        * to expose the 5700/5701 write DMA bug.
+        */
+       saved_dma_rwctrl = tp->dma_rwctrl;
+       tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
+       tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+
        while (1) {
                u32 *p = buf, i;
 
@@ -8906,8 +9118,9 @@
                        if (p[i] == i)
                                continue;
 
-                       if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) ==
-                           DMA_RWCTRL_WRITE_BNDRY_DISAB) {
+                       if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) !=
+                           DMA_RWCTRL_WRITE_BNDRY_16) {
+                               tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
                                tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16;
                                tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
                                break;
@@ -8924,6 +9137,14 @@
                        break;
                }
        }
+       if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) !=
+           DMA_RWCTRL_WRITE_BNDRY_16) {
+               /* DMA test passed without adjusting DMA boundary,
+                * just restore the calculated DMA boundary
+                */
+               tp->dma_rwctrl = saved_dma_rwctrl;
+               tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+       }
 
 out:
        pci_free_consistent(tp->pdev, TEST_BUFFER_SIZE, buf, buf_dma);
@@ -9011,6 +9232,31 @@
        return peer;
 }
 
+static void __devinit tg3_init_coal(struct tg3 *tp)
+{
+       struct ethtool_coalesce *ec = &tp->coal;
+
+       memset(ec, 0, sizeof(*ec));
+       ec->cmd = ETHTOOL_GCOALESCE;
+       ec->rx_coalesce_usecs = LOW_RXCOL_TICKS;
+       ec->tx_coalesce_usecs = LOW_TXCOL_TICKS;
+       ec->rx_max_coalesced_frames = LOW_RXMAX_FRAMES;
+       ec->tx_max_coalesced_frames = LOW_TXMAX_FRAMES;
+       ec->rx_coalesce_usecs_irq = DEFAULT_RXCOAL_TICK_INT;
+       ec->tx_coalesce_usecs_irq = DEFAULT_TXCOAL_TICK_INT;
+       ec->rx_max_coalesced_frames_irq = DEFAULT_RXCOAL_MAXF_INT;
+       ec->tx_max_coalesced_frames_irq = DEFAULT_TXCOAL_MAXF_INT;
+       ec->stats_block_coalesce_usecs = DEFAULT_STAT_COAL_TICKS;
+
+       if (tp->coalesce_mode & (HOSTCC_MODE_CLRTICK_RXBD |
+                                HOSTCC_MODE_CLRTICK_TXBD)) {
+               ec->rx_coalesce_usecs = LOW_RXCOL_TICKS_CLRTCKS;
+               ec->rx_coalesce_usecs_irq = DEFAULT_RXCOAL_TICK_INT_CLRTCKS;
+               ec->tx_coalesce_usecs = LOW_TXCOL_TICKS_CLRTCKS;
+               ec->tx_coalesce_usecs_irq = DEFAULT_TXCOAL_TICK_INT_CLRTCKS;
+       }
+}
+
 static int __devinit tg3_init_one(struct pci_dev *pdev,
                                  const struct pci_device_id *ent)
 {
@@ -9256,6 +9502,8 @@
        /* flow control autonegotiation is default behavior */
        tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
 
+       tg3_init_coal(tp);
+
        err = register_netdev(dev);
        if (err) {
                printk(KERN_ERR PFX "Cannot register net device, "
@@ -9298,6 +9546,8 @@
               (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0,
               (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0,
               (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
+       printk(KERN_INFO "%s: dma_rwctrl[%08x]\n",
+              dev->name, tp->dma_rwctrl);
 
        return 0;
 
diff -urN linux/drivers/net/tg3.h linux/drivers/net/tg3.h
--- linux/drivers/net/tg3.h     2005/05/19 12:08:26     1.32
+++ linux/drivers/net/tg3.h     2005/05/26 09:12:44     1.33
@@ -876,10 +876,12 @@
 #define  HOSTCC_STATUS_ERROR_ATTN       0x00000004
 #define HOSTCC_RXCOL_TICKS             0x00003c08
 #define  LOW_RXCOL_TICKS                0x00000032
+#define  LOW_RXCOL_TICKS_CLRTCKS        0x00000014
 #define  DEFAULT_RXCOL_TICKS            0x00000048
 #define  HIGH_RXCOL_TICKS               0x00000096
 #define HOSTCC_TXCOL_TICKS             0x00003c0c
 #define  LOW_TXCOL_TICKS                0x00000096
+#define  LOW_TXCOL_TICKS_CLRTCKS        0x00000048
 #define  DEFAULT_TXCOL_TICKS            0x0000012c
 #define  HIGH_TXCOL_TICKS               0x00000145
 #define HOSTCC_RXMAX_FRAMES            0x00003c10
@@ -892,8 +894,10 @@
 #define  HIGH_TXMAX_FRAMES              0x00000052
 #define HOSTCC_RXCOAL_TICK_INT         0x00003c18
 #define  DEFAULT_RXCOAL_TICK_INT        0x00000019
+#define  DEFAULT_RXCOAL_TICK_INT_CLRTCKS 0x00000014
 #define HOSTCC_TXCOAL_TICK_INT         0x00003c1c
 #define  DEFAULT_TXCOAL_TICK_INT        0x00000019
+#define  DEFAULT_TXCOAL_TICK_INT_CLRTCKS 0x00000014
 #define HOSTCC_RXCOAL_MAXF_INT         0x00003c20
 #define  DEFAULT_RXCOAL_MAXF_INT        0x00000005
 #define HOSTCC_TXCOAL_MAXF_INT         0x00003c24
@@ -2023,6 +2027,7 @@
 
        struct tg3_hw_status            *hw_status;
        dma_addr_t                      status_mapping;
+       u32                             last_tag;
 
        u32                             msg_enable;
 
@@ -2068,6 +2073,7 @@
 
        u32                             rx_offset;
        u32                             tg3_flags;
+#define TG3_FLAG_TAGGED_STATUS         0x00000001
 #define TG3_FLAG_TXD_MBOX_HWBUG                0x00000002
 #define TG3_FLAG_RX_CHECKSUMS          0x00000004
 #define TG3_FLAG_USE_LINKCHG_REG       0x00000008
@@ -2225,7 +2231,7 @@
 
 #define SST_25VF0X0_PAGE_SIZE          4098
 
-
+       struct ethtool_coalesce         coal;
 };
 
 #endif /* !(_T3_H) */
diff -urN linux/drivers/net/ibm_emac/ibm_emac_core.c 
linux/drivers/net/ibm_emac/ibm_emac_core.c
--- linux/drivers/net/ibm_emac/ibm_emac_core.c  2005/03/18 17:37:37     1.8
+++ linux/drivers/net/ibm_emac/ibm_emac_core.c  2005/05/26 09:12:45     1.9
@@ -1595,7 +1595,7 @@
 static int emac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
        struct ocp_enet_private *fep = dev->priv;
-       uint *data = (uint *) & rq->ifr_ifru;
+       uint16_t *data = (uint16_t *) & rq->ifr_ifru;
 
        switch (cmd) {
        case SIOCGMIIPHY:
diff -urN linux/drivers/net/tulip/tulip_core.c 
linux/drivers/net/tulip/tulip_core.c
--- linux/drivers/net/tulip/tulip_core.c        2005/03/18 17:37:38     1.63
+++ linux/drivers/net/tulip/tulip_core.c        2005/05/26 09:12:45     1.64
@@ -1104,7 +1104,7 @@
                        if (entry != 0) {
                                /* Avoid a chip errata by prefixing a dummy 
entry. Don't do
                                   this on the ULI526X as it triggers a 
different problem */
-                               if (!(tp->chip_id == ULI526X && (tp->revision = 
0x40 || tp->revision == 0x50))) {
+                               if (!(tp->chip_id == ULI526X && (tp->revision 
== 0x40 || tp->revision == 0x50))) {
                                        tp->tx_buffers[entry].skb = NULL;
                                        tp->tx_buffers[entry].mapping = 0;
                                        tp->tx_ring[entry].length =
diff -urN linux/drivers/net/wireless/Kconfig linux/drivers/net/wireless/Kconfig
--- linux/drivers/net/wireless/Kconfig  2005/01/25 04:28:36     1.18
+++ linux/drivers/net/wireless/Kconfig  2005/05/26 09:12:45     1.19
@@ -323,7 +323,7 @@
          For a complete list of supported cards visit <http://prism54.org>.
          Here is the latest confirmed list of supported cards:
 
-         3com OfficeConnect 11g Cardbus Card aka 3CRWE154G72
+         3com OfficeConnect 11g Cardbus Card aka 3CRWE154G72 (version 1)
          Allnet ALL0271 PCI Card
          Compex WL54G Cardbus Card
          Corega CG-WLCB54GT Cardbus Card
diff -urN linux/drivers/pci/hotplug.c linux/drivers/pci/hotplug.c
--- linux/drivers/pci/hotplug.c 2005/05/19 12:08:27     1.20
+++ linux/drivers/pci/hotplug.c 2005/05/26 09:12:45     1.21
@@ -52,116 +52,17 @@
        if ((buffer_size - length <= 0) || (i >= num_envp))
                return -ENOMEM;
 
+       envp[i++] = scratch;
+       length += scnprintf (scratch, buffer_size - length,
+                           
"MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x\n",
+                           pdev->vendor, pdev->device,
+                           pdev->subsystem_vendor, pdev->subsystem_device,
+                           (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
+                           (u8)(pdev->class));
+       if ((buffer_size - length <= 0) || (i >= num_envp))
+               return -ENOMEM;
+
        envp[i] = NULL;
 
        return 0;
 }
-
-static int pci_visit_bus (struct pci_visit * fn, struct pci_bus_wrapped 
*wrapped_bus, struct pci_dev_wrapped *wrapped_parent)
-{
-       struct list_head *ln;
-       struct pci_dev *dev;
-       struct pci_dev_wrapped wrapped_dev;
-       int result = 0;
-
-       pr_debug("PCI: Scanning bus %04x:%02x\n", 
pci_domain_nr(wrapped_bus->bus),
-               wrapped_bus->bus->number);
-
-       if (fn->pre_visit_pci_bus) {
-               result = fn->pre_visit_pci_bus(wrapped_bus, wrapped_parent);
-               if (result)
-                       return result;
-       }
-
-       ln = wrapped_bus->bus->devices.next; 
-       while (ln != &wrapped_bus->bus->devices) {
-               dev = pci_dev_b(ln);
-               ln = ln->next;
-
-               memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));
-               wrapped_dev.dev = dev;
-
-               result = pci_visit_dev(fn, &wrapped_dev, wrapped_bus);
-               if (result)
-                       return result;
-       }
-
-       if (fn->post_visit_pci_bus)
-               result = fn->post_visit_pci_bus(wrapped_bus, wrapped_parent);
-
-       return result;
-}
-
-static int pci_visit_bridge (struct pci_visit * fn,
-                            struct pci_dev_wrapped *wrapped_dev,
-                            struct pci_bus_wrapped *wrapped_parent)
-{
-       struct pci_bus *bus;
-       struct pci_bus_wrapped wrapped_bus;
-       int result = 0;
-
-       pr_debug("PCI: Scanning bridge %s\n", pci_name(wrapped_dev->dev));
-
-       if (fn->visit_pci_dev) {
-               result = fn->visit_pci_dev(wrapped_dev, wrapped_parent);
-               if (result)
-                       return result;
-       }
-
-       bus = wrapped_dev->dev->subordinate;
-       if (bus) {
-               memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
-               wrapped_bus.bus = bus;
-
-               result = pci_visit_bus(fn, &wrapped_bus, wrapped_dev);
-       }
-       return result;
-}
-
-/**
- * pci_visit_dev - scans the pci buses.
- * @fn: callback functions that are called while visiting
- * @wrapped_dev: the device to scan
- * @wrapped_parent: the bus where @wrapped_dev is connected to
- *
- * Every bus and every function is presented to a custom
- * function that can act upon it.
- */
-int pci_visit_dev(struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev,
-                 struct pci_bus_wrapped *wrapped_parent)
-{
-       struct pci_dev* dev = wrapped_dev ? wrapped_dev->dev : NULL;
-       int result = 0;
-
-       if (!dev)
-               return 0;
-
-       if (fn->pre_visit_pci_dev) {
-               result = fn->pre_visit_pci_dev(wrapped_dev, wrapped_parent);
-               if (result)
-                       return result;
-       }
-
-       switch (dev->class >> 8) {
-               case PCI_CLASS_BRIDGE_PCI:
-                       result = pci_visit_bridge(fn, wrapped_dev,
-                                                 wrapped_parent);
-                       if (result)
-                               return result;
-                       break;
-               default:
-                       pr_debug("PCI: Scanning device %s\n", pci_name(dev));
-                       if (fn->visit_pci_dev) {
-                               result = fn->visit_pci_dev (wrapped_dev,
-                                                           wrapped_parent);
-                               if (result)
-                                       return result;
-                       }
-       }
-
-       if (fn->post_visit_pci_dev)
-               result = fn->post_visit_pci_dev(wrapped_dev, wrapped_parent);
-
-       return result;
-}
-EXPORT_SYMBOL(pci_visit_dev);
diff -urN linux/drivers/pci/pci-sysfs.c linux/drivers/pci/pci-sysfs.c
--- linux/drivers/pci/pci-sysfs.c       2005/05/19 12:08:27     1.15
+++ linux/drivers/pci/pci-sysfs.c       2005/05/26 09:12:45     1.16
@@ -73,6 +73,17 @@
        return (str - buf);
 }
 
+static ssize_t modalias_show(struct device *dev, char *buf)
+{
+       struct pci_dev *pci_dev = to_pci_dev(dev);
+
+       return sprintf(buf, "pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x\n",
+                      pci_dev->vendor, pci_dev->device,
+                      pci_dev->subsystem_vendor, pci_dev->subsystem_device,
+                      (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8),
+                      (u8)(pci_dev->class));
+}
+
 struct device_attribute pci_dev_attrs[] = {
        __ATTR_RO(resource),
        __ATTR_RO(vendor),
@@ -82,6 +93,7 @@
        __ATTR_RO(class),
        __ATTR_RO(irq),
        __ATTR_RO(local_cpus),
+       __ATTR_RO(modalias),
        __ATTR_NULL,
 };
 
diff -urN linux/drivers/pci/pci.h linux/drivers/pci/pci.h
--- linux/drivers/pci/pci.h     2005/03/18 17:37:42     1.11
+++ linux/drivers/pci/pci.h     2005/05/26 09:12:45     1.12
@@ -32,33 +32,6 @@
 extern unsigned char pci_bus_max_busnr(struct pci_bus *bus);
 extern int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, 
int cap);
 
-struct pci_dev_wrapped {
-       struct pci_dev  *dev;
-       void            *data;
-};
-
-struct pci_bus_wrapped {
-       struct pci_bus  *bus;
-       void            *data;
-};
-
-struct pci_visit {
-       int (* pre_visit_pci_bus)       (struct pci_bus_wrapped *,
-                                        struct pci_dev_wrapped *);
-       int (* post_visit_pci_bus)      (struct pci_bus_wrapped *,
-                                        struct pci_dev_wrapped *);
-
-       int (* pre_visit_pci_dev)       (struct pci_dev_wrapped *,
-                                        struct pci_bus_wrapped *);
-       int (* visit_pci_dev)           (struct pci_dev_wrapped *,
-                                        struct pci_bus_wrapped *);
-       int (* post_visit_pci_dev)      (struct pci_dev_wrapped *,
-                                        struct pci_bus_wrapped *);
-};
-
-extern int pci_visit_dev(struct pci_visit *fn,
-                        struct pci_dev_wrapped *wrapped_dev,
-                        struct pci_bus_wrapped *wrapped_parent);
 extern void pci_remove_legacy_files(struct pci_bus *bus);
 
 /* Lock for read/write access to pci device and bus lists */
diff -urN linux/drivers/pci/hotplug/cpci_hotplug.h 
linux/drivers/pci/hotplug/cpci_hotplug.h
--- linux/drivers/pci/hotplug/cpci_hotplug.h    2004/06/06 02:12:46     1.4
+++ linux/drivers/pci/hotplug/cpci_hotplug.h    2005/05/26 09:12:45     1.5
@@ -31,7 +31,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 
-/* PICMG 2.12 R2.0 HS CSR bits: */
+/* PICMG 2.1 R2.0 HS CSR bits: */
 #define HS_CSR_INS     0x0080
 #define HS_CSR_EXT     0x0040
 #define HS_CSR_PI      0x0030
diff -urN linux/drivers/pci/hotplug/cpci_hotplug_core.c 
linux/drivers/pci/hotplug/cpci_hotplug_core.c
--- linux/drivers/pci/hotplug/cpci_hotplug_core.c       2004/08/24 15:10:11     
1.7
+++ linux/drivers/pci/hotplug/cpci_hotplug_core.c       2005/05/26 09:12:45     
1.8
@@ -33,11 +33,11 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
+#include <asm/atomic.h>
 #include <linux/delay.h>
 #include "pci_hotplug.h"
 #include "cpci_hotplug.h"
 
-#define DRIVER_VERSION "0.2"
 #define DRIVER_AUTHOR  "Scott Murray <scottm@somanetworks.com>"
 #define DRIVER_DESC    "CompactPCI Hot Plug Core"
 
@@ -54,9 +54,10 @@
 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , 
## arg)
 
 /* local variables */
-static spinlock_t list_lock;
+static DECLARE_RWSEM(list_rwsem);
 static LIST_HEAD(slot_list);
 static int slots;
+static atomic_t extracting;
 int cpci_debug;
 static struct cpci_hp_controller *controller;
 static struct semaphore event_semaphore;       /* mutex for process loop (up 
if something to process) */
@@ -68,6 +69,8 @@
 static int set_attention_status(struct hotplug_slot *slot, u8 value);
 static int get_power_status(struct hotplug_slot *slot, u8 * value);
 static int get_attention_status(struct hotplug_slot *slot, u8 * value);
+static int get_adapter_status(struct hotplug_slot *slot, u8 * value);
+static int get_latch_status(struct hotplug_slot *slot, u8 * value);
 
 static struct hotplug_slot_ops cpci_hotplug_slot_ops = {
        .owner = THIS_MODULE,
@@ -76,6 +79,8 @@
        .set_attention_status = set_attention_status,
        .get_power_status = get_power_status,
        .get_attention_status = get_attention_status,
+       .get_adapter_status = get_adapter_status,
+       .get_latch_status = get_latch_status,
 };
 
 static int
@@ -148,8 +153,10 @@
                warn("failure to update adapter file");
        }
 
-       slot->extracting = 0;
-
+       if(slot->extracting) {
+               slot->extracting = 0;
+               atomic_dec(&extracting);
+       }
        return retval;
 }
 
@@ -188,6 +195,20 @@
        return cpci_set_attention_status(hotplug_slot->private, status);
 }
 
+static int
+get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value)
+{
+       *value = hotplug_slot->info->adapter_status;
+       return 0;
+}
+
+static int
+get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value)
+{
+       *value = hotplug_slot->info->latch_status;
+       return 0;
+}
+
 static void release_slot(struct hotplug_slot *hotplug_slot)
 {
        struct slot *slot = hotplug_slot->private;
@@ -273,10 +294,10 @@
                }
 
                /* Add slot to our internal list */
-               spin_lock(&list_lock);
+               down_write(&list_rwsem);
                list_add(&slot->slot_list, &slot_list);
                slots++;
-               spin_unlock(&list_lock);
+               up_write(&list_rwsem);
        }
        return 0;
 error_name:
@@ -299,9 +320,9 @@
        struct list_head *next;
        int status;
 
-       spin_lock(&list_lock);
+       down_write(&list_rwsem);
        if(!slots) {
-               spin_unlock(&list_lock);
+               up_write(&list_rwsem);
                return -1;
        }
        list_for_each_safe(tmp, next, &slot_list) {
@@ -319,7 +340,7 @@
                        slots--;
                }
        }
-       spin_unlock(&list_lock);
+       up_write(&list_rwsem);
        return 0;
 }
 
@@ -347,7 +368,7 @@
 }
 
 /*
- * According to PICMG 2.12 R2.0, section 6.3.2, upon
+ * According to PICMG 2.1 R2.0, section 6.3.2, upon
  * initialization, the system driver shall clear the
  * INS bits of the cold-inserted devices.
  */
@@ -359,9 +380,9 @@
        struct pci_dev* dev;
 
        dbg("%s - enter", __FUNCTION__);
-       spin_lock(&list_lock);
+       down_read(&list_rwsem);
        if(!slots) {
-               spin_unlock(&list_lock);
+               up_read(&list_rwsem);
                return -1;
        }
        list_for_each(tmp, &slot_list) {
@@ -386,7 +407,7 @@
                        }
                }
        }
-       spin_unlock(&list_lock);
+       up_read(&list_rwsem);
        dbg("%s - exit", __FUNCTION__);
        return 0;
 }
@@ -398,10 +419,11 @@
        struct list_head *tmp;
        int extracted;
        int inserted;
+       u16 hs_csr;
 
-       spin_lock(&list_lock);
+       down_read(&list_rwsem);
        if(!slots) {
-               spin_unlock(&list_lock);
+               up_read(&list_rwsem);
                err("no slots registered, shutting down");
                return -1;
        }
@@ -411,8 +433,6 @@
                dbg("%s - looking at slot %s",
                    __FUNCTION__, slot->hotplug_slot->name);
                if(cpci_check_and_clear_ins(slot)) {
-                       u16 hs_csr;
-
                        /* Some broken hardware (e.g. PLX 9054AB) asserts ENUM# 
twice... */
                        if(slot->dev) {
                                warn("slot %s already inserted", 
slot->hotplug_slot->name);
@@ -462,8 +482,6 @@
 
                        inserted++;
                } else if(cpci_check_ext(slot)) {
-                       u16 hs_csr;
-
                        /* Process extraction request */
                        dbg("%s - slot %s extracted",
                            __FUNCTION__, slot->hotplug_slot->name);
@@ -476,20 +494,40 @@
                        if(!slot->extracting) {
                                if(update_latch_status(slot->hotplug_slot, 0)) {
                                        warn("failure to update latch file");
+
                                }
+                               atomic_inc(&extracting);
                                slot->extracting = 1;
                        }
                        extracted++;
+               } else if(slot->extracting) {
+                       hs_csr = cpci_get_hs_csr(slot);
+                       if(hs_csr == 0xffff) {
+                               /*
+                                * Hmmm, we're likely hosed at this point, 
should we
+                                * bother trying to tell the driver or not?
+                                */
+                               err("card in slot %s was improperly removed",
+                                   slot->hotplug_slot->name);
+                               if(update_adapter_status(slot->hotplug_slot, 
0)) {
+                                       warn("failure to update adapter file");
+                               }
+                               slot->extracting = 0;
+                               atomic_dec(&extracting);
+                       }
                }
        }
-       spin_unlock(&list_lock);
+       up_read(&list_rwsem);
+       dbg("inserted=%d, extracted=%d, extracting=%d",
+           inserted, extracted, atomic_read(&extracting));
        if(inserted || extracted) {
                return extracted;
        }
-       else {
+       else if(!atomic_read(&extracting)) {
                err("cannot find ENUM# source, shutting down");
                return -1;
        }
+       return 0;
 }
 
 /* This is the interrupt mode worker thread body */
@@ -497,8 +535,6 @@
 event_thread(void *data)
 {
        int rc;
-       struct slot *slot;
-       struct list_head *tmp;
 
        lock_kernel();
        daemonize("cpci_hp_eventd");
@@ -512,39 +548,22 @@
                    thread_finished);
                if(thread_finished || signal_pending(current))
                        break;
-               while(controller->ops->query_enum()) {
+               do {
                        rc = check_slots();
-                       if (rc > 0)
+                       if (rc > 0) {
                                /* Give userspace a chance to handle extraction 
*/
                                msleep(500);
-                       else if (rc < 0) {
+                       } else if (rc < 0) {
                                dbg("%s - error checking slots", __FUNCTION__);
                                thread_finished = 1;
                                break;
                        }
-               }
-               /* Check for someone yanking out a board */
-               list_for_each(tmp, &slot_list) {
-                       slot = list_entry(tmp, struct slot, slot_list);
-                       if(slot->extracting) {
-                               /*
-                                * Hmmm, we're likely hosed at this point, 
should we
-                                * bother trying to tell the driver or not?
-                                */
-                               err("card in slot %s was improperly removed",
-                                   slot->hotplug_slot->name);
-                               if(update_adapter_status(slot->hotplug_slot, 
0)) {
-                                       warn("failure to update adapter file");
-                               }
-                               slot->extracting = 0;
-                       }
-               }
+               } while(atomic_read(&extracting) != 0);
 
                /* Re-enable ENUM# interrupt */
                dbg("%s - re-enabling irq", __FUNCTION__);
                controller->ops->enable_irq();
        }
-
        dbg("%s - event thread signals exit", __FUNCTION__);
        up(&thread_exit);
        return 0;
@@ -555,8 +574,6 @@
 poll_thread(void *data)
 {
        int rc;
-       struct slot *slot;
-       struct list_head *tmp;
 
        lock_kernel();
        daemonize("cpci_hp_polld");
@@ -565,35 +582,19 @@
        while(1) {
                if(thread_finished || signal_pending(current))
                        break;
-
-               while(controller->ops->query_enum()) {
-                       rc = check_slots();
-                       if(rc > 0)
-                               /* Give userspace a chance to handle extraction 
*/
-                               msleep(500);
-                       else if (rc < 0) {
-                               dbg("%s - error checking slots", __FUNCTION__);
-                               thread_finished = 1;
-                               break;
-                       }
-               }
-               /* Check for someone yanking out a board */
-               list_for_each(tmp, &slot_list) {
-                       slot = list_entry(tmp, struct slot, slot_list);
-                       if(slot->extracting) {
-                               /*
-                                * Hmmm, we're likely hosed at this point, 
should we
-                                * bother trying to tell the driver or not?
-                                */
-                               err("card in slot %s was improperly removed",
-                                   slot->hotplug_slot->name);
-                               if(update_adapter_status(slot->hotplug_slot, 
0)) {
-                                       warn("failure to update adapter file");
+               if(controller->ops->query_enum()) {
+                       do {
+                               rc = check_slots();
+                               if(rc > 0) {
+                                       /* Give userspace a chance to handle 
extraction */
+                                       msleep(500);
+                               } else if(rc < 0) {
+                                       dbg("%s - error checking slots", 
__FUNCTION__);
+                                       thread_finished = 1;
+                                       break;
                                }
-                               slot->extracting = 0;
-                       }
+                       } while(atomic_read(&extracting) != 0);
                }
-
                msleep(100);
        }
        dbg("poll thread signals exit");
@@ -667,6 +668,9 @@
        int status = 0;
 
        if(controller) {
+               if(atomic_read(&extracting) != 0) {
+                       return -EBUSY;
+               }
                if(!thread_finished) {
                        cpci_stop_thread();
                }
@@ -691,12 +695,12 @@
                return -ENODEV;
        }
 
-       spin_lock(&list_lock);
-       if(!slots) {
-               spin_unlock(&list_lock);
+       down_read(&list_rwsem);
+       if(list_empty(&slot_list)) {
+               up_read(&list_rwsem);
                return -ENODEV;
        }
-       spin_unlock(&list_lock);
+       up_read(&list_rwsem);
 
        if(first) {
                status = init_slots();
@@ -727,7 +731,9 @@
        if(!controller) {
                return -ENODEV;
        }
-
+       if(atomic_read(&extracting) != 0) {
+               return -EBUSY;
+       }
        if(controller->irq) {
                /* Stop enum interrupt processing */
                dbg("%s - disabling irq", __FUNCTION__);
@@ -747,7 +753,7 @@
         * Unregister all of our slots with the pci_hotplug subsystem,
         * and free up all memory that we had allocated.
         */
-       spin_lock(&list_lock);
+       down_write(&list_rwsem);
        if(!slots) {
                goto null_cleanup;
        }
@@ -761,17 +767,14 @@
                kfree(slot);
        }
       null_cleanup:
-       spin_unlock(&list_lock);
+       up_write(&list_rwsem);
        return;
 }
 
 int __init
 cpci_hotplug_init(int debug)
 {
-       spin_lock_init(&list_lock);
        cpci_debug = debug;
-
-       info(DRIVER_DESC " version: " DRIVER_VERSION);
        return 0;
 }
 
diff -urN linux/drivers/pci/hotplug/cpci_hotplug_pci.c 
linux/drivers/pci/hotplug/cpci_hotplug_pci.c
--- linux/drivers/pci/hotplug/cpci_hotplug_pci.c        2005/01/13 14:06:18     
1.6
+++ linux/drivers/pci/hotplug/cpci_hotplug_pci.c        2005/05/26 09:12:45     
1.7
@@ -32,11 +32,7 @@
 #include "pci_hotplug.h"
 #include "cpci_hotplug.h"
 
-#if !defined(MODULE)
 #define MY_NAME        "cpci_hotplug"
-#else
-#define MY_NAME        THIS_MODULE->name
-#endif
 
 extern int cpci_debug;
 
@@ -127,38 +123,6 @@
        return hs_csr;
 }
 
-#if 0
-u16 cpci_set_hs_csr(struct slot* slot, u16 hs_csr)
-{
-       int hs_cap;
-       u16 new_hs_csr;
-
-       hs_cap = pci_bus_find_capability(slot->bus,
-                                        slot->devfn,
-                                        PCI_CAP_ID_CHSWP);
-       if(!hs_cap) {
-               return 0xFFFF;
-       }
-
-       /* Write out the new value */
-       if(pci_bus_write_config_word(slot->bus,
-                                     slot->devfn,
-                                     hs_cap + 2,
-                                     hs_csr)) {
-               return 0xFFFF;
-       }
-
-       /* Read back what we just wrote out */
-       if(pci_bus_read_config_word(slot->bus,
-                                    slot->devfn,
-                                    hs_cap + 2,
-                                    &new_hs_csr)) {
-               return 0xFFFF;
-       }
-       return new_hs_csr;
-}
-#endif
-
 int cpci_check_and_clear_ins(struct slot* slot)
 {
        int hs_cap;
@@ -261,7 +225,6 @@
                return -ENODEV;
        }
        if((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) {
-               /* Set LOO */
                hs_csr |= HS_CSR_LOO;
                if(pci_bus_write_config_word(slot->bus,
                                              slot->devfn,
@@ -293,7 +256,6 @@
                return -ENODEV;
        }
        if(hs_csr & HS_CSR_LOO) {
-               /* Clear LOO */
                hs_csr &= ~HS_CSR_LOO;
                if(pci_bus_write_config_word(slot->bus,
                                              slot->devfn,
@@ -312,257 +274,23 @@
  * Device configuration functions
  */
 
-static int cpci_configure_dev(struct pci_bus *bus, struct pci_dev *dev)
-{
-       u8 irq_pin;
-       int r;
-
-       dbg("%s - enter", __FUNCTION__);
-
-       /* NOTE: device already setup from prior scan */
-
-       /* FIXME: How would we know if we need to enable the expansion ROM? */
-       pci_write_config_word(dev, PCI_ROM_ADDRESS, 0x00L);
-
-       /* Assign resources */
-       dbg("assigning resources for %02x:%02x.%x",
-           dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
-       for (r = 0; r < 6; r++) {
-               struct resource *res = dev->resource + r;
-               if(res->flags)
-                       pci_assign_resource(dev, r);
-       }
-       dbg("finished assigning resources for %02x:%02x.%x",
-           dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
-
-       /* Does this function have an interrupt at all? */
-       dbg("checking for function interrupt");
-       pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
-       if(irq_pin) {
-               dbg("function uses interrupt pin %d", irq_pin);
-       }
-
-       /*
-        * Need to explicitly set irq field to 0 so that it'll get assigned
-        * by the pcibios platform dependent code called by pci_enable_device.
-        */
-       dev->irq = 0;
-
-       dbg("enabling device");
-       pci_enable_device(dev); /* XXX check return */
-       dbg("now dev->irq = %d", dev->irq);
-       if(irq_pin && dev->irq) {
-               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-       }
-
-       /* Can't use pci_insert_device at the moment, do it manually for now */
-       pci_proc_attach_device(dev);
-       dbg("notifying drivers");
-       //pci_announce_device_to_drivers(dev);
-       dbg("%s - exit", __FUNCTION__);
-       return 0;
-}
-
-static int cpci_configure_bridge(struct pci_bus* bus, struct pci_dev* dev)
+static void cpci_enable_device(struct pci_dev *dev)
 {
-       int rc;
-       struct pci_bus* child;
-       struct resource* r;
-       u8 max, n;
-       u16 command;
-
-       dbg("%s - enter", __FUNCTION__);
+       struct pci_bus *bus;
 
-       /* Do basic bridge initialization */
-       rc = pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40);
-       if(rc) {
-               printk(KERN_ERR "%s - write of PCI_LATENCY_TIMER failed\n", 
__FUNCTION__);
-       }
-       rc = pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 0x40);
-       if(rc) {
-               printk(KERN_ERR "%s - write of PCI_SEC_LATENCY_TIMER failed\n", 
__FUNCTION__);
-       }
-       rc = pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 
4);
-       if(rc) {
-               printk(KERN_ERR "%s - write of PCI_CACHE_LINE_SIZE failed\n", 
__FUNCTION__);
-       }
-
-       /*
-        * Set parent bridge's subordinate field so that configuration space
-        * access will work in pci_scan_bridge and friends.
-        */
-       max = pci_max_busnr();
-       bus->subordinate = max + 1;
-       pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, max + 1);
-
-       /* Scan behind bridge */
-       n = pci_scan_bridge(bus, dev, max, 2);
-       child = pci_find_bus(0, max + 1);
-       if (!child)
-               return -ENODEV;
-       pci_proc_attach_bus(child);
-
-       /*
-        * Update parent bridge's subordinate field if there were more bridges
-        * behind the bridge that was scanned.
-        */
-       if(n > max) {
-               bus->subordinate = n;
-               pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, n);
-       }
-
-       /*
-        * Update the bridge resources of the bridge to accommodate devices
-        * behind it.
-        */
-       pci_bus_size_bridges(child);
-       pci_bus_assign_resources(child);
-
-       /* Enable resource mapping via command register */
-       command = PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | 
PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
-       r = child->resource[0];
-       if(r && r->start) {
-               command |= PCI_COMMAND_IO;
-       }
-       r = child->resource[1];
-       if(r && r->start) {
-               command |= PCI_COMMAND_MEMORY;
-       }
-       r = child->resource[2];
-       if(r && r->start) {
-               command |= PCI_COMMAND_MEMORY;
-       }
-       rc = pci_write_config_word(dev, PCI_COMMAND, command);
-       if(rc) {
-               err("Error setting command register");
-               return rc;
-       }
-
-       /* Set bridge control register */
-       command = PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR | 
PCI_BRIDGE_CTL_NO_ISA;
-       rc = pci_write_config_word(dev, PCI_BRIDGE_CONTROL, command);
-       if(rc) {
-               err("Error setting bridge control register");
-               return rc;
-       }
-       dbg("%s - exit", __FUNCTION__);
-       return 0;
-}
-
-static int configure_visit_pci_dev(struct pci_dev_wrapped *wrapped_dev,
-                                  struct pci_bus_wrapped *wrapped_bus)
-{
-       int rc;
-       struct pci_dev *dev = wrapped_dev->dev;
-       struct pci_bus *bus = wrapped_bus->bus;
-       struct slot* slot;
-
-       dbg("%s - enter", __FUNCTION__);
-
-       /*
-        * We need to fix up the hotplug representation with the Linux
-        * representation.
-        */
-       if(wrapped_dev->data) {
-               slot = (struct slot*) wrapped_dev->data;
-               slot->dev = dev;
-       }
-
-       /* If it's a bridge, scan behind it for devices */
+       pci_enable_device(dev);
        if(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-               rc = cpci_configure_bridge(bus, dev);
-               if(rc)
-                       return rc;
-       }
-
-       /* Actually configure device */
-       if(dev) {
-               rc = cpci_configure_dev(bus, dev);
-               if(rc)
-                       return rc;
-       }
-       dbg("%s - exit", __FUNCTION__);
-       return 0;
-}
-
-static int unconfigure_visit_pci_dev_phase2(struct pci_dev_wrapped 
*wrapped_dev,
-                                           struct pci_bus_wrapped *wrapped_bus)
-{
-       struct pci_dev *dev = wrapped_dev->dev;
-       struct slot* slot;
-
-       dbg("%s - enter", __FUNCTION__);
-       if(!dev)
-               return -ENODEV;
-
-       /* Remove the Linux representation */
-       if(pci_remove_device_safe(dev)) {
-               err("Could not remove device\n");
-               return -1;
-       }
-
-       /*
-        * Now remove the hotplug representation.
-        */
-       if(wrapped_dev->data) {
-               slot = (struct slot*) wrapped_dev->data;
-               slot->dev = NULL;
-       } else {
-               dbg("No hotplug representation for %02x:%02x.%x",
-                   dev->bus->number, PCI_SLOT(dev->devfn), 
PCI_FUNC(dev->devfn));
-       }
-       dbg("%s - exit", __FUNCTION__);
-       return 0;
-}
-
-static int unconfigure_visit_pci_bus_phase2(struct pci_bus_wrapped 
*wrapped_bus,
-                                           struct pci_dev_wrapped *wrapped_dev)
-{
-       struct pci_bus *bus = wrapped_bus->bus;
-       struct pci_bus *parent = bus->self->bus;
-
-       dbg("%s - enter", __FUNCTION__);
-
-       /* The cleanup code for proc entries regarding buses should be in the 
kernel... */
-       if(bus->procdir)
-               dbg("detach_pci_bus %s", bus->procdir->name);
-       pci_proc_detach_bus(bus);
-
-       /* The cleanup code should live in the kernel... */
-       bus->self->subordinate = NULL;
-
-       /* unlink from parent bus */
-       list_del(&bus->node);
-
-       /* Now, remove */
-       if(bus)
-               kfree(bus);
-
-       /* Update parent's subordinate field */
-       if(parent) {
-               u8 n = pci_bus_max_busnr(parent);
-               if(n < parent->subordinate) {
-                       parent->subordinate = n;
-                       pci_write_config_byte(parent->self, 
PCI_SUBORDINATE_BUS, n);
+               bus = dev->subordinate;
+               list_for_each_entry(dev, &bus->devices, bus_list) {
+                       cpci_enable_device(dev);
                }
        }
-       dbg("%s - exit", __FUNCTION__);
-       return 0;
 }
 
-static struct pci_visit configure_functions = {
-       .visit_pci_dev = configure_visit_pci_dev,
-};
-
-static struct pci_visit unconfigure_functions_phase2 = {
-       .post_visit_pci_bus = unconfigure_visit_pci_bus_phase2,
-       .post_visit_pci_dev = unconfigure_visit_pci_dev_phase2
-};
-
-
 int cpci_configure_slot(struct slot* slot)
 {
-       int rc = 0;
+       unsigned char busnr;
+       struct pci_bus *child;
 
        dbg("%s - enter", __FUNCTION__);
 
@@ -588,74 +316,44 @@
                slot->dev = pci_find_slot(slot->bus->number, slot->devfn);
                if(slot->dev == NULL) {
                        err("Could not find PCI device for slot %02x", 
slot->number);
-                       return 0;
+                       return 1;
                }
        }
-       dbg("slot->dev = %p", slot->dev);
-       if(slot->dev) {
-               struct pci_dev *dev;
-               struct pci_dev_wrapped wrapped_dev;
-               struct pci_bus_wrapped wrapped_bus;
-               int i;
-
-               memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped));
-               memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped));
-
-               for (i = 0; i < 8; i++) {
-                       dev = pci_find_slot(slot->bus->number,
-                                           
PCI_DEVFN(PCI_SLOT(slot->dev->devfn), i));
-                       if(!dev)
-                               continue;
-                       wrapped_dev.dev = dev;
-                       wrapped_bus.bus = slot->dev->bus;
-                       if(i)
-                               wrapped_dev.data = NULL;
-                       else
-                               wrapped_dev.data = (void*) slot;
-                       rc = pci_visit_dev(&configure_functions, &wrapped_dev, 
&wrapped_bus);
-               }
+
+       if (slot->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+               pci_read_config_byte(slot->dev, PCI_SECONDARY_BUS, &busnr);
+               child = pci_add_new_bus(slot->dev->bus, slot->dev, busnr);
+               pci_do_scan_bus(child);
+               pci_bus_size_bridges(child);
        }
 
-       dbg("%s - exit, rc = %d", __FUNCTION__, rc);
-       return rc;
+       pci_bus_assign_resources(slot->dev->bus);
+
+       cpci_enable_device(slot->dev);
+
+       dbg("%s - exit", __FUNCTION__);
+       return 0;
 }
 
 int cpci_unconfigure_slot(struct slot* slot)
 {
-       int rc = 0;
        int i;
-       struct pci_dev_wrapped wrapped_dev;
-       struct pci_bus_wrapped wrapped_bus;
        struct pci_dev *dev;
 
        dbg("%s - enter", __FUNCTION__);
-
        if(!slot->dev) {
                err("No device for slot %02x\n", slot->number);
                return -ENODEV;
        }
 
-       memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped));
-       memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped));
-
        for (i = 0; i < 8; i++) {
                dev = pci_find_slot(slot->bus->number,
                                    PCI_DEVFN(PCI_SLOT(slot->devfn), i));
                if(dev) {
-                       wrapped_dev.dev = dev;
-                       wrapped_bus.bus = dev->bus;
-                       if(i)
-                               wrapped_dev.data = NULL;
-                       else
-                               wrapped_dev.data = (void*) slot;
-                       dbg("%s - unconfigure phase 2", __FUNCTION__);
-                       rc = pci_visit_dev(&unconfigure_functions_phase2,
-                                          &wrapped_dev,
-                                          &wrapped_bus);
-                       if(rc)
-                               break;
+                       pci_remove_bus_device(dev);
+                       slot->dev = NULL;
                }
        }
-       dbg("%s - exit, rc = %d", __FUNCTION__, rc);
-       return rc;
+       dbg("%s - exit", __FUNCTION__);
+       return 0;
 }
diff -urN linux/drivers/pci/hotplug/pciehp.h linux/drivers/pci/hotplug/pciehp.h
--- linux/drivers/pci/hotplug/pciehp.h  2005/01/25 04:28:38     1.6
+++ linux/drivers/pci/hotplug/pciehp.h  2005/05/26 09:12:45     1.7
@@ -130,6 +130,7 @@
        u8 slot_bus;            /* Bus where the slots handled by this 
controller sit */
        u8 ctrlcap;
        u16 vendor_id;
+       u8 cap_base;
 };
 
 struct irq_mapping {
diff -urN linux/drivers/pci/hotplug/pciehp_core.c 
linux/drivers/pci/hotplug/pciehp_core.c
--- linux/drivers/pci/hotplug/pciehp_core.c     2005/05/19 12:08:28     1.9
+++ linux/drivers/pci/hotplug/pciehp_core.c     2005/05/26 09:12:45     1.10
@@ -607,7 +607,7 @@
 static struct pcie_port_service_id port_pci_ids[] = { { 
        .vendor = PCI_ANY_ID, 
        .device = PCI_ANY_ID,
-       .port_type = PCIE_RC_PORT, 
+       .port_type = PCIE_ANY_PORT,
        .service_type = PCIE_PORT_SERVICE_HP,
        .driver_data =  0, 
        }, { /* end: all zeroes */ }
diff -urN linux/drivers/pci/hotplug/pciehp_hpc.c 
linux/drivers/pci/hotplug/pciehp_hpc.c
--- linux/drivers/pci/hotplug/pciehp_hpc.c      2005/01/25 04:28:38     1.11
+++ linux/drivers/pci/hotplug/pciehp_hpc.c      2005/05/26 09:12:45     1.12
@@ -109,20 +109,20 @@
 };
 static int pcie_cap_base = 0;          /* Base of the PCI Express capability 
item structure */ 
 
-#define PCIE_CAP_ID    ( pcie_cap_base + PCIECAPID )
-#define NXT_CAP_PTR    ( pcie_cap_base + NXTCAPPTR )
-#define CAP_REG                ( pcie_cap_base + CAPREG )
-#define DEV_CAP                ( pcie_cap_base + DEVCAP )
-#define DEV_CTRL       ( pcie_cap_base + DEVCTRL )
-#define DEV_STATUS     ( pcie_cap_base + DEVSTATUS )
-#define LNK_CAP                ( pcie_cap_base + LNKCAP )
-#define LNK_CTRL       ( pcie_cap_base + LNKCTRL )
-#define LNK_STATUS     ( pcie_cap_base + LNKSTATUS )
-#define SLOT_CAP       ( pcie_cap_base + SLOTCAP )
-#define SLOT_CTRL      ( pcie_cap_base + SLOTCTRL )
-#define SLOT_STATUS    ( pcie_cap_base + SLOTSTATUS )
-#define ROOT_CTRL      ( pcie_cap_base + ROOTCTRL )
-#define ROOT_STATUS    ( pcie_cap_base + ROOTSTATUS )
+#define PCIE_CAP_ID(cb)        ( cb + PCIECAPID )
+#define NXT_CAP_PTR(cb)        ( cb + NXTCAPPTR )
+#define CAP_REG(cb)    ( cb + CAPREG )
+#define DEV_CAP(cb)    ( cb + DEVCAP )
+#define DEV_CTRL(cb)   ( cb + DEVCTRL )
+#define DEV_STATUS(cb) ( cb + DEVSTATUS )
+#define LNK_CAP(cb)    ( cb + LNKCAP )
+#define LNK_CTRL(cb)   ( cb + LNKCTRL )
+#define LNK_STATUS(cb) ( cb + LNKSTATUS )
+#define SLOT_CAP(cb)   ( cb + SLOTCAP )
+#define SLOT_CTRL(cb)  ( cb + SLOTCTRL )
+#define SLOT_STATUS(cb)        ( cb + SLOTSTATUS )
+#define ROOT_CTRL(cb)  ( cb + ROOTCTRL )
+#define ROOT_STATUS(cb)        ( cb + ROOTSTATUS )
 
 #define hp_register_read_word(pdev, reg , value)               \
        pci_read_config_word(pdev, reg, &value)
@@ -303,7 +303,7 @@
                return -1;
        }
 
-       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, 
slot_status);
+       retval = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_STATUS(slot->ctrl->cap_base), slot_status);
        if (retval) {
                        err("%s : hp_register_read_word SLOT_STATUS failed\n", 
__FUNCTION__);
                        return retval;
@@ -317,7 +317,7 @@
        }
 
        dbg("%s: Before hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, 
cmd);
-       retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, cmd | 
CMD_CMPL_INTR_ENABLE);
+       retval = hp_register_write_word(php_ctlr->pci_dev, 
SLOT_CTRL(slot->ctrl->cap_base), cmd | CMD_CMPL_INTR_ENABLE);
        if (retval) {
                err("%s : hp_register_write_word SLOT_CTRL failed\n", 
__FUNCTION__);
                return retval;
@@ -342,7 +342,7 @@
                return -1;
        }
        
-       retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, 
lnk_status);
+       retval = hp_register_read_word(php_ctlr->pci_dev, 
LNK_STATUS(ctrl->cap_base), lnk_status);
 
        if (retval) {
                err("%s : hp_register_read_word LNK_STATUS failed\n", 
__FUNCTION__);
@@ -376,14 +376,14 @@
                return -1;
        }
 
-       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+       retval = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        if (retval) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", 
__FUNCTION__);
                return retval;
        }
 
-       dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__,SLOT_CTRL, 
slot_ctrl);
+       dbg("%s: SLOT_CTRL %x, value read %x\n", 
__FUNCTION__,SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6;
 
@@ -423,13 +423,13 @@
                return -1;
        }
 
-       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+       retval = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        if (retval) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", 
__FUNCTION__);
                return retval;
        }
-       dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, 
slot_ctrl);
+       dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, 
SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        pwr_state = (slot_ctrl & PWR_CTRL) >> 10;
 
@@ -463,7 +463,7 @@
                return -1;
        }
 
-       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, 
slot_status);
+       retval = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_STATUS(slot->ctrl->cap_base), slot_status);
 
        if (retval) {
                err("%s : hp_register_read_word SLOT_STATUS failed\n", 
__FUNCTION__);
@@ -490,7 +490,7 @@
                return -1;
        }
 
-       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, 
slot_status);
+       retval = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_STATUS(slot->ctrl->cap_base), slot_status);
 
        if (retval) {
                err("%s : hp_register_read_word SLOT_STATUS failed\n", 
__FUNCTION__);
@@ -518,7 +518,7 @@
                return -1;
        }
 
-       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, 
slot_status);
+       retval = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_STATUS(slot->ctrl->cap_base), slot_status);
 
        if (retval) {
                err("%s : hp_register_read_word SLOT_STATUS failed\n", 
__FUNCTION__);
@@ -549,7 +549,7 @@
                err("%s: Invalid HPC slot number!\n", __FUNCTION__);
                return -1;
        }
-       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+       rc = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        if (rc) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", 
__FUNCTION__);
@@ -574,7 +574,7 @@
                slot_cmd = slot_cmd | HP_INTR_ENABLE; 
 
        pcie_write_cmd(slot, slot_cmd);
-       dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL, 
slot_cmd);
+       dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, 
SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
        
        return rc;
 }
@@ -598,7 +598,7 @@
                return ;
        }
 
-       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+       rc = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        if (rc) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", 
__FUNCTION__);
@@ -611,7 +611,7 @@
 
        pcie_write_cmd(slot, slot_cmd);
 
-       dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, 
slot_cmd);
+       dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, 
SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
        return;
 }
 
@@ -633,7 +633,7 @@
                return ;
        }
 
-       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+       rc = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        if (rc) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", 
__FUNCTION__);
@@ -646,7 +646,7 @@
        if (!pciehp_poll_mode)
                slot_cmd = slot_cmd | HP_INTR_ENABLE; 
        pcie_write_cmd(slot, slot_cmd);
-       dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL, 
slot_cmd);
+       dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, 
SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
 
        return;
 }
@@ -669,7 +669,7 @@
                return ;
        }
 
-       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+       rc = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        if (rc) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", 
__FUNCTION__);
@@ -683,7 +683,7 @@
                slot_cmd = slot_cmd | HP_INTR_ENABLE; 
        pcie_write_cmd(slot, slot_cmd);
 
-       dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, 
slot_cmd);
+       dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, 
SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
        return;
 }
 
@@ -707,7 +707,7 @@
        *first_device_num = 0;
        *num_ctlr_slots = 1; 
 
-       rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP, slot_cap);
+       rc = hp_register_read_dword(php_ctlr->pci_dev, 
SLOT_CAP(ctrl->cap_base), slot_cap);
 
        if (rc) {
                err("%s : hp_register_read_dword SLOT_CAP failed\n", 
__FUNCTION__);
@@ -793,13 +793,13 @@
                return -1;
        }
 
-       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+       retval = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        if (retval) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", 
__FUNCTION__);
                return retval;
        }
-       dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, SLOT_CTRL, 
+       dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, 
SLOT_CTRL(slot->ctrl->cap_base),
                slot_ctrl);
 
        slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON;
@@ -813,7 +813,7 @@
                err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd);
                return -1;
        }
-       dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, 
slot_cmd);
+       dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, 
SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
 
        DBG_LEAVE_ROUTINE
 
@@ -842,13 +842,13 @@
                err("%s: Invalid HPC slot number!\n", __FUNCTION__);
                return -1;
        }
-       retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+       retval = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
 
        if (retval) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", 
__FUNCTION__);
                return retval;
        }
-       dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, SLOT_CTRL, 
+       dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, 
SLOT_CTRL(slot->ctrl->cap_base),
                slot_ctrl);
 
        slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF;
@@ -862,7 +862,7 @@
                err("%s: Write command failed!\n", __FUNCTION__);
                return -1;
        }
-       dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, 
slot_cmd);
+       dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, 
SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
 
        DBG_LEAVE_ROUTINE
 
@@ -900,7 +900,7 @@
                return IRQ_NONE;
        }
 
-       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+       rc = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_STATUS(ctrl->cap_base), slot_status);
        if (rc) {
                err("%s : hp_register_read_word SLOT_STATUS failed\n", 
__FUNCTION__);
                return IRQ_NONE;
@@ -918,7 +918,7 @@
        dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
        /* Mask Hot-plug Interrupt Enable */
        if (!pciehp_poll_mode) {
-               rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, 
temp_word);
+               rc = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_CTRL(ctrl->cap_base), temp_word);
                if (rc) {
                        err("%s : hp_register_read_word SLOT_CTRL failed\n", 
__FUNCTION__);
                        return IRQ_NONE;
@@ -928,14 +928,14 @@
                dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", 
__FUNCTION__, temp_word);
                temp_word = (temp_word & ~HP_INTR_ENABLE & 
~CMD_CMPL_INTR_ENABLE) | 0x00;
 
-               rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, 
temp_word);
+               rc = hp_register_write_word(php_ctlr->pci_dev, 
SLOT_CTRL(ctrl->cap_base), temp_word);
                if (rc) {
                        err("%s : hp_register_write_word SLOT_CTRL failed\n", 
__FUNCTION__);
                        return IRQ_NONE;
                }
                dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", 
__FUNCTION__, temp_word);
                
-               rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, 
slot_status);
+               rc = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_STATUS(ctrl->cap_base), slot_status);
                if (rc) {
                        err("%s : hp_register_read_word SLOT_STATUS failed\n", 
__FUNCTION__);
                        return IRQ_NONE;
@@ -944,7 +944,7 @@
                
                /* Clear command complete interrupt caused by this write */
                temp_word = 0x1f;
-               rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, 
temp_word);
+               rc = hp_register_write_word(php_ctlr->pci_dev, 
SLOT_STATUS(ctrl->cap_base), temp_word);
                if (rc) {
                        err("%s : hp_register_write_word SLOT_STATUS failed\n", 
__FUNCTION__);
                        return IRQ_NONE;
@@ -975,14 +975,14 @@
 
        /* Clear all events after serving them */
        temp_word = 0x1F;
-       rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+       rc = hp_register_write_word(php_ctlr->pci_dev, 
SLOT_STATUS(ctrl->cap_base), temp_word);
        if (rc) {
                err("%s : hp_register_write_word SLOT_STATUS failed\n", 
__FUNCTION__);
                return IRQ_NONE;
        }
        /* Unmask Hot-plug Interrupt Enable */
        if (!pciehp_poll_mode) {
-               rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, 
temp_word);
+               rc = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_CTRL(ctrl->cap_base), temp_word);
                if (rc) {
                        err("%s : hp_register_read_word SLOT_CTRL failed\n", 
__FUNCTION__);
                        return IRQ_NONE;
@@ -992,14 +992,14 @@
                dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", 
__FUNCTION__, temp_word);
                temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
 
-               rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, 
temp_word);
+               rc = hp_register_write_word(php_ctlr->pci_dev, 
SLOT_CTRL(ctrl->cap_base), temp_word);
                if (rc) {
                        err("%s : hp_register_write_word SLOT_CTRL failed\n", 
__FUNCTION__);
                        return IRQ_NONE;
                }
                dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", 
__FUNCTION__, temp_word);   
        
-               rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, 
slot_status);
+               rc = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_STATUS(ctrl->cap_base), slot_status);
                if (rc) {
                        err("%s : hp_register_read_word SLOT_STATUS failed\n", 
__FUNCTION__);
                        return IRQ_NONE;
@@ -1008,7 +1008,7 @@
                
                /* Clear command complete interrupt caused by this write */
                temp_word = 0x1F;
-               rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, 
temp_word);
+               rc = hp_register_write_word(php_ctlr->pci_dev, 
SLOT_STATUS(ctrl->cap_base), temp_word);
                if (rc) {
                        err("%s : hp_register_write_word SLOT_STATUS failed\n", 
__FUNCTION__);
                        return IRQ_NONE;
@@ -1038,7 +1038,7 @@
                return -1;
        }
 
-       retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP, lnk_cap);
+       retval = hp_register_read_dword(php_ctlr->pci_dev, 
LNK_CAP(slot->ctrl->cap_base), lnk_cap);
 
        if (retval) {
                err("%s : hp_register_read_dword  LNK_CAP failed\n", 
__FUNCTION__);
@@ -1079,7 +1079,7 @@
                return -1;
        }
 
-       retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP, lnk_cap);
+       retval = hp_register_read_dword(php_ctlr->pci_dev, 
LNK_CAP(slot->ctrl->cap_base), lnk_cap);
 
        if (retval) {
                err("%s : hp_register_read_dword  LNK_CAP failed\n", 
__FUNCTION__);
@@ -1141,7 +1141,7 @@
                return -1;
        }
 
-       retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, 
lnk_status);
+       retval = hp_register_read_word(php_ctlr->pci_dev, 
LNK_STATUS(slot->ctrl->cap_base), lnk_status);
 
        if (retval) {
                err("%s : hp_register_read_word LNK_STATUS failed\n", 
__FUNCTION__);
@@ -1182,7 +1182,7 @@
                return -1;
        }
 
-       retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, 
lnk_status);
+       retval = hp_register_read_word(php_ctlr->pci_dev, 
LNK_STATUS(slot->ctrl->cap_base), lnk_status);
 
        if (retval) {
                err("%s : hp_register_read_word LNK_STATUS failed\n", 
__FUNCTION__);
@@ -1292,47 +1292,48 @@
                goto abort_free_ctlr;
        }
 
-       pcie_cap_base = cap_base;
+       ctrl->cap_base = cap_base;
 
        dbg("%s: pcie_cap_base %x\n", __FUNCTION__, pcie_cap_base);
 
-       rc = hp_register_read_word(pdev, CAP_REG, cap_reg);
+       rc = hp_register_read_word(pdev, CAP_REG(ctrl->cap_base), cap_reg);
        if (rc) {
                err("%s : hp_register_read_word CAP_REG failed\n", 
__FUNCTION__);
                goto abort_free_ctlr;
        }
-       dbg("%s: CAP_REG offset %x cap_reg %x\n", __FUNCTION__, CAP_REG, 
cap_reg);
+       dbg("%s: CAP_REG offset %x cap_reg %x\n", __FUNCTION__, 
CAP_REG(ctrl->cap_base), cap_reg);
 
-       if (((cap_reg & SLOT_IMPL) == 0) || ((cap_reg & DEV_PORT_TYPE) != 
0x0040)){
+       if (((cap_reg & SLOT_IMPL) == 0) || (((cap_reg & DEV_PORT_TYPE) != 
0x0040)
+               && ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {
                dbg("%s : This is not a root port or the port is not connected 
to a slot\n", __FUNCTION__);
                goto abort_free_ctlr;
        }
 
-       rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP, slot_cap);
+       rc = hp_register_read_dword(php_ctlr->pci_dev, 
SLOT_CAP(ctrl->cap_base), slot_cap);
        if (rc) {
                err("%s : hp_register_read_word CAP_REG failed\n", 
__FUNCTION__);
                goto abort_free_ctlr;
        }
-       dbg("%s: SLOT_CAP offset %x slot_cap %x\n", __FUNCTION__, SLOT_CAP, 
slot_cap);
+       dbg("%s: SLOT_CAP offset %x slot_cap %x\n", __FUNCTION__, 
SLOT_CAP(ctrl->cap_base), slot_cap);
 
        if (!(slot_cap & HP_CAP)) {
                dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);
                goto abort_free_ctlr;
        }
        /* For debugging purpose */
-       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+       rc = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_STATUS(ctrl->cap_base), slot_status);
        if (rc) {
                err("%s : hp_register_read_word SLOT_STATUS failed\n", 
__FUNCTION__);
                goto abort_free_ctlr;
        }
-       dbg("%s: SLOT_STATUS offset %x slot_status %x\n", __FUNCTION__, 
SLOT_STATUS, slot_status);
+       dbg("%s: SLOT_STATUS offset %x slot_status %x\n", __FUNCTION__, 
SLOT_STATUS(ctrl->cap_base), slot_status);
 
-       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+       rc = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_CTRL(ctrl->cap_base), slot_ctrl);
        if (rc) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", 
__FUNCTION__);
                goto abort_free_ctlr;
        }
-       dbg("%s: SLOT_CTRL offset %x slot_ctrl %x\n", __FUNCTION__, SLOT_CTRL, 
slot_ctrl);
+       dbg("%s: SLOT_CTRL offset %x slot_ctrl %x\n", __FUNCTION__, 
SLOT_CTRL(ctrl->cap_base), slot_ctrl);
 
        if (first) {
                spin_lock_init(&hpc_event_lock);
@@ -1372,36 +1373,37 @@
        php_ctlr->num_slots = 1;
 
        /* Mask Hot-plug Interrupt Enable */
-       rc = hp_register_read_word(pdev, SLOT_CTRL, temp_word);
+       rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
        if (rc) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", 
__FUNCTION__);
                goto abort_free_ctlr;
        }
 
-       dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, 
temp_word);
+       dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, 
SLOT_CTRL(ctrl->cap_base), temp_word);
        temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 
0x00;
 
-       rc = hp_register_write_word(pdev, SLOT_CTRL, temp_word);
+       rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
        if (rc) {
                err("%s : hp_register_write_word SLOT_CTRL failed\n", 
__FUNCTION__);
                goto abort_free_ctlr;
        }
        dbg("%s : Mask HPIE hp_register_write_word SLOT_CTRL %x\n", 
__FUNCTION__, temp_word);
 
-       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+       rc = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_STATUS(ctrl->cap_base), slot_status);
        if (rc) {
                err("%s : hp_register_read_word SLOT_STATUS failed\n", 
__FUNCTION__);
                goto abort_free_ctlr;
        }
-       dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", 
__FUNCTION__, SLOT_STATUS, slot_status);
+       dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", 
__FUNCTION__, SLOT_STATUS(ctrl->cap_base)
+               , slot_status);
 
        temp_word = 0x1F; /* Clear all events */
-       rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+       rc = hp_register_write_word(php_ctlr->pci_dev, 
SLOT_STATUS(ctrl->cap_base), temp_word);
        if (rc) {
                err("%s : hp_register_write_word SLOT_STATUS failed\n", 
__FUNCTION__);
                goto abort_free_ctlr;
        }
-       dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, 
SLOT_STATUS, temp_word);
+       dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, 
SLOT_STATUS(ctrl->cap_base), temp_word);
 
        if (pciehp_poll_mode)  {/* Install interrupt polling code */
                /* Install and start the interrupt polling timer */
@@ -1417,12 +1419,12 @@
                }
        }
 
-       rc = hp_register_read_word(pdev, SLOT_CTRL, temp_word);
+       rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
        if (rc) {
                err("%s : hp_register_read_word SLOT_CTRL failed\n", 
__FUNCTION__);
                goto abort_free_ctlr;
        }
-       dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, 
temp_word);
+       dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, 
SLOT_CTRL(ctrl->cap_base), temp_word);
        dbg("%s: slot_cap %x\n", __FUNCTION__, slot_cap);
 
        intr_enable = intr_enable | PRSN_DETECT_ENABLE;
@@ -1446,27 +1448,27 @@
        dbg("%s: temp_word %x\n", __FUNCTION__, temp_word);
 
        /* Unmask Hot-plug Interrupt Enable for the interrupt notification 
mechanism case */
-       rc = hp_register_write_word(pdev, SLOT_CTRL, temp_word);
+       rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
        if (rc) {
                err("%s : hp_register_write_word SLOT_CTRL failed\n", 
__FUNCTION__);
                goto abort_free_ctlr;
        }
        dbg("%s : Unmask HPIE hp_register_write_word SLOT_CTRL with %x\n", 
__FUNCTION__, temp_word);
-       rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+       rc = hp_register_read_word(php_ctlr->pci_dev, 
SLOT_STATUS(ctrl->cap_base), slot_status);
        if (rc) {
                err("%s : hp_register_read_word SLOT_STATUS failed\n", 
__FUNCTION__);
                goto abort_free_ctlr;
        }
        dbg("%s: Unmask HPIE SLOT_STATUS offset %x reads slot_status %x\n", 
__FUNCTION__, 
-               SLOT_STATUS, slot_status);
+               SLOT_STATUS(ctrl->cap_base), slot_status);
        
        temp_word =  0x1F; /* Clear all events */
-       rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+       rc = hp_register_write_word(php_ctlr->pci_dev, 
SLOT_STATUS(ctrl->cap_base), temp_word);
        if (rc) {
                err("%s : hp_register_write_word SLOT_STATUS failed\n", 
__FUNCTION__);
                goto abort_free_ctlr;
        }
-       dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, 
SLOT_STATUS, temp_word);
+       dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, 
SLOT_STATUS(ctrl->cap_base), temp_word);
        
        /*  Add this HPC instance into the HPC list */
        spin_lock(&list_lock);
diff -urN linux/drivers/pci/hotplug/shpchp_core.c 
linux/drivers/pci/hotplug/shpchp_core.c
--- linux/drivers/pci/hotplug/shpchp_core.c     2005/01/13 14:06:18     1.5
+++ linux/drivers/pci/hotplug/shpchp_core.c     2005/05/26 09:12:45     1.6
@@ -95,7 +95,7 @@
  */
 static void release_slot(struct hotplug_slot *hotplug_slot)
 {
-       struct slot *slot = (struct slot *)hotplug_slot->private;
+       struct slot *slot = hotplug_slot->private;
 
        dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
 
diff -urN linux/drivers/pci/hotplug/shpchp_ctrl.c 
linux/drivers/pci/hotplug/shpchp_ctrl.c
--- linux/drivers/pci/hotplug/shpchp_ctrl.c     2004/11/15 11:49:30     1.8
+++ linux/drivers/pci/hotplug/shpchp_ctrl.c     2005/05/26 09:12:45     1.9
@@ -1885,7 +1885,7 @@
        func = shpchp_slot_find(p_slot->bus, p_slot->device, 0);
        if (!func) {
                dbg("%s: Error! slot NULL\n", __FUNCTION__);
-               return 1;
+               return -ENODEV;
        }
 
        /* Check to see if (latch closed, card present, power off) */
@@ -1894,19 +1894,19 @@
        if (rc || !getstatus) {
                info("%s: no adapter on slot(%x)\n", __FUNCTION__, 
p_slot->number);
                up(&p_slot->ctrl->crit_sect);
-               return 1;
+               return -ENODEV;
        }
        rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
        if (rc || getstatus) {
                info("%s: latch open on slot(%x)\n", __FUNCTION__, 
p_slot->number);
                up(&p_slot->ctrl->crit_sect);
-               return 1;
+               return -ENODEV;
        }
        rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
        if (rc || getstatus) {
                info("%s: already enabled on slot(%x)\n", __FUNCTION__, 
p_slot->number);
                up(&p_slot->ctrl->crit_sect);
-               return 1;
+               return -ENODEV;
        }
        up(&p_slot->ctrl->crit_sect);
 
@@ -1914,7 +1914,7 @@
 
        func = shpchp_slot_create(p_slot->bus);
        if (func == NULL)
-               return 1;
+               return -ENOMEM;
 
        func->bus = p_slot->bus;
        func->device = p_slot->device;
@@ -1939,7 +1939,7 @@
                /* Setup slot structure with entry for empty slot */
                func = shpchp_slot_create(p_slot->bus);
                if (func == NULL)
-                       return (1);     /* Out of memory */
+                       return -ENOMEM; /* Out of memory */
 
                func->bus = p_slot->bus;
                func->device = p_slot->device;
@@ -1972,7 +1972,7 @@
        struct pci_func *func;
 
        if (!p_slot->ctrl)
-               return 1;
+               return -ENODEV;
 
        pci_bus = p_slot->ctrl->pci_dev->subordinate;
 
@@ -1983,19 +1983,19 @@
        if (ret || !getstatus) {
                info("%s: no adapter on slot(%x)\n", __FUNCTION__, 
p_slot->number);
                up(&p_slot->ctrl->crit_sect);
-               return 1;
+               return -ENODEV;
        }
        ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
        if (ret || getstatus) {
                info("%s: latch open on slot(%x)\n", __FUNCTION__, 
p_slot->number);
                up(&p_slot->ctrl->crit_sect);
-               return 1;
+               return -ENODEV;
        }
        ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
        if (ret || !getstatus) {
                info("%s: already disabled slot(%x)\n", __FUNCTION__, 
p_slot->number);
                up(&p_slot->ctrl->crit_sect);
-               return 1;
+               return -ENODEV;
        }
        up(&p_slot->ctrl->crit_sect);
 
@@ -2011,7 +2011,7 @@
                /* Check the Class Code */
                rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, 
&class_code);
                if (rc)
-                       return rc;
+                       return -ENODEV;
 
                if (class_code == PCI_BASE_CLASS_DISPLAY) {
                        /* Display/Video adapter (not supported) */
@@ -2020,13 +2020,13 @@
                        /* See if it's a bridge */
                        rc = pci_bus_read_config_byte (pci_bus, devfn, 
PCI_HEADER_TYPE, &header_type);
                        if (rc)
-                               return rc;
+                               return -ENODEV;
 
                        /* If it's a bridge, check the VGA Enable bit */
                        if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
                                rc = pci_bus_read_config_byte (pci_bus, devfn, 
PCI_BRIDGE_CONTROL, &BCR);
                                if (rc)
-                                       return rc;
+                                       return -ENODEV;
 
                                /* If the VGA Enable bit is set, remove isn't 
supported */
                                if (BCR & PCI_BRIDGE_CTL_VGA) {
@@ -2042,12 +2042,12 @@
        if ((func != NULL) && !rc) {
                rc = remove_board(func, p_slot->ctrl);
        } else if (!rc)
-               rc = 1;
+               rc = -ENODEV;
 
        if (p_slot)
                update_slot_info(p_slot);
 
-       return(rc);
+       return rc;
 }
 
 
diff -urN linux/drivers/pci/pcie/portdrv_bus.c 
linux/drivers/pci/pcie/portdrv_bus.c
--- linux/drivers/pci/pcie/portdrv_bus.c        2005/04/29 11:15:09     1.3
+++ linux/drivers/pci/pcie/portdrv_bus.c        2005/05/26 09:12:45     1.4
@@ -39,7 +39,8 @@
                driver->id_table->vendor != pciedev->id.vendor) ||
               (driver->id_table->device != PCI_ANY_ID &&
                driver->id_table->device != pciedev->id.device) ||      
-               driver->id_table->port_type != pciedev->id.port_type ||
+              (driver->id_table->port_type != PCIE_ANY_PORT &&
+               driver->id_table->port_type != pciedev->id.port_type) ||
                driver->id_table->service_type != pciedev->id.service_type )
                return 0;
 
diff -urN linux/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c
--- linux/drivers/pcmcia/ds.c   2005/04/08 18:58:22     1.44
+++ linux/drivers/pcmcia/ds.c   2005/05/26 09:12:45     1.45
@@ -1592,9 +1592,9 @@
 
        /* Set up character device for user mode clients */
        i = register_chrdev(0, "pcmcia", &ds_fops);
-       if (i == -EBUSY)
+       if (i < 0)
                printk(KERN_NOTICE "unable to find a free device # for "
-                      "Driver Services\n");
+                      "Driver Services (error=%d)\n", i);
        else
                major_dev = i;
 
diff -urN linux/drivers/s390/block/dasd.c linux/drivers/s390/block/dasd.c
--- linux/drivers/s390/block/dasd.c     2005/05/19 12:08:28     1.57
+++ linux/drivers/s390/block/dasd.c     2005/05/26 09:12:45     1.58
@@ -7,7 +7,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
  *
- * $Revision: 1.161 $
+ * $Revision: 1.164 $
  */
 
 #include <linux/config.h>
@@ -1766,10 +1766,10 @@
                printk(KERN_WARNING
                       "dasd_generic_probe: could not add sysfs entries "
                       "for %s\n", cdev->dev.bus_id);
+       } else {
+               cdev->handler = &dasd_int_handler;
        }
 
-       cdev->handler = &dasd_int_handler;
-
        return ret;
 }
 
@@ -1780,6 +1780,8 @@
 {
        struct dasd_device *device;
 
+       cdev->handler = NULL;
+
        dasd_remove_sysfs_files(cdev);
        device = dasd_device_from_cdev(cdev);
        if (IS_ERR(device))
@@ -1810,14 +1812,14 @@
        struct dasd_device *device;
        int feature_diag, rc;
 
-       feature_diag = dasd_get_feature(cdev, DASD_FEATURE_USEDIAG);
-       if (feature_diag < 0)
-               return feature_diag;
-
        device = dasd_create_device(cdev);
        if (IS_ERR(device))
                return PTR_ERR(device);
 
+       feature_diag = dasd_get_feature(cdev, DASD_FEATURE_USEDIAG);
+       if (feature_diag < 0)
+               return feature_diag;
+
        if (feature_diag) {
                if (!dasd_diag_discipline_pointer) {
                        printk (KERN_WARNING
diff -urN linux/drivers/sbus/char/aurora.c linux/drivers/sbus/char/aurora.c
--- linux/drivers/sbus/char/aurora.c    2005/03/18 17:37:44     1.28
+++ linux/drivers/sbus/char/aurora.c    2005/05/26 09:12:45     1.29
@@ -81,10 +81,6 @@
 int irqhit=0;
 #endif
 
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
 static struct tty_driver *aurora_driver;
 static struct Aurora_board aurora_board[AURORA_NBOARD] = {
        {0,},
@@ -594,7 +590,7 @@
                                            &bp->r[chip]->r[CD180_TDR]);
                                port->COR2 &= ~COR2_ETC;
                        }
-                       count = MIN(port->break_length, 0xff);
+                       count = min(port->break_length, 0xff);
                        sbus_writeb(CD180_C_ESC,
                                    &bp->r[chip]->r[CD180_TDR]);
                        sbus_writeb(CD180_C_DELAY,
@@ -1575,7 +1571,7 @@
        save_flags(flags);
        while (1) {
                cli();
-               c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+               c = min(count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
                                   SERIAL_XMIT_SIZE - port->xmit_head));
                if (c <= 0) {
                        restore_flags(flags);
diff -urN linux/drivers/scsi/libata-core.c linux/drivers/scsi/libata-core.c
--- linux/drivers/scsi/libata-core.c    2005/03/18 17:37:44     1.27
+++ linux/drivers/scsi/libata-core.c    2005/05/26 09:12:46     1.28
@@ -1253,11 +1253,11 @@
        unsigned long timeout = jiffies + (HZ * 5);
 
        if (ap->flags & ATA_FLAG_SATA_RESET) {
-               scr_write(ap, SCR_CONTROL, 0x301); /* issue phy wake/reset */
-               scr_read(ap, SCR_STATUS);       /* dummy read; flush */
+               /* issue phy wake/reset */
+               scr_write_flush(ap, SCR_CONTROL, 0x301);
                udelay(400);                    /* FIXME: a guess */
        }
-       scr_write(ap, SCR_CONTROL, 0x300);      /* issue phy wake/clear reset */
+       scr_write_flush(ap, SCR_CONTROL, 0x300); /* phy wake/clear reset */
 
        /* wait for phy to become ready, if necessary */
        do {
@@ -2539,7 +2539,7 @@
        ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
        qc->dma_dir = DMA_FROM_DEVICE;
 
-       memset(&qc->cdb, 0, sizeof(ap->cdb_len));
+       memset(&qc->cdb, 0, ap->cdb_len);
        qc->cdb[0] = REQUEST_SENSE;
        qc->cdb[4] = SCSI_SENSE_BUFFERSIZE;
 
@@ -2811,6 +2811,7 @@
 
        /* call completion callback */
        rc = qc->complete_fn(qc, drv_stat);
+       qc->flags &= ~ATA_QCFLAG_ACTIVE;
 
        /* if callback indicates not to complete command (non-zero),
         * return immediately
@@ -3229,7 +3230,8 @@
                        struct ata_queued_cmd *qc;
 
                        qc = ata_qc_from_tag(ap, ap->active_tag);
-                       if (qc && (!(qc->tf.ctl & ATA_NIEN)))
+                       if (qc && (!(qc->tf.ctl & ATA_NIEN)) &&
+                           (qc->flags & ATA_QCFLAG_ACTIVE))
                                handled |= ata_host_intr(ap, qc);
                }
        }
diff -urN linux/drivers/scsi/libata-scsi.c linux/drivers/scsi/libata-scsi.c
--- linux/drivers/scsi/libata-scsi.c    2005/04/29 11:15:10     1.22
+++ linux/drivers/scsi/libata-scsi.c    2005/05/26 09:12:46     1.23
@@ -347,7 +347,10 @@
                 */
                if ((dev->flags & ATA_DFLAG_LBA48) &&
                    ((dev->flags & ATA_DFLAG_LOCK_SECTORS) == 0)) {
-                       sdev->host->max_sectors = 2048;
+                       /*
+                        * do not overwrite sdev->host->max_sectors, since
+                        * other drives on this host may not support LBA48
+                        */
                        blk_queue_max_sectors(sdev->request_queue, 2048);
                }
        }
diff -urN linux/drivers/scsi/sata_svw.c linux/drivers/scsi/sata_svw.c
--- linux/drivers/scsi/sata_svw.c       2005/03/18 17:37:44     1.16
+++ linux/drivers/scsi/sata_svw.c       2005/05/26 09:12:46     1.17
@@ -395,7 +395,7 @@
 
        /* Clear a magic bit in SCR1 according to Darwin, those help
         * some funky seagate drives (though so far, those were already
-        * set by the firmware on the machines I had access to
+        * set by the firmware on the machines I had access to)
         */
        writel(readl(mmio_base + K2_SATA_SICR1_OFFSET) & ~0x00040000,
               mmio_base + K2_SATA_SICR1_OFFSET);
diff -urN linux/drivers/scsi/scsi_transport_spi.c 
linux/drivers/scsi/scsi_transport_spi.c
--- linux/drivers/scsi/scsi_transport_spi.c     2005/05/19 12:08:29     1.11
+++ linux/drivers/scsi/scsi_transport_spi.c     2005/05/26 09:12:46     1.12
@@ -35,7 +35,7 @@
 
 #define SPI_PRINTK(x, l, f, a...)      dev_printk(l, &(x)->dev, f , ##a)
 
-#define SPI_NUM_ATTRS 10       /* increase this if you add attributes */
+#define SPI_NUM_ATTRS 13       /* increase this if you add attributes */
 #define SPI_OTHER_ATTRS 1      /* Increase this if you add "always
                                 * on" attributes */
 #define SPI_HOST_ATTRS 1
@@ -219,8 +219,11 @@
        struct scsi_target *starget = to_scsi_target(dev);
 
        spi_period(starget) = -1;       /* illegal value */
+       spi_min_period(starget) = 0;
        spi_offset(starget) = 0;        /* async */
+       spi_max_offset(starget) = 255;
        spi_width(starget) = 0; /* narrow */
+       spi_max_width(starget) = 1;
        spi_iu(starget) = 0;    /* no IU */
        spi_dt(starget) = 0;    /* ST */
        spi_qas(starget) = 0;
@@ -235,6 +238,34 @@
        return 0;
 }
 
+#define spi_transport_show_simple(field, format_string)                        
\
+                                                                       \
+static ssize_t                                                         \
+show_spi_transport_##field(struct class_device *cdev, char *buf)       \
+{                                                                      \
+       struct scsi_target *starget = transport_class_to_starget(cdev); \
+       struct spi_transport_attrs *tp;                                 \
+                                                                       \
+       tp = (struct spi_transport_attrs *)&starget->starget_data;      \
+       return snprintf(buf, 20, format_string, tp->field);             \
+}
+
+#define spi_transport_store_simple(field, format_string)               \
+                                                                       \
+static ssize_t                                                         \
+store_spi_transport_##field(struct class_device *cdev, const char *buf, \
+                           size_t count)                               \
+{                                                                      \
+       int val;                                                        \
+       struct scsi_target *starget = transport_class_to_starget(cdev); \
+       struct spi_transport_attrs *tp;                                 \
+                                                                       \
+       tp = (struct spi_transport_attrs *)&starget->starget_data;      \
+       val = simple_strtoul(buf, NULL, 0);                             \
+       tp->field = val;                                                \
+       return count;                                                   \
+}
+
 #define spi_transport_show_function(field, format_string)              \
                                                                        \
 static ssize_t                                                         \
@@ -261,6 +292,25 @@
        struct spi_internal *i = to_spi_internal(shost->transportt);    \
                                                                        \
        val = simple_strtoul(buf, NULL, 0);                             \
+       i->f->set_##field(starget, val);                        \
+       return count;                                                   \
+}
+
+#define spi_transport_store_max(field, format_string)                  \
+static ssize_t                                                         \
+store_spi_transport_##field(struct class_device *cdev, const char *buf, \
+                           size_t count)                               \
+{                                                                      \
+       int val;                                                        \
+       struct scsi_target *starget = transport_class_to_starget(cdev); \
+       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);    \
+       struct spi_internal *i = to_spi_internal(shost->transportt);    \
+       struct spi_transport_attrs *tp                                  \
+               = (struct spi_transport_attrs *)&starget->starget_data; \
+                                                                       \
+       val = simple_strtoul(buf, NULL, 0);                             \
+       if (val > tp->max_##field)                                      \
+               val = tp->max_##field;                                  \
        i->f->set_##field(starget, val);                                \
        return count;                                                   \
 }
@@ -272,9 +322,24 @@
                         show_spi_transport_##field,                    \
                         store_spi_transport_##field);
 
+#define spi_transport_simple_attr(field, format_string)                        
\
+       spi_transport_show_simple(field, format_string)                 \
+       spi_transport_store_simple(field, format_string)                \
+static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR,                     \
+                        show_spi_transport_##field,                    \
+                        store_spi_transport_##field);
+
+#define spi_transport_max_attr(field, format_string)                   \
+       spi_transport_show_function(field, format_string)               \
+       spi_transport_store_max(field, format_string)                   \
+       spi_transport_simple_attr(max_##field, format_string)           \
+static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR,                     \
+                        show_spi_transport_##field,                    \
+                        store_spi_transport_##field);
+
 /* The Parallel SCSI Tranport Attributes: */
-spi_transport_rd_attr(offset, "%d\n");
-spi_transport_rd_attr(width, "%d\n");
+spi_transport_max_attr(offset, "%d\n");
+spi_transport_max_attr(width, "%d\n");
 spi_transport_rd_attr(iu, "%d\n");
 spi_transport_rd_attr(dt, "%d\n");
 spi_transport_rd_attr(qas, "%d\n");
@@ -300,26 +365,18 @@
 
 /* Translate the period into ns according to the current spec
  * for SDTR/PPR messages */
-static ssize_t show_spi_transport_period(struct class_device *cdev, char *buf)
-
+static ssize_t
+show_spi_transport_period_helper(struct class_device *cdev, char *buf,
+                                int period)
 {
-       struct scsi_target *starget = transport_class_to_starget(cdev);
-       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-       struct spi_transport_attrs *tp;
        int len, picosec;
-       struct spi_internal *i = to_spi_internal(shost->transportt);
-
-       tp = (struct spi_transport_attrs *)&starget->starget_data;
-
-       if (i->f->get_period)
-               i->f->get_period(starget);
 
-       if (tp->period < 0 || tp->period > 0xff) {
+       if (period < 0 || period > 0xff) {
                picosec = -1;
-       } else if (tp->period <= SPI_STATIC_PPR) {
-               picosec = ppr_to_ps[tp->period];
+       } else if (period <= SPI_STATIC_PPR) {
+               picosec = ppr_to_ps[period];
        } else {
-               picosec = tp->period * 4000;
+               picosec = period * 4000;
        }
 
        if (picosec == -1) {
@@ -334,12 +391,9 @@
 }
 
 static ssize_t
-store_spi_transport_period(struct class_device *cdev, const char *buf,
-                           size_t count)
+store_spi_transport_period_helper(struct class_device *cdev, const char *buf,
+                                 size_t count, int *periodp)
 {
-       struct scsi_target *starget = transport_class_to_starget(cdev);
-       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-       struct spi_internal *i = to_spi_internal(shost->transportt);
        int j, picosec, period = -1;
        char *endp;
 
@@ -368,15 +422,79 @@
        if (period > 0xff)
                period = 0xff;
 
-       i->f->set_period(starget, period);
+       *periodp = period;
 
        return count;
 }
 
+static ssize_t
+show_spi_transport_period(struct class_device *cdev, char *buf)
+{
+       struct scsi_target *starget = transport_class_to_starget(cdev);
+       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+       struct spi_internal *i = to_spi_internal(shost->transportt);
+       struct spi_transport_attrs *tp =
+               (struct spi_transport_attrs *)&starget->starget_data;
+
+       if (i->f->get_period)
+               i->f->get_period(starget);
+
+       return show_spi_transport_period_helper(cdev, buf, tp->period);
+}
+
+static ssize_t
+store_spi_transport_period(struct class_device *cdev, const char *buf,
+                           size_t count)
+{
+       struct scsi_target *starget = transport_class_to_starget(cdev);
+       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+       struct spi_internal *i = to_spi_internal(shost->transportt);
+       struct spi_transport_attrs *tp =
+               (struct spi_transport_attrs *)&starget->starget_data;
+       int period, retval;
+
+       retval = store_spi_transport_period_helper(cdev, buf, count, &period);
+
+       if (period < tp->min_period)
+               period = tp->min_period;
+
+       i->f->set_period(starget, period);
+
+       return retval;
+}
+
 static CLASS_DEVICE_ATTR(period, S_IRUGO | S_IWUSR, 
                         show_spi_transport_period,
                         store_spi_transport_period);
 
+static ssize_t
+show_spi_transport_min_period(struct class_device *cdev, char *buf)
+{
+       struct scsi_target *starget = transport_class_to_starget(cdev);
+       struct spi_transport_attrs *tp =
+               (struct spi_transport_attrs *)&starget->starget_data;
+
+       return show_spi_transport_period_helper(cdev, buf, tp->min_period);
+}
+
+static ssize_t
+store_spi_transport_min_period(struct class_device *cdev, const char *buf,
+                           size_t count)
+{
+       struct scsi_target *starget = transport_class_to_starget(cdev);
+       struct spi_transport_attrs *tp =
+               (struct spi_transport_attrs *)&starget->starget_data;
+
+       return store_spi_transport_period_helper(cdev, buf, count,
+                                                &tp->min_period);
+}
+
+
+static CLASS_DEVICE_ATTR(min_period, S_IRUGO | S_IWUSR, 
+                        show_spi_transport_min_period,
+                        store_spi_transport_min_period);
+
+
 static ssize_t show_spi_host_signalling(struct class_device *cdev, char *buf)
 {
        struct Scsi_Host *shost = transport_class_to_shost(cdev);
@@ -642,6 +760,7 @@
 {
        struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt);
        struct scsi_device *sdev = sreq->sr_device;
+       struct scsi_target *starget = sdev->sdev_target;
        int len = sdev->inquiry_len;
        /* first set us up for narrow async */
        DV_SET(offset, 0);
@@ -655,9 +774,11 @@
        }
 
        /* test width */
-       if (i->f->set_width && sdev->wdtr) {
+       if (i->f->set_width && spi_max_width(starget) && sdev->wdtr) {
                i->f->set_width(sdev->sdev_target, 1);
 
+               printk("WIDTH IS %d\n", spi_max_width(starget));
+
                if (spi_dv_device_compare_inquiry(sreq, buffer,
                                                   buffer + len,
                                                   DV_LOOPS)
@@ -684,8 +805,8 @@
  retry:
 
        /* now set up to the maximum */
-       DV_SET(offset, 255);
-       DV_SET(period, 1);
+       DV_SET(offset, spi_max_offset(starget));
+       DV_SET(period, spi_min_period(starget));
 
        if (len == 0) {
                SPI_PRINTK(sdev->sdev_target, KERN_INFO, "Domain Validation 
skipping write tests\n");
@@ -892,6 +1013,16 @@
        if (i->f->show_##field)                                         \
                count++
 
+#define SETUP_RELATED_ATTRIBUTE(field, rel_field)                      \
+       i->private_attrs[count] = class_device_attr_##field;            \
+       if (!i->f->set_##rel_field) {                                   \
+               i->private_attrs[count].attr.mode = S_IRUGO;            \
+               i->private_attrs[count].store = NULL;                   \
+       }                                                               \
+       i->attrs[count] = &i->private_attrs[count];                     \
+       if (i->f->show_##rel_field)                                     \
+               count++
+
 #define SETUP_HOST_ATTRIBUTE(field)                                    \
        i->private_host_attrs[count] = class_device_attr_##field;       \
        if (!i->f->set_##field) {                                       \
@@ -975,8 +1106,11 @@
        i->f = ft;
 
        SETUP_ATTRIBUTE(period);
+       SETUP_RELATED_ATTRIBUTE(min_period, period);
        SETUP_ATTRIBUTE(offset);
+       SETUP_RELATED_ATTRIBUTE(max_offset, offset);
        SETUP_ATTRIBUTE(width);
+       SETUP_RELATED_ATTRIBUTE(max_width, width);
        SETUP_ATTRIBUTE(iu);
        SETUP_ATTRIBUTE(dt);
        SETUP_ATTRIBUTE(qas);
diff -urN linux/drivers/scsi/aic7xxx/aic7770_osm.c 
linux/drivers/scsi/aic7xxx/aic7770_osm.c
--- linux/drivers/scsi/aic7xxx/aic7770_osm.c    2005/01/25 04:28:43     1.8
+++ linux/drivers/scsi/aic7xxx/aic7770_osm.c    2005/05/26 09:12:46     1.9
@@ -41,7 +41,6 @@
 
 #include "aic7xxx_osm.h"
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 #include <linux/device.h>
 #include <linux/eisa.h>
 
@@ -62,13 +61,6 @@
 };
 
 typedef  struct device *aic7770_dev_t;
-#else
-#define MINSLOT                        1
-#define NUMSLOTS               16
-#define IDOFFSET               0x80
-
-typedef void *aic7770_dev_t;
-#endif
 
 static int aic7770_linux_config(struct aic7770_identity *entry,
                                aic7770_dev_t dev, u_int eisaBase);
@@ -76,7 +68,6 @@
 int
 ahc_linux_eisa_init(void)
 {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
        struct eisa_device_id *eid;
        struct aic7770_identity *id;
        int i;
@@ -110,44 +101,6 @@
        eid->sig[0] = 0;
 
        return eisa_driver_register(&aic7770_driver);
-#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) */
-       struct aic7770_identity *entry;
-       u_int  slot;
-       u_int  eisaBase;
-       u_int  i;
-       int ret = -ENODEV;
-
-       if (aic7xxx_probe_eisa_vl == 0)
-               return ret;
-
-       eisaBase = 0x1000 + AHC_EISA_SLOT_OFFSET;
-       for (slot = 1; slot < NUMSLOTS; eisaBase+=0x1000, slot++) {
-               uint32_t eisa_id;
-               size_t   id_size;
-
-               if (request_region(eisaBase, AHC_EISA_IOSIZE, "aic7xxx") == 0)
-                       continue;
-
-               eisa_id = 0;
-               id_size = sizeof(eisa_id);
-               for (i = 0; i < 4; i++) {
-                       /* VLcards require priming*/
-                       outb(0x80 + i, eisaBase + IDOFFSET);
-                       eisa_id |= inb(eisaBase + IDOFFSET + i)
-                                  << ((id_size-i-1) * 8);
-               }
-               release_region(eisaBase, AHC_EISA_IOSIZE);
-               if (eisa_id & 0x80000000)
-                       continue;  /* no EISA card in slot */
-
-               entry = aic7770_find_device(eisa_id);
-               if (entry != NULL) {
-                       aic7770_linux_config(entry, NULL, eisaBase);
-                       ret = 0;
-               }
-       }
-       return ret;
-#endif
 }
 
 void
@@ -187,11 +140,10 @@
                ahc_free(ahc);
                return (error);
        }
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+
        dev->driver_data = (void *)ahc;
        if (aic7xxx_detect_complete)
                error = ahc_linux_register_host(ahc, &aic7xxx_driver_template);
-#endif
        return (error);
 }
 
@@ -225,7 +177,6 @@
        return (-error);
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 static int
 aic7770_eisa_dev_probe(struct device *dev)
 {
@@ -261,4 +212,3 @@
 
        return (0);
 }
-#endif
diff -urN linux/drivers/scsi/aic7xxx/aic7xxx_osm.c 
linux/drivers/scsi/aic7xxx/aic7xxx_osm.c
--- linux/drivers/scsi/aic7xxx/aic7xxx_osm.c    2005/05/19 12:08:29     1.27
+++ linux/drivers/scsi/aic7xxx/aic7xxx_osm.c    2005/05/26 09:12:46     1.28
@@ -134,11 +134,6 @@
 #include "aiclib.c"
 
 #include <linux/init.h>                /* __setup */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include "sd.h"                        /* For geometry detection */
-#endif
-
 #include <linux/mm.h>          /* For fetching system memory size */
 #include <linux/blkdev.h>              /* For block_size() */
 #include <linux/delay.h>       /* For ssleep/msleep */
@@ -148,11 +143,6 @@
  */
 spinlock_t ahc_list_spinlock;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/* For dynamic sglist size calculation. */
-u_int ahc_linux_nseg;
-#endif
-
 /*
  * Set this to the delay in seconds after SCSI bus reset.
  * Note, we honor this only for the initial bus reset.
@@ -436,15 +426,12 @@
                                         struct ahc_linux_device *,
                                         struct scb *);
 static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc,
-                                        Scsi_Cmnd *cmd);
+                                        struct scsi_cmnd *cmd);
 static void ahc_linux_sem_timeout(u_long arg);
 static void ahc_linux_freeze_simq(struct ahc_softc *ahc);
 static void ahc_linux_release_simq(u_long arg);
-static void ahc_linux_dev_timed_unfreeze(u_long arg);
-static int  ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag);
+static int  ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
 static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
-static void ahc_linux_size_nseg(void);
-static void ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc);
 static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc,
                                     struct ahc_devinfo *devinfo);
 static void ahc_linux_device_queue_depth(struct ahc_softc *ahc,
@@ -458,54 +445,27 @@
                                                       u_int);
 static void                    ahc_linux_free_device(struct ahc_softc*,
                                                      struct ahc_linux_device*);
-static void ahc_linux_run_device_queue(struct ahc_softc*,
-                                      struct ahc_linux_device*);
+static int ahc_linux_run_command(struct ahc_softc*,
+                                struct ahc_linux_device *,
+                                struct scsi_cmnd *);
 static void ahc_linux_setup_tag_info_global(char *p);
 static aic_option_callback_t ahc_linux_setup_tag_info;
 static int  aic7xxx_setup(char *s);
 static int  ahc_linux_next_unit(void);
-static void ahc_runq_tasklet(unsigned long data);
-static struct ahc_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc);
 
 /********************************* Inlines 
************************************/
-static __inline void ahc_schedule_runq(struct ahc_softc *ahc);
 static __inline struct ahc_linux_device*
                     ahc_linux_get_device(struct ahc_softc *ahc, u_int channel,
-                                         u_int target, u_int lun, int alloc);
-static __inline void ahc_schedule_completeq(struct ahc_softc *ahc);
-static __inline void ahc_linux_check_device_queue(struct ahc_softc *ahc,
-                                                 struct ahc_linux_device *dev);
-static __inline struct ahc_linux_device *
-                    ahc_linux_next_device_to_run(struct ahc_softc *ahc);
-static __inline void ahc_linux_run_device_queues(struct ahc_softc *ahc);
+                                         u_int target, u_int lun);
 static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*);
 
 static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
                                      struct ahc_dma_seg *sg,
                                      dma_addr_t addr, bus_size_t len);
 
-static __inline void
-ahc_schedule_completeq(struct ahc_softc *ahc)
-{
-       if ((ahc->platform_data->flags & AHC_RUN_CMPLT_Q_TIMER) == 0) {
-               ahc->platform_data->flags |= AHC_RUN_CMPLT_Q_TIMER;
-               ahc->platform_data->completeq_timer.expires = jiffies;
-               add_timer(&ahc->platform_data->completeq_timer);
-       }
-}
-
-/*
- * Must be called with our lock held.
- */
-static __inline void
-ahc_schedule_runq(struct ahc_softc *ahc)
-{
-       tasklet_schedule(&ahc->platform_data->runq_tasklet);
-}
-
 static __inline struct ahc_linux_device*
 ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target,
-                    u_int lun, int alloc)
+                    u_int lun)
 {
        struct ahc_linux_target *targ;
        struct ahc_linux_device *dev;
@@ -515,102 +475,15 @@
        if (channel != 0)
                target_offset += 8;
        targ = ahc->platform_data->targets[target_offset];
-       if (targ == NULL) {
-               if (alloc != 0) {
-                       targ = ahc_linux_alloc_target(ahc, channel, target);
-                       if (targ == NULL)
-                               return (NULL);
-               } else
-                       return (NULL);
-       }
+       BUG_ON(targ == NULL);
        dev = targ->devices[lun];
-       if (dev == NULL && alloc != 0)
-               dev = ahc_linux_alloc_device(ahc, targ, lun);
-       return (dev);
-}
-
-#define AHC_LINUX_MAX_RETURNED_ERRORS 4
-static struct ahc_cmd *
-ahc_linux_run_complete_queue(struct ahc_softc *ahc)
-{
-       struct  ahc_cmd *acmd;
-       u_long  done_flags;
-       int     with_errors;
-
-       with_errors = 0;
-       ahc_done_lock(ahc, &done_flags);
-       while ((acmd = TAILQ_FIRST(&ahc->platform_data->completeq)) != NULL) {
-               Scsi_Cmnd *cmd;
-
-               if (with_errors > AHC_LINUX_MAX_RETURNED_ERRORS) {
-                       /*
-                        * Linux uses stack recursion to requeue
-                        * commands that need to be retried.  Avoid
-                        * blowing out the stack by "spoon feeding"
-                        * commands that completed with error back
-                        * the operating system in case they are going
-                        * to be retried. "ick"
-                        */
-                       ahc_schedule_completeq(ahc);
-                       break;
-               }
-               TAILQ_REMOVE(&ahc->platform_data->completeq,
-                            acmd, acmd_links.tqe);
-               cmd = &acmd_scsi_cmd(acmd);
-               cmd->host_scribble = NULL;
-               if (ahc_cmd_get_transaction_status(cmd) != DID_OK
-                || (cmd->result & 0xFF) != SCSI_STATUS_OK)
-                       with_errors++;
-
-               cmd->scsi_done(cmd);
-       }
-       ahc_done_unlock(ahc, &done_flags);
-       return (acmd);
-}
-
-static __inline void
-ahc_linux_check_device_queue(struct ahc_softc *ahc,
-                            struct ahc_linux_device *dev)
-{
-       if ((dev->flags & AHC_DEV_FREEZE_TIL_EMPTY) != 0
-        && dev->active == 0) {
-               dev->flags &= ~AHC_DEV_FREEZE_TIL_EMPTY;
-               dev->qfrozen--;
-       }
-
-       if (TAILQ_FIRST(&dev->busyq) == NULL
-        || dev->openings == 0 || dev->qfrozen != 0)
-               return;
-
-       ahc_linux_run_device_queue(ahc, dev);
-}
-
-static __inline struct ahc_linux_device *
-ahc_linux_next_device_to_run(struct ahc_softc *ahc)
-{
-       
-       if ((ahc->flags & AHC_RESOURCE_SHORTAGE) != 0
-           || (ahc->platform_data->qfrozen != 0))
-               return (NULL);
-       return (TAILQ_FIRST(&ahc->platform_data->device_runq));
-}
-
-static __inline void
-ahc_linux_run_device_queues(struct ahc_softc *ahc)
-{
-       struct ahc_linux_device *dev;
-
-       while ((dev = ahc_linux_next_device_to_run(ahc)) != NULL) {
-               TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links);
-               dev->flags &= ~AHC_DEV_ON_RUN_LIST;
-               ahc_linux_check_device_queue(ahc, dev);
-       }
+       return dev;
 }
 
 static __inline void
 ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb)
 {
-       Scsi_Cmnd *cmd;
+       struct scsi_cmnd *cmd;
 
        cmd = scb->io_ctx;
        ahc_sync_sglist(ahc, scb, BUS_DMASYNC_POSTWRITE);
@@ -650,109 +523,15 @@
        return (consumed);
 }
 
-/************************  Host template entry points 
*************************/
-static int        ahc_linux_detect(Scsi_Host_Template *);
-static int        ahc_linux_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
-static const char *ahc_linux_info(struct Scsi_Host *);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static int        ahc_linux_slave_alloc(Scsi_Device *);
-static int        ahc_linux_slave_configure(Scsi_Device *);
-static void       ahc_linux_slave_destroy(Scsi_Device *);
-#if defined(__i386__)
-static int        ahc_linux_biosparam(struct scsi_device*,
-                                      struct block_device*,
-                                      sector_t, int[]);
-#endif
-#else
-static int        ahc_linux_release(struct Scsi_Host *);
-static void       ahc_linux_select_queue_depth(struct Scsi_Host *host,
-                                               Scsi_Device *scsi_devs);
-#if defined(__i386__)
-static int        ahc_linux_biosparam(Disk *, kdev_t, int[]);
-#endif
-#endif
-static int        ahc_linux_bus_reset(Scsi_Cmnd *);
-static int        ahc_linux_dev_reset(Scsi_Cmnd *);
-static int        ahc_linux_abort(Scsi_Cmnd *);
-
-/*
- * Calculate a safe value for AHC_NSEG (as expressed through ahc_linux_nseg).
- *
- * In pre-2.5.X...
- * The midlayer allocates an S/G array dynamically when a command is issued
- * using SCSI malloc.  This array, which is in an OS dependent format that
- * must later be copied to our private S/G list, is sized to house just the
- * number of segments needed for the current transfer.  Since the code that
- * sizes the SCSI malloc pool does not take into consideration fragmentation
- * of the pool, executing transactions numbering just a fraction of our
- * concurrent transaction limit with list lengths aproaching AHC_NSEG will
- * quickly depleat the SCSI malloc pool of usable space.  Unfortunately, the
- * mid-layer does not properly handle this scsi malloc failures for the S/G
- * array and the result can be a lockup of the I/O subsystem.  We try to size
- * our S/G list so that it satisfies our drivers allocation requirements in
- * addition to avoiding fragmentation of the SCSI malloc pool.
- */
-static void
-ahc_linux_size_nseg(void)
-{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-       u_int cur_size;
-       u_int best_size;
-
-       /*
-        * The SCSI allocator rounds to the nearest 512 bytes
-        * an cannot allocate across a page boundary.  Our algorithm
-        * is to start at 1K of scsi malloc space per-command and
-        * loop through all factors of the PAGE_SIZE and pick the best.
-        */
-       best_size = 0;
-       for (cur_size = 1024; cur_size <= PAGE_SIZE; cur_size *= 2) {
-               u_int nseg;
-
-               nseg = cur_size / sizeof(struct scatterlist);
-               if (nseg < AHC_LINUX_MIN_NSEG)
-                       continue;
-
-               if (best_size == 0) {
-                       best_size = cur_size;
-                       ahc_linux_nseg = nseg;
-               } else {
-                       u_int best_rem;
-                       u_int cur_rem;
-
-                       /*
-                        * Compare the traits of the current "best_size"
-                        * with the current size to determine if the
-                        * current size is a better size.
-                        */
-                       best_rem = best_size % sizeof(struct scatterlist);
-                       cur_rem = cur_size % sizeof(struct scatterlist);
-                       if (cur_rem < best_rem) {
-                               best_size = cur_size;
-                               ahc_linux_nseg = nseg;
-                       }
-               }
-       }
-#endif
-}
-
 /*
  * Try to detect an Adaptec 7XXX controller.
  */
 static int
-ahc_linux_detect(Scsi_Host_Template *template)
+ahc_linux_detect(struct scsi_host_template *template)
 {
        struct  ahc_softc *ahc;
        int     found = 0;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-       /*
-        * It is a bug that the upper layer takes
-        * this lock just prior to calling us.
-        */
-       spin_unlock_irq(&io_request_lock);
-#endif
-
        /*
         * Sanity checking of Linux SCSI data structures so
         * that some of our hacks^H^H^H^H^Hassumptions aren't
@@ -764,7 +543,6 @@
                printf("ahc_linux_detect: Unable to attach\n");
                return (0);
        }
-       ahc_linux_size_nseg();
        /*
         * If we've been passed any parameters, process them now.
         */
@@ -793,48 +571,11 @@
                        found++;
        }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-       spin_lock_irq(&io_request_lock);
-#endif
        aic7xxx_detect_complete++;
 
        return (found);
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/*
- * Free the passed in Scsi_Host memory structures prior to unloading the
- * module.
- */
-int
-ahc_linux_release(struct Scsi_Host * host)
-{
-       struct ahc_softc *ahc;
-       u_long l;
-
-       ahc_list_lock(&l);
-       if (host != NULL) {
-
-               /*
-                * We should be able to just perform
-                * the free directly, but check our
-                * list for extra sanity.
-                */
-               ahc = ahc_find_softc(*(struct ahc_softc **)host->hostdata);
-               if (ahc != NULL) {
-                       u_long s;
-
-                       ahc_lock(ahc, &s);
-                       ahc_intr_enable(ahc, FALSE);
-                       ahc_unlock(ahc, &s);
-                       ahc_free(ahc);
-               }
-       }
-       ahc_list_unlock(&l);
-       return (0);
-}
-#endif
-
 /*
  * Return a string describing the driver.
  */
@@ -867,11 +608,10 @@
  * Queue an SCB to the controller.
  */
 static int
-ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
+ahc_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
 {
        struct   ahc_softc *ahc;
        struct   ahc_linux_device *dev;
-       u_long   flags;
 
        ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
 
@@ -880,205 +620,152 @@
         */
        cmd->scsi_done = scsi_done;
 
-       ahc_midlayer_entrypoint_lock(ahc, &flags);
-
        /*
         * Close the race of a command that was in the process of
         * being queued to us just as our simq was frozen.  Let
         * DV commands through so long as we are only frozen to
         * perform DV.
         */
-       if (ahc->platform_data->qfrozen != 0) {
+       if (ahc->platform_data->qfrozen != 0)
+               return SCSI_MLQUEUE_HOST_BUSY;
 
-               ahc_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
-               ahc_linux_queue_cmd_complete(ahc, cmd);
-               ahc_schedule_completeq(ahc);
-               ahc_midlayer_entrypoint_unlock(ahc, &flags);
-               return (0);
-       }
        dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id,
-                                  cmd->device->lun, /*alloc*/TRUE);
-       if (dev == NULL) {
-               ahc_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
-               ahc_linux_queue_cmd_complete(ahc, cmd);
-               ahc_schedule_completeq(ahc);
-               ahc_midlayer_entrypoint_unlock(ahc, &flags);
-               printf("%s: aic7xxx_linux_queue - Unable to allocate device!\n",
-                      ahc_name(ahc));
-               return (0);
-       }
+                                  cmd->device->lun);
+       BUG_ON(dev == NULL);
+
        cmd->result = CAM_REQ_INPROG << 16;
-       TAILQ_INSERT_TAIL(&dev->busyq, (struct ahc_cmd *)cmd, acmd_links.tqe);
-       if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) {
-               TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links);
-               dev->flags |= AHC_DEV_ON_RUN_LIST;
-               ahc_linux_run_device_queues(ahc);
-       }
-       ahc_midlayer_entrypoint_unlock(ahc, &flags);
-       return (0);
+
+       return ahc_linux_run_command(ahc, dev, cmd);
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 static int
-ahc_linux_slave_alloc(Scsi_Device *device)
+ahc_linux_slave_alloc(struct scsi_device *device)
 {
        struct  ahc_softc *ahc;
+       struct ahc_linux_target *targ;
+       struct scsi_target *starget = device->sdev_target;
+       struct ahc_linux_device *dev;
+       unsigned int target_offset;
+       unsigned long flags;
+       int retval = -ENOMEM;
+
+       target_offset = starget->id;
+       if (starget->channel != 0)
+               target_offset += 8;
 
        ahc = *((struct ahc_softc **)device->host->hostdata);
        if (bootverbose)
                printf("%s: Slave Alloc %d\n", ahc_name(ahc), device->id);
-       return (0);
+       ahc_lock(ahc, &flags);
+       targ = ahc->platform_data->targets[target_offset];
+       if (targ == NULL) {
+               struct seeprom_config *sc;
+
+               targ = ahc_linux_alloc_target(ahc, starget->channel,
+                                               starget->id);
+               sc = ahc->seep_config;
+               if (targ == NULL)
+                       goto out;
+
+               if (sc) {
+                       unsigned short scsirate;
+                       struct ahc_devinfo devinfo;
+                       struct ahc_initiator_tinfo *tinfo;
+                       struct ahc_tmode_tstate *tstate;
+                       char channel = starget->channel + 'A';
+                       unsigned int our_id = ahc->our_id;
+
+                       if (starget->channel)
+                               our_id = ahc->our_id_b;
+
+                       if ((ahc->features & AHC_ULTRA2) != 0) {
+                               scsirate = sc->device_flags[target_offset] & 
CFXFER;
+                       } else {
+                               scsirate = (sc->device_flags[target_offset] & 
CFXFER) << 4;
+                               if (sc->device_flags[target_offset] & CFSYNCH)
+                                       scsirate |= SOFS;
+                       }
+                       if (sc->device_flags[target_offset] & CFWIDEB) {
+                               scsirate |= WIDEXFER;
+                               spi_max_width(starget) = 1;
+                       } else
+                               spi_max_width(starget) = 0;
+                       spi_min_period(starget) = 
+                               ahc_find_period(ahc, scsirate, AHC_SYNCRATE_DT);
+                       tinfo = ahc_fetch_transinfo(ahc, channel, ahc->our_id,
+                                                   targ->target, &tstate);
+                       ahc_compile_devinfo(&devinfo, our_id, targ->target,
+                                           CAM_LUN_WILDCARD, channel,
+                                           ROLE_INITIATOR);
+                       ahc_set_syncrate(ahc, &devinfo, NULL, 0, 0, 0,
+                                        AHC_TRANS_GOAL, /*paused*/FALSE);
+                       ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
+                                     AHC_TRANS_GOAL, /*paused*/FALSE);
+               }
+                       
+       }
+       dev = targ->devices[device->lun];
+       if (dev == NULL) {
+               dev = ahc_linux_alloc_device(ahc, targ, device->lun);
+               if (dev == NULL)
+                       goto out;
+       }
+       retval = 0;
+
+ out:
+       ahc_unlock(ahc, &flags);
+       return retval;
 }
 
 static int
-ahc_linux_slave_configure(Scsi_Device *device)
+ahc_linux_slave_configure(struct scsi_device *device)
 {
        struct  ahc_softc *ahc;
        struct  ahc_linux_device *dev;
-       u_long  flags;
 
        ahc = *((struct ahc_softc **)device->host->hostdata);
+
        if (bootverbose)
                printf("%s: Slave Configure %d\n", ahc_name(ahc), device->id);
-       ahc_midlayer_entrypoint_lock(ahc, &flags);
-       /*
-        * Since Linux has attached to the device, configure
-        * it so we don't free and allocate the device
-        * structure on every command.
-        */
-       dev = ahc_linux_get_device(ahc, device->channel,
-                                  device->id, device->lun,
-                                  /*alloc*/TRUE);
-       if (dev != NULL) {
-               dev->flags &= ~AHC_DEV_UNCONFIGURED;
-               dev->scsi_device = device;
-               ahc_linux_device_queue_depth(ahc, dev);
-       }
-       ahc_midlayer_entrypoint_unlock(ahc, &flags);
+
+       dev = ahc_linux_get_device(ahc, device->channel, device->id,
+                                  device->lun);
+       dev->scsi_device = device;
+       ahc_linux_device_queue_depth(ahc, dev);
 
        /* Initial Domain Validation */
        if (!spi_initial_dv(device->sdev_target))
                spi_dv_device(device);
 
-       return (0);
+       return 0;
 }
 
 static void
-ahc_linux_slave_destroy(Scsi_Device *device)
+ahc_linux_slave_destroy(struct scsi_device *device)
 {
        struct  ahc_softc *ahc;
        struct  ahc_linux_device *dev;
-       u_long  flags;
 
        ahc = *((struct ahc_softc **)device->host->hostdata);
        if (bootverbose)
                printf("%s: Slave Destroy %d\n", ahc_name(ahc), device->id);
-       ahc_midlayer_entrypoint_lock(ahc, &flags);
        dev = ahc_linux_get_device(ahc, device->channel,
-                                  device->id, device->lun,
-                                          /*alloc*/FALSE);
-       /*
-        * Filter out "silly" deletions of real devices by only
-        * deleting devices that have had slave_configure()
-        * called on them.  All other devices that have not
-        * been configured will automatically be deleted by
-        * the refcounting process.
-        */
-       if (dev != NULL
-        && (dev->flags & AHC_DEV_SLAVE_CONFIGURED) != 0) {
-               dev->flags |= AHC_DEV_UNCONFIGURED;
-               if (TAILQ_EMPTY(&dev->busyq)
-                && dev->active == 0
-                && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0)
-                       ahc_linux_free_device(ahc, dev);
-       }
-       ahc_midlayer_entrypoint_unlock(ahc, &flags);
-}
-#else
-/*
- * Sets the queue depth for each SCSI device hanging
- * off the input host adapter.
- */
-static void
-ahc_linux_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs)
-{
-       Scsi_Device *device;
-       Scsi_Device *ldev;
-       struct  ahc_softc *ahc;
-       u_long  flags;
+                                  device->id, device->lun);
 
-       ahc = *((struct ahc_softc **)host->hostdata);
-       ahc_lock(ahc, &flags);
-       for (device = scsi_devs; device != NULL; device = device->next) {
-
-               /*
-                * Watch out for duplicate devices.  This works around
-                * some quirks in how the SCSI scanning code does its
-                * device management.
-                */
-               for (ldev = scsi_devs; ldev != device; ldev = ldev->next) {
-                       if (ldev->host == device->host
-                        && ldev->channel == device->channel
-                        && ldev->id == device->id
-                        && ldev->lun == device->lun)
-                               break;
-               }
-               /* Skip duplicate. */
-               if (ldev != device)
-                       continue;
+       BUG_ON(dev->active);
 
-               if (device->host == host) {
-                       struct   ahc_linux_device *dev;
-
-                       /*
-                        * Since Linux has attached to the device, configure
-                        * it so we don't free and allocate the device
-                        * structure on every command.
-                        */
-                       dev = ahc_linux_get_device(ahc, device->channel,
-                                                  device->id, device->lun,
-                                                  /*alloc*/TRUE);
-                       if (dev != NULL) {
-                               dev->flags &= ~AHC_DEV_UNCONFIGURED;
-                               dev->scsi_device = device;
-                               ahc_linux_device_queue_depth(ahc, dev);
-                               device->queue_depth = dev->openings
-                                                   + dev->active;
-                               if ((dev->flags & (AHC_DEV_Q_BASIC
-                                               | AHC_DEV_Q_TAGGED)) == 0) {
-                                       /*
-                                        * We allow the OS to queue 2 untagged
-                                        * transactions to us at any time even
-                                        * though we can only execute them
-                                        * serially on the controller/device.
-                                        * This should remove some latency.
-                                        */
-                                       device->queue_depth = 2;
-                               }
-                       }
-               }
-       }
-       ahc_unlock(ahc, &flags);
+       ahc_linux_free_device(ahc, dev);
 }
-#endif
 
 #if defined(__i386__)
 /*
  * Return the disk geometry for the given SCSI device.
  */
 static int
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 ahc_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev,
                    sector_t capacity, int geom[])
 {
        uint8_t *bh;
-#else
-ahc_linux_biosparam(Disk *disk, kdev_t dev, int geom[])
-{
-       struct  scsi_device *sdev = disk->device;
-       u_long  capacity = disk->capacity;
-       struct  buffer_head *bh;
-#endif
        int      heads;
        int      sectors;
        int      cylinders;
@@ -1090,22 +777,11 @@
        ahc = *((struct ahc_softc **)sdev->host->hostdata);
        channel = sdev->channel;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
        bh = scsi_bios_ptable(bdev);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17)
-       bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, block_size(dev));
-#else
-       bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, 1024);
-#endif
-
        if (bh) {
                ret = scsi_partsize(bh, capacity,
                                    &geom[2], &geom[0], &geom[1]);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
                kfree(bh);
-#else
-               brelse(bh);
-#endif
                if (ret != -1)
                        return (ret);
        }
@@ -1135,7 +811,7 @@
  * Abort the current SCSI command(s).
  */
 static int
-ahc_linux_abort(Scsi_Cmnd *cmd)
+ahc_linux_abort(struct scsi_cmnd *cmd)
 {
        int error;
 
@@ -1149,7 +825,7 @@
  * Attempt to send a target reset message to the device that timed out.
  */
 static int
-ahc_linux_dev_reset(Scsi_Cmnd *cmd)
+ahc_linux_dev_reset(struct scsi_cmnd *cmd)
 {
        int error;
 
@@ -1163,18 +839,14 @@
  * Reset the SCSI bus.
  */
 static int
-ahc_linux_bus_reset(Scsi_Cmnd *cmd)
+ahc_linux_bus_reset(struct scsi_cmnd *cmd)
 {
        struct ahc_softc *ahc;
-       u_long s;
        int    found;
 
        ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
-       ahc_midlayer_entrypoint_lock(ahc, &s);
        found = ahc_reset_channel(ahc, cmd->device->channel + 'A',
                                  /*initiate reset*/TRUE);
-       ahc_linux_run_complete_queue(ahc);
-       ahc_midlayer_entrypoint_unlock(ahc, &s);
 
        if (bootverbose)
                printf("%s: SCSI bus reset delivered. "
@@ -1183,7 +855,7 @@
        return SUCCESS;
 }
 
-Scsi_Host_Template aic7xxx_driver_template = {
+struct scsi_host_template aic7xxx_driver_template = {
        .module                 = THIS_MODULE,
        .name                   = "aic7xxx",
        .proc_info              = ahc_linux_proc_info,
@@ -1206,33 +878,6 @@
 
 /**************************** Tasklet Handler 
*********************************/
 
-/*
- * In 2.4.X and above, this routine is called from a tasklet,
- * so we must re-acquire our lock prior to executing this code.
- * In all prior kernels, ahc_schedule_runq() calls this routine
- * directly and ahc_schedule_runq() is called with our lock held.
- */
-static void
-ahc_runq_tasklet(unsigned long data)
-{
-       struct ahc_softc* ahc;
-       struct ahc_linux_device *dev;
-       u_long flags;
-
-       ahc = (struct ahc_softc *)data;
-       ahc_lock(ahc, &flags);
-       while ((dev = ahc_linux_next_device_to_run(ahc)) != NULL) {
-       
-               TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links);
-               dev->flags &= ~AHC_DEV_ON_RUN_LIST;
-               ahc_linux_check_device_queue(ahc, dev);
-               /* Yeild to our interrupt handler */
-               ahc_unlock(ahc, &flags);
-               ahc_lock(ahc, &flags);
-       }
-       ahc_unlock(ahc, &flags);
-}
-
 /******************************** Macros 
**************************************/
 #define BUILD_SCSIID(ahc, cmd)                                             \
        ((((cmd)->device->id << TID_SHIFT) & TID)                           \
@@ -1278,37 +923,11 @@
 ahc_dmamem_alloc(struct ahc_softc *ahc, bus_dma_tag_t dmat, void** vaddr,
                 int flags, bus_dmamap_t *mapp)
 {
-       bus_dmamap_t map;
-
-       map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT);
-       if (map == NULL)
-               return (ENOMEM);
-       /*
-        * Although we can dma data above 4GB, our
-        * "consistent" memory is below 4GB for
-        * space efficiency reasons (only need a 4byte
-        * address).  For this reason, we have to reset
-        * our dma mask when doing allocations.
-        */
-       if (ahc->dev_softc != NULL)
-               if (pci_set_dma_mask(ahc->dev_softc, 0xFFFFFFFF)) {
-                       printk(KERN_WARNING "aic7xxx: No suitable DMA 
available.\n");
-                       kfree(map);
-                       return (ENODEV);
-               }
        *vaddr = pci_alloc_consistent(ahc->dev_softc,
-                                     dmat->maxsize, &map->bus_addr);
-       if (ahc->dev_softc != NULL)
-               if (pci_set_dma_mask(ahc->dev_softc,
-                                    ahc->platform_data->hw_dma_mask)) {
-                       printk(KERN_WARNING "aic7xxx: No suitable DMA 
available.\n");
-                       kfree(map);
-                       return (ENODEV);
-               }
+                                     dmat->maxsize, mapp);
        if (*vaddr == NULL)
-               return (ENOMEM);
-       *mapp = map;
-       return(0);
+               return ENOMEM;
+       return 0;
 }
 
 void
@@ -1316,7 +935,7 @@
                void* vaddr, bus_dmamap_t map)
 {
        pci_free_consistent(ahc->dev_softc, dmat->maxsize,
-                           vaddr, map->bus_addr);
+                           vaddr, map);
 }
 
 int
@@ -1330,7 +949,7 @@
         */
        bus_dma_segment_t stack_sg;
 
-       stack_sg.ds_addr = map->bus_addr;
+       stack_sg.ds_addr = map;
        stack_sg.ds_len = dmat->maxsize;
        cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0);
        return (0);
@@ -1339,12 +958,6 @@
 void
 ahc_dmamap_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map)
 {
-       /*
-        * The map may is NULL in our < 2.3.X implementation.
-        * Now it's 2.6.5, but just in case...
-        */
-       BUG_ON(map == NULL);
-       free(map, M_DEVBUF);
 }
 
 int
@@ -1550,7 +1163,7 @@
 uint32_t aic7xxx_verbose;
 
 int
-ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
+ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template 
*template)
 {
        char     buf[80];
        struct   Scsi_Host *host;
@@ -1564,11 +1177,7 @@
 
        *((struct ahc_softc **)host->hostdata) = ahc;
        ahc_lock(ahc, &s);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
        scsi_assign_lock(host, &ahc->platform_data->spin_lock);
-#elif AHC_SCSI_HAS_HOST_LOCK != 0
-       host->lock = &ahc->platform_data->spin_lock;
-#endif
        ahc->platform_data->host = host;
        host->can_queue = AHC_MAX_QUEUE;
        host->cmd_per_lun = 2;
@@ -1587,19 +1196,14 @@
                ahc_set_name(ahc, new_name);
        }
        host->unique_id = ahc->unit;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-       scsi_set_pci_device(host, ahc->dev_softc);
-#endif
        ahc_linux_initialize_scsi_bus(ahc);
        ahc_intr_enable(ahc, TRUE);
        ahc_unlock(ahc, &s);
 
        host->transportt = ahc_linux_transport_template;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
        scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL)); /* 
XXX handle failure */
        scsi_scan_host(host);
-#endif
        return (0);
 }
 
@@ -1717,19 +1321,9 @@
        if (ahc->platform_data == NULL)
                return (ENOMEM);
        memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data));
-       TAILQ_INIT(&ahc->platform_data->completeq);
-       TAILQ_INIT(&ahc->platform_data->device_runq);
        ahc->platform_data->irq = AHC_LINUX_NOIRQ;
-       ahc->platform_data->hw_dma_mask = 0xFFFFFFFF;
        ahc_lockinit(ahc);
-       ahc_done_lockinit(ahc);
-       init_timer(&ahc->platform_data->completeq_timer);
-       ahc->platform_data->completeq_timer.data = (u_long)ahc;
-       ahc->platform_data->completeq_timer.function =
-           (ahc_linux_callback_t *)ahc_linux_thread_run_complete_queue;
        init_MUTEX_LOCKED(&ahc->platform_data->eh_sem);
-       tasklet_init(&ahc->platform_data->runq_tasklet, ahc_runq_tasklet,
-                    (unsigned long)ahc);
        ahc->seltime = (aic7xxx_seltime & 0x3) << 4;
        ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4;
        if (aic7xxx_pci_parity == 0)
@@ -1746,12 +1340,8 @@
        int i, j;
 
        if (ahc->platform_data != NULL) {
-               del_timer_sync(&ahc->platform_data->completeq_timer);
-               tasklet_kill(&ahc->platform_data->runq_tasklet);
                if (ahc->platform_data->host != NULL) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
                        scsi_remove_host(ahc->platform_data->host);
-#endif
                        scsi_host_put(ahc->platform_data->host);
                }
 
@@ -1787,16 +1377,7 @@
                        release_mem_region(ahc->platform_data->mem_busaddr,
                                           0x1000);
                }
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-               /*
-                * In 2.4 we detach from the scsi midlayer before the PCI
-                * layer invokes our remove callback.  No per-instance
-                * detach is provided, so we must reach inside the PCI
-                * subsystem's internals and detach our driver manually.
-                */
-               if (ahc->dev_softc != NULL)
-                       ahc->dev_softc->driver = NULL;
-#endif
+
                free(ahc->platform_data, M_DEVBUF);
        }
 }
@@ -1820,7 +1401,7 @@
 
        dev = ahc_linux_get_device(ahc, devinfo->channel - 'A',
                                   devinfo->target,
-                                  devinfo->lun, /*alloc*/FALSE);
+                                  devinfo->lun);
        if (dev == NULL)
                return;
        was_queuing = dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED);
@@ -1873,7 +1454,6 @@
                dev->maxtags = 0;
                dev->openings =  1 - dev->active;
        }
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
        if (dev->scsi_device != NULL) {
                switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) {
                case AHC_DEV_Q_BASIC:
@@ -1899,90 +1479,13 @@
                        break;
                }
        }
-#endif
 }
 
 int
 ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, char channel,
                        int lun, u_int tag, role_t role, uint32_t status)
 {
-       int chan;
-       int maxchan;
-       int targ;
-       int maxtarg;
-       int clun;
-       int maxlun;
-       int count;
-
-       if (tag != SCB_LIST_NULL)
-               return (0);
-
-       chan = 0;
-       if (channel != ALL_CHANNELS) {
-               chan = channel - 'A';
-               maxchan = chan + 1;
-       } else {
-               maxchan = (ahc->features & AHC_TWIN) ? 2 : 1;
-       }
-       targ = 0;
-       if (target != CAM_TARGET_WILDCARD) {
-               targ = target;
-               maxtarg = targ + 1;
-       } else {
-               maxtarg = (ahc->features & AHC_WIDE) ? 16 : 8;
-       }
-       clun = 0;
-       if (lun != CAM_LUN_WILDCARD) {
-               clun = lun;
-               maxlun = clun + 1;
-       } else {
-               maxlun = AHC_NUM_LUNS;
-       }
-
-       count = 0;
-       for (; chan < maxchan; chan++) {
-
-               for (; targ < maxtarg; targ++) {
-
-                       for (; clun < maxlun; clun++) {
-                               struct ahc_linux_device *dev;
-                               struct ahc_busyq *busyq;
-                               struct ahc_cmd *acmd;
-
-                               dev = ahc_linux_get_device(ahc, chan,
-                                                          targ, clun,
-                                                          /*alloc*/FALSE);
-                               if (dev == NULL)
-                                       continue;
-
-                               busyq = &dev->busyq;
-                               while ((acmd = TAILQ_FIRST(busyq)) != NULL) {
-                                       Scsi_Cmnd *cmd;
-
-                                       cmd = &acmd_scsi_cmd(acmd);
-                                       TAILQ_REMOVE(busyq, acmd,
-                                                    acmd_links.tqe);
-                                       count++;
-                                       cmd->result = status << 16;
-                                       ahc_linux_queue_cmd_complete(ahc, cmd);
-                               }
-                       }
-               }
-       }
-
-       return (count);
-}
-
-static void
-ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc)
-{
-       u_long flags;
-
-       ahc_lock(ahc, &flags);
-       del_timer(&ahc->platform_data->completeq_timer);
-       ahc->platform_data->flags &= ~AHC_RUN_CMPLT_Q_TIMER;
-       ahc_linux_run_complete_queue(ahc);
-       ahc_unlock(ahc, &flags);
+       return 0;
 }
 
 static u_int
@@ -2045,213 +1548,200 @@
        }
 }
 
-static void
-ahc_linux_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev)
+static int
+ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev,
+                     struct scsi_cmnd *cmd)
 {
-       struct   ahc_cmd *acmd;
-       struct   scsi_cmnd *cmd;
        struct   scb *scb;
        struct   hardware_scb *hscb;
        struct   ahc_initiator_tinfo *tinfo;
        struct   ahc_tmode_tstate *tstate;
        uint16_t mask;
+       struct scb_tailq *untagged_q = NULL;
 
-       if ((dev->flags & AHC_DEV_ON_RUN_LIST) != 0)
-               panic("running device on run list");
+       /*
+        * Schedule us to run later.  The only reason we are not
+        * running is because the whole controller Q is frozen.
+        */
+       if (ahc->platform_data->qfrozen != 0)
+               return SCSI_MLQUEUE_HOST_BUSY;
 
-       while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL
-           && dev->openings > 0 && dev->qfrozen == 0) {
+       /*
+        * We only allow one untagged transaction
+        * per target in the initiator role unless
+        * we are storing a full busy target *lun*
+        * table in SCB space.
+        */
+       if (!blk_rq_tagged(cmd->request)
+           && (ahc->features & AHC_SCB_BTT) == 0) {
+               int target_offset;
 
-               /*
-                * Schedule us to run later.  The only reason we are not
-                * running is because the whole controller Q is frozen.
-                */
-               if (ahc->platform_data->qfrozen != 0) {
-                       TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq,
-                                         dev, links);
-                       dev->flags |= AHC_DEV_ON_RUN_LIST;
-                       return;
-               }
-               /*
-                * Get an scb to use.
-                */
-               if ((scb = ahc_get_scb(ahc)) == NULL) {
-                       TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq,
-                                        dev, links);
-                       dev->flags |= AHC_DEV_ON_RUN_LIST;
+               target_offset = cmd->device->id + cmd->device->channel * 8;
+               untagged_q = &(ahc->untagged_queues[target_offset]);
+               if (!TAILQ_EMPTY(untagged_q))
+                       /* if we're already executing an untagged command
+                        * we're busy to another */
+                       return SCSI_MLQUEUE_DEVICE_BUSY;
+       }
+
+       /*
+        * Get an scb to use.
+        */
+       if ((scb = ahc_get_scb(ahc)) == NULL) {
                        ahc->flags |= AHC_RESOURCE_SHORTAGE;
-                       return;
-               }
-               TAILQ_REMOVE(&dev->busyq, acmd, acmd_links.tqe);
-               cmd = &acmd_scsi_cmd(acmd);
-               scb->io_ctx = cmd;
-               scb->platform_data->dev = dev;
-               hscb = scb->hscb;
-               cmd->host_scribble = (char *)scb;
+                       return SCSI_MLQUEUE_HOST_BUSY;
+       }
 
-               /*
-                * Fill out basics of the HSCB.
-                */
-               hscb->control = 0;
-               hscb->scsiid = BUILD_SCSIID(ahc, cmd);
-               hscb->lun = cmd->device->lun;
-               mask = SCB_GET_TARGET_MASK(ahc, scb);
-               tinfo = ahc_fetch_transinfo(ahc, SCB_GET_CHANNEL(ahc, scb),
-                                           SCB_GET_OUR_ID(scb),
-                                           SCB_GET_TARGET(ahc, scb), &tstate);
-               hscb->scsirate = tinfo->scsirate;
-               hscb->scsioffset = tinfo->curr.offset;
-               if ((tstate->ultraenb & mask) != 0)
-                       hscb->control |= ULTRAENB;
-
-               if ((ahc->user_discenable & mask) != 0)
-                       hscb->control |= DISCENB;
-
-               if ((tstate->auto_negotiate & mask) != 0) {
-                       scb->flags |= SCB_AUTO_NEGOTIATE;
-                       scb->hscb->control |= MK_MESSAGE;
-               }
-
-               if ((dev->flags & (AHC_DEV_Q_TAGGED|AHC_DEV_Q_BASIC)) != 0) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-                       int     msg_bytes;
-                       uint8_t tag_msgs[2];
-
-                       msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
-                       if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
-                               hscb->control |= tag_msgs[0];
-                               if (tag_msgs[0] == MSG_ORDERED_TASK)
-                                       dev->commands_since_idle_or_otag = 0;
-                       } else
-#endif
-                       if (dev->commands_since_idle_or_otag == AHC_OTAG_THRESH
-                        && (dev->flags & AHC_DEV_Q_TAGGED) != 0) {
-                               hscb->control |= MSG_ORDERED_TASK;
-                               dev->commands_since_idle_or_otag = 0;
-                       } else {
-                               hscb->control |= MSG_SIMPLE_TASK;
-                       }
-               }
+       scb->io_ctx = cmd;
+       scb->platform_data->dev = dev;
+       hscb = scb->hscb;
+       cmd->host_scribble = (char *)scb;
+
+       /*
+        * Fill out basics of the HSCB.
+        */
+       hscb->control = 0;
+       hscb->scsiid = BUILD_SCSIID(ahc, cmd);
+       hscb->lun = cmd->device->lun;
+       mask = SCB_GET_TARGET_MASK(ahc, scb);
+       tinfo = ahc_fetch_transinfo(ahc, SCB_GET_CHANNEL(ahc, scb),
+                                   SCB_GET_OUR_ID(scb),
+                                   SCB_GET_TARGET(ahc, scb), &tstate);
+       hscb->scsirate = tinfo->scsirate;
+       hscb->scsioffset = tinfo->curr.offset;
+       if ((tstate->ultraenb & mask) != 0)
+               hscb->control |= ULTRAENB;
+       
+       if ((ahc->user_discenable & mask) != 0)
+               hscb->control |= DISCENB;
+       
+       if ((tstate->auto_negotiate & mask) != 0) {
+               scb->flags |= SCB_AUTO_NEGOTIATE;
+               scb->hscb->control |= MK_MESSAGE;
+       }
 
-               hscb->cdb_len = cmd->cmd_len;
-               if (hscb->cdb_len <= 12) {
-                       memcpy(hscb->shared_data.cdb, cmd->cmnd, hscb->cdb_len);
+       if ((dev->flags & (AHC_DEV_Q_TAGGED|AHC_DEV_Q_BASIC)) != 0) {
+               int     msg_bytes;
+               uint8_t tag_msgs[2];
+               
+               msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
+               if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
+                       hscb->control |= tag_msgs[0];
+                       if (tag_msgs[0] == MSG_ORDERED_TASK)
+                               dev->commands_since_idle_or_otag = 0;
+               } else if (dev->commands_since_idle_or_otag == AHC_OTAG_THRESH
+                               && (dev->flags & AHC_DEV_Q_TAGGED) != 0) {
+                       hscb->control |= MSG_ORDERED_TASK;
+                       dev->commands_since_idle_or_otag = 0;
                } else {
-                       memcpy(hscb->cdb32, cmd->cmnd, hscb->cdb_len);
-                       scb->flags |= SCB_CDB32_PTR;
+                       hscb->control |= MSG_SIMPLE_TASK;
                }
+       }
 
-               scb->platform_data->xfer_len = 0;
-               ahc_set_residual(scb, 0);
-               ahc_set_sense_residual(scb, 0);
-               scb->sg_count = 0;
-               if (cmd->use_sg != 0) {
-                       struct  ahc_dma_seg *sg;
-                       struct  scatterlist *cur_seg;
-                       struct  scatterlist *end_seg;
-                       int     nseg;
-
-                       cur_seg = (struct scatterlist *)cmd->request_buffer;
-                       nseg = pci_map_sg(ahc->dev_softc, cur_seg, cmd->use_sg,
-                           cmd->sc_data_direction);
-                       end_seg = cur_seg + nseg;
-                       /* Copy the segments into the SG list. */
-                       sg = scb->sg_list;
-                       /*
-                        * The sg_count may be larger than nseg if
-                        * a transfer crosses a 32bit page.
-                        */ 
-                       while (cur_seg < end_seg) {
-                               dma_addr_t addr;
-                               bus_size_t len;
-                               int consumed;
-
-                               addr = sg_dma_address(cur_seg);
-                               len = sg_dma_len(cur_seg);
-                               consumed = ahc_linux_map_seg(ahc, scb,
-                                                            sg, addr, len);
-                               sg += consumed;
-                               scb->sg_count += consumed;
-                               cur_seg++;
-                       }
-                       sg--;
-                       sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
-
-                       /*
-                        * Reset the sg list pointer.
-                        */
-                       scb->hscb->sgptr =
-                           ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
+       hscb->cdb_len = cmd->cmd_len;
+       if (hscb->cdb_len <= 12) {
+               memcpy(hscb->shared_data.cdb, cmd->cmnd, hscb->cdb_len);
+       } else {
+               memcpy(hscb->cdb32, cmd->cmnd, hscb->cdb_len);
+               scb->flags |= SCB_CDB32_PTR;
+       }
 
-                       /*
-                        * Copy the first SG into the "current"
-                        * data pointer area.
-                        */
-                       scb->hscb->dataptr = scb->sg_list->addr;
-                       scb->hscb->datacnt = scb->sg_list->len;
-               } else if (cmd->request_bufflen != 0) {
-                       struct   ahc_dma_seg *sg;
+       scb->platform_data->xfer_len = 0;
+       ahc_set_residual(scb, 0);
+       ahc_set_sense_residual(scb, 0);
+       scb->sg_count = 0;
+       if (cmd->use_sg != 0) {
+               struct  ahc_dma_seg *sg;
+               struct  scatterlist *cur_seg;
+               struct  scatterlist *end_seg;
+               int     nseg;
+
+               cur_seg = (struct scatterlist *)cmd->request_buffer;
+               nseg = pci_map_sg(ahc->dev_softc, cur_seg, cmd->use_sg,
+                                 cmd->sc_data_direction);
+               end_seg = cur_seg + nseg;
+               /* Copy the segments into the SG list. */
+               sg = scb->sg_list;
+               /*
+                * The sg_count may be larger than nseg if
+                * a transfer crosses a 32bit page.
+                */ 
+               while (cur_seg < end_seg) {
                        dma_addr_t addr;
+                       bus_size_t len;
+                       int consumed;
 
-                       sg = scb->sg_list;
-                       addr = pci_map_single(ahc->dev_softc,
-                              cmd->request_buffer,
-                              cmd->request_bufflen,
-                              cmd->sc_data_direction);
-                       scb->platform_data->buf_busaddr = addr;
-                       scb->sg_count = ahc_linux_map_seg(ahc, scb,
-                                                         sg, addr,
-                                                         cmd->request_bufflen);
-                       sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
+                       addr = sg_dma_address(cur_seg);
+                       len = sg_dma_len(cur_seg);
+                       consumed = ahc_linux_map_seg(ahc, scb,
+                                                    sg, addr, len);
+                       sg += consumed;
+                       scb->sg_count += consumed;
+                       cur_seg++;
+               }
+               sg--;
+               sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
 
-                       /*
-                        * Reset the sg list pointer.
-                        */
-                       scb->hscb->sgptr =
-                           ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
+               /*
+                * Reset the sg list pointer.
+                */
+               scb->hscb->sgptr =
+                       ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
+               
+               /*
+                * Copy the first SG into the "current"
+                * data pointer area.
+                */
+               scb->hscb->dataptr = scb->sg_list->addr;
+               scb->hscb->datacnt = scb->sg_list->len;
+       } else if (cmd->request_bufflen != 0) {
+               struct   ahc_dma_seg *sg;
+               dma_addr_t addr;
 
-                       /*
-                        * Copy the first SG into the "current"
-                        * data pointer area.
-                        */
-                       scb->hscb->dataptr = sg->addr;
-                       scb->hscb->datacnt = sg->len;
-               } else {
-                       scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL);
-                       scb->hscb->dataptr = 0;
-                       scb->hscb->datacnt = 0;
-                       scb->sg_count = 0;
-               }
+               sg = scb->sg_list;
+               addr = pci_map_single(ahc->dev_softc,
+                                     cmd->request_buffer,
+                                     cmd->request_bufflen,
+                                     cmd->sc_data_direction);
+               scb->platform_data->buf_busaddr = addr;
+               scb->sg_count = ahc_linux_map_seg(ahc, scb,
+                                                 sg, addr,
+                                                 cmd->request_bufflen);
+               sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
 
-               ahc_sync_sglist(ahc, scb, BUS_DMASYNC_PREWRITE);
-               LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links);
-               dev->openings--;
-               dev->active++;
-               dev->commands_issued++;
-               if ((dev->flags & AHC_DEV_PERIODIC_OTAG) != 0)
-                       dev->commands_since_idle_or_otag++;
+               /*
+                * Reset the sg list pointer.
+                */
+               scb->hscb->sgptr =
+                       ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
 
                /*
-                * We only allow one untagged transaction
-                * per target in the initiator role unless
-                * we are storing a full busy target *lun*
-                * table in SCB space.
+                * Copy the first SG into the "current"
+                * data pointer area.
                 */
-               if ((scb->hscb->control & (TARGET_SCB|TAG_ENB)) == 0
-                && (ahc->features & AHC_SCB_BTT) == 0) {
-                       struct scb_tailq *untagged_q;
-                       int target_offset;
-
-                       target_offset = SCB_GET_TARGET_OFFSET(ahc, scb);
-                       untagged_q = &(ahc->untagged_queues[target_offset]);
-                       TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe);
-                       scb->flags |= SCB_UNTAGGEDQ;
-                       if (TAILQ_FIRST(untagged_q) != scb)
-                               continue;
-               }
-               scb->flags |= SCB_ACTIVE;
-               ahc_queue_scb(ahc, scb);
+               scb->hscb->dataptr = sg->addr;
+               scb->hscb->datacnt = sg->len;
+       } else {
+               scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL);
+               scb->hscb->dataptr = 0;
+               scb->hscb->datacnt = 0;
+               scb->sg_count = 0;
        }
+
+       LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links);
+       dev->openings--;
+       dev->active++;
+       dev->commands_issued++;
+       if ((dev->flags & AHC_DEV_PERIODIC_OTAG) != 0)
+               dev->commands_since_idle_or_otag++;
+       
+       scb->flags |= SCB_ACTIVE;
+       if (untagged_q) {
+               TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe);
+               scb->flags |= SCB_UNTAGGEDQ;
+       }
+       ahc_queue_scb(ahc, scb);
+       return 0;
 }
 
 /*
@@ -2267,9 +1757,6 @@
        ahc = (struct ahc_softc *) dev_id;
        ahc_lock(ahc, &flags); 
        ours = ahc_intr(ahc);
-       if (ahc_linux_next_device_to_run(ahc) != NULL)
-               ahc_schedule_runq(ahc);
-       ahc_linux_run_complete_queue(ahc);
        ahc_unlock(ahc, &flags);
        return IRQ_RETVAL(ours);
 }
@@ -2278,8 +1765,6 @@
 ahc_platform_flushwork(struct ahc_softc *ahc)
 {
 
-       while (ahc_linux_run_complete_queue(ahc) != NULL)
-               ;
 }
 
 static struct ahc_linux_target*
@@ -2348,9 +1833,6 @@
        if (dev == NULL)
                return (NULL);
        memset(dev, 0, sizeof(*dev));
-       init_timer(&dev->timer);
-       TAILQ_INIT(&dev->busyq);
-       dev->flags = AHC_DEV_UNCONFIGURED;
        dev->lun = lun;
        dev->target = targ;
 
@@ -2373,7 +1855,7 @@
 }
 
 static void
-__ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev)
+ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev)
 {
        struct ahc_linux_target *targ;
 
@@ -2385,13 +1867,6 @@
                ahc_linux_free_target(ahc, targ);
 }
 
-static void
-ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev)
-{
-       del_timer_sync(&dev->timer);
-       __ahc_linux_free_device(ahc, dev);
-}
-
 void
 ahc_send_async(struct ahc_softc *ahc, char channel,
               u_int target, u_int lun, ac_code code, void *arg)
@@ -2463,28 +1938,9 @@
        }
         case AC_SENT_BDR:
        {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
                WARN_ON(lun != CAM_LUN_WILDCARD);
                scsi_report_device_reset(ahc->platform_data->host,
                                         channel - 'A', target);
-#else
-               Scsi_Device *scsi_dev;
-
-               /*
-                * Find the SCSI device associated with this
-                * request and indicate that a UA is expected.
-                */
-               for (scsi_dev = ahc->platform_data->host->host_queue;
-                    scsi_dev != NULL; scsi_dev = scsi_dev->next) {
-                       if (channel - 'A' == scsi_dev->channel
-                        && target == scsi_dev->id
-                        && (lun == CAM_LUN_WILDCARD
-                         || lun == scsi_dev->lun)) {
-                               scsi_dev->was_reset = 1;
-                               scsi_dev->expecting_cc_ua = 1;
-                       }
-               }
-#endif
                break;
        }
         case AC_BUS_RESET:
@@ -2504,7 +1960,7 @@
 void
 ahc_done(struct ahc_softc *ahc, struct scb *scb)
 {
-       Scsi_Cmnd *cmd;
+       struct scsi_cmnd *cmd;
        struct     ahc_linux_device *dev;
 
        LIST_REMOVE(scb, pending_links);
@@ -2515,7 +1971,7 @@
                target_offset = SCB_GET_TARGET_OFFSET(ahc, scb);
                untagged_q = &(ahc->untagged_queues[target_offset]);
                TAILQ_REMOVE(untagged_q, scb, links.tqe);
-               ahc_run_untagged_queue(ahc, untagged_q);
+               BUG_ON(!TAILQ_EMPTY(untagged_q));
        }
 
        if ((scb->flags & SCB_ACTIVE) == 0) {
@@ -2583,8 +2039,6 @@
                }
        } else if (ahc_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) {
                ahc_linux_handle_scsi_status(ahc, dev, scb);
-       } else if (ahc_get_transaction_status(scb) == CAM_SEL_TIMEOUT) {
-               dev->flags |= AHC_DEV_UNCONFIGURED;
        }
 
        if (dev->openings == 1
@@ -2606,16 +2060,6 @@
        if (dev->active == 0)
                dev->commands_since_idle_or_otag = 0;
 
-       if (TAILQ_EMPTY(&dev->busyq)) {
-               if ((dev->flags & AHC_DEV_UNCONFIGURED) != 0
-                && dev->active == 0
-                && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0)
-                       ahc_linux_free_device(ahc, dev);
-       } else if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) {
-               TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links);
-               dev->flags |= AHC_DEV_ON_RUN_LIST;
-       }
-
        if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
                printf("Recovery SCB completes\n");
                if (ahc_get_transaction_status(scb) == CAM_BDR_SENT
@@ -2659,7 +2103,7 @@
        case SCSI_STATUS_CHECK_COND:
        case SCSI_STATUS_CMD_TERMINATED:
        {
-               Scsi_Cmnd *cmd;
+               struct scsi_cmnd *cmd;
 
                /*
                 * Copy sense information to the OS's cmd
@@ -2754,52 +2198,15 @@
                ahc_platform_set_tags(ahc, &devinfo,
                             (dev->flags & AHC_DEV_Q_BASIC)
                           ? AHC_QUEUE_BASIC : AHC_QUEUE_TAGGED);
-               /* FALLTHROUGH */
-       }
-       case SCSI_STATUS_BUSY:
-       {
-               /*
-                * Set a short timer to defer sending commands for
-                * a bit since Linux will not delay in this case.
-                */
-               if ((dev->flags & AHC_DEV_TIMER_ACTIVE) != 0) {
-                       printf("%s:%c:%d: Device Timer still active during "
-                              "busy processing\n", ahc_name(ahc),
-                               dev->target->channel, dev->target->target);
-                       break;
-               }
-               dev->flags |= AHC_DEV_TIMER_ACTIVE;
-               dev->qfrozen++;
-               init_timer(&dev->timer);
-               dev->timer.data = (u_long)dev;
-               dev->timer.expires = jiffies + (HZ/2);
-               dev->timer.function = ahc_linux_dev_timed_unfreeze;
-               add_timer(&dev->timer);
                break;
        }
        }
 }
 
 static void
-ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, Scsi_Cmnd *cmd)
+ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd)
 {
        /*
-        * Typically, the complete queue has very few entries
-        * queued to it before the queue is emptied by
-        * ahc_linux_run_complete_queue, so sorting the entries
-        * by generation number should be inexpensive.
-        * We perform the sort so that commands that complete
-        * with an error are retuned in the order origionally
-        * queued to the controller so that any subsequent retries
-        * are performed in order.  The underlying ahc routines do
-        * not guarantee the order that aborted commands will be
-        * returned to us.
-        */
-       struct ahc_completeq *completeq;
-       struct ahc_cmd *list_cmd;
-       struct ahc_cmd *acmd;
-
-       /*
         * Map CAM error codes into Linux Error codes.  We
         * avoid the conversion so that the DV code has the
         * full error information available when making
@@ -2852,26 +2259,7 @@
                        new_status = DID_ERROR;
                        break;
                case CAM_REQUEUE_REQ:
-                       /*
-                        * If we want the request requeued, make sure there
-                        * are sufficent retries.  In the old scsi error code,
-                        * we used to be able to specify a result code that
-                        * bypassed the retry count.  Now we must use this
-                        * hack.  We also "fake" a check condition with
-                        * a sense code of ABORTED COMMAND.  This seems to
-                        * evoke a retry even if this command is being sent
-                        * via the eh thread.  Ick!  Ick!  Ick!
-                        */
-                       if (cmd->retries > 0)
-                               cmd->retries--;
-                       new_status = DID_OK;
-                       ahc_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND);
-                       cmd->result |= (DRIVER_SENSE << 24);
-                       memset(cmd->sense_buffer, 0,
-                              sizeof(cmd->sense_buffer));
-                       cmd->sense_buffer[0] = SSD_ERRCODE_VALID
-                                            | SSD_CURRENT_ERROR;
-                       cmd->sense_buffer[2] = SSD_KEY_ABORTED_COMMAND;
+                       new_status = DID_REQUEUE;
                        break;
                default:
                        /* We should never get here */
@@ -2882,17 +2270,7 @@
                ahc_cmd_set_transaction_status(cmd, new_status);
        }
 
-       completeq = &ahc->platform_data->completeq;
-       list_cmd = TAILQ_FIRST(completeq);
-       acmd = (struct ahc_cmd *)cmd;
-       while (list_cmd != NULL
-           && acmd_scsi_cmd(list_cmd).serial_number
-            < acmd_scsi_cmd(acmd).serial_number)
-               list_cmd = TAILQ_NEXT(list_cmd, acmd_links.tqe);
-       if (list_cmd != NULL)
-               TAILQ_INSERT_BEFORE(list_cmd, acmd, acmd_links.tqe);
-       else
-               TAILQ_INSERT_TAIL(completeq, acmd, acmd_links.tqe);
+       cmd->scsi_done(cmd);
 }
 
 static void
@@ -2940,7 +2318,6 @@
                ahc->platform_data->qfrozen--;
        if (ahc->platform_data->qfrozen == 0)
                unblock_reqs = 1;
-       ahc_schedule_runq(ahc);
        ahc_unlock(ahc, &s);
        /*
         * There is still a race here.  The mid-layer
@@ -2952,37 +2329,12 @@
                scsi_unblock_requests(ahc->platform_data->host);
 }
 
-static void
-ahc_linux_dev_timed_unfreeze(u_long arg)
-{
-       struct ahc_linux_device *dev;
-       struct ahc_softc *ahc;
-       u_long s;
-
-       dev = (struct ahc_linux_device *)arg;
-       ahc = dev->target->ahc;
-       ahc_lock(ahc, &s);
-       dev->flags &= ~AHC_DEV_TIMER_ACTIVE;
-       if (dev->qfrozen > 0)
-               dev->qfrozen--;
-       if (dev->qfrozen == 0
-        && (dev->flags & AHC_DEV_ON_RUN_LIST) == 0)
-               ahc_linux_run_device_queue(ahc, dev);
-       if (TAILQ_EMPTY(&dev->busyq)
-        && dev->active == 0)
-               __ahc_linux_free_device(ahc, dev);
-       ahc_unlock(ahc, &s);
-}
-
 static int
-ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
+ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
 {
        struct ahc_softc *ahc;
-       struct ahc_cmd *acmd;
-       struct ahc_cmd *list_acmd;
        struct ahc_linux_device *dev;
        struct scb *pending_scb;
-       u_long s;
        u_int  saved_scbptr;
        u_int  active_scb_index;
        u_int  last_phase;
@@ -2998,7 +2350,6 @@
        paused = FALSE;
        wait = FALSE;
        ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
-       acmd = (struct ahc_cmd *)cmd;
 
        printf("%s:%d:%d:%d: Attempting to queue a%s message\n",
               ahc_name(ahc), cmd->device->channel,
@@ -3011,22 +2362,6 @@
        printf("\n");
 
        /*
-        * In all versions of Linux, we have to work around
-        * a major flaw in how the mid-layer is locked down
-        * if we are to sleep successfully in our error handler
-        * while allowing our interrupt handler to run.  Since
-        * the midlayer acquires either the io_request_lock or
-        * our lock prior to calling us, we must use the
-        * spin_unlock_irq() method for unlocking our lock.
-        * This will force interrupts to be enabled on the
-        * current CPU.  Since the EH thread should not have
-        * been running with CPU interrupts disabled other than
-        * by acquiring either the io_request_lock or our own
-        * lock, this *should* be safe.
-        */
-       ahc_midlayer_entrypoint_lock(ahc, &s);
-
-       /*
         * First determine if we currently own this command.
         * Start by searching the device queue.  If not found
         * there, check the pending_scb list.  If not found
@@ -3034,7 +2369,7 @@
         * command, return success.
         */
        dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id,
-                                  cmd->device->lun, /*alloc*/FALSE);
+                                  cmd->device->lun);
 
        if (dev == NULL) {
                /*
@@ -3048,24 +2383,6 @@
                goto no_cmd;
        }
 
-       TAILQ_FOREACH(list_acmd, &dev->busyq, acmd_links.tqe) {
-               if (list_acmd == acmd)
-                       break;
-       }
-
-       if (list_acmd != NULL) {
-               printf("%s:%d:%d:%d: Command found on device queue\n",
-                      ahc_name(ahc), cmd->device->channel, cmd->device->id,
-                      cmd->device->lun);
-               if (flag == SCB_ABORT) {
-                       TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe);
-                       cmd->result = DID_ABORT << 16;
-                       ahc_linux_queue_cmd_complete(ahc, cmd);
-                       retval = SUCCESS;
-                       goto done;
-               }
-       }
-
        if ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0
         && ahc_search_untagged_queues(ahc, cmd, cmd->device->id,
                                       cmd->device->channel + 'A',
@@ -3299,53 +2616,42 @@
                }
                spin_lock_irq(&ahc->platform_data->spin_lock);
        }
-       ahc_schedule_runq(ahc);
-       ahc_linux_run_complete_queue(ahc);
-       ahc_midlayer_entrypoint_unlock(ahc, &s);
        return (retval);
 }
 
 void
 ahc_platform_dump_card_state(struct ahc_softc *ahc)
 {
-       struct ahc_linux_device *dev;
-       int channel;
-       int maxchannel;
-       int target;
-       int maxtarget;
-       int lun;
-       int i;
-
-       maxchannel = (ahc->features & AHC_TWIN) ? 1 : 0;
-       maxtarget = (ahc->features & AHC_WIDE) ? 15 : 7;
-       for (channel = 0; channel <= maxchannel; channel++) {
-
-               for (target = 0; target <=maxtarget; target++) {
-
-                       for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
-                               struct ahc_cmd *acmd;
-
-                               dev = ahc_linux_get_device(ahc, channel, target,
-                                                          lun, /*alloc*/FALSE);
-                               if (dev == NULL)
-                                       continue;
-
-                               printf("DevQ(%d:%d:%d): ",
-                                      channel, target, lun);
-                               i = 0;
-                               TAILQ_FOREACH(acmd, &dev->busyq,
-                                             acmd_links.tqe) {
-                                       if (i++ > AHC_SCB_MAX)
-                                               break;
-                               }
-                               printf("%d waiting\n", i);
-                       }
-               }
-       }
 }
 
 static void ahc_linux_exit(void);
 
+static void ahc_linux_get_width(struct scsi_target *starget)
+{
+       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+       struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
+       struct ahc_tmode_tstate *tstate;
+       struct ahc_initiator_tinfo *tinfo 
+               = ahc_fetch_transinfo(ahc,
+                                     starget->channel + 'A',
+                                     shost->this_id, starget->id, &tstate);
+       spi_width(starget) = tinfo->curr.width;
+}
+
+static void ahc_linux_set_width(struct scsi_target *starget, int width)
+{
+       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+       struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
+       struct ahc_devinfo devinfo;
+       unsigned long flags;
+
+       ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+                           starget->channel + 'A', ROLE_INITIATOR);
+       ahc_lock(ahc, &flags);
+       ahc_set_width(ahc, &devinfo, width, AHC_TRANS_GOAL, FALSE);
+       ahc_unlock(ahc, &flags);
+}
+
 static void ahc_linux_get_period(struct scsi_target *starget)
 {
        struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@@ -3376,8 +2682,21 @@
        if (offset == 0)
                offset = MAX_OFFSET;
 
+       if (period < 9)
+               period = 9;     /* 12.5ns is our minimum */
+       if (period == 9)
+               ppr_options |= MSG_EXT_PPR_DT_REQ;
+
        ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
                            starget->channel + 'A', ROLE_INITIATOR);
+
+       /* all PPR requests apart from QAS require wide transfers */
+       if (ppr_options & ~MSG_EXT_PPR_QAS_REQ) {
+               ahc_linux_get_width(starget);
+               if (spi_width(starget) == 0)
+                       ppr_options &= MSG_EXT_PPR_QAS_REQ;
+       }
+
        syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, 
AHC_SYNCRATE_DT);
        ahc_lock(ahc, &flags);
        ahc_set_syncrate(ahc, &devinfo, syncrate, period, offset,
@@ -3425,32 +2744,6 @@
        ahc_unlock(ahc, &flags);
 }
 
-static void ahc_linux_get_width(struct scsi_target *starget)
-{
-       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-       struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
-       struct ahc_tmode_tstate *tstate;
-       struct ahc_initiator_tinfo *tinfo 
-               = ahc_fetch_transinfo(ahc,
-                                     starget->channel + 'A',
-                                     shost->this_id, starget->id, &tstate);
-       spi_width(starget) = tinfo->curr.width;
-}
-
-static void ahc_linux_set_width(struct scsi_target *starget, int width)
-{
-       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-       struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
-       struct ahc_devinfo devinfo;
-       unsigned long flags;
-
-       ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
-                           starget->channel + 'A', ROLE_INITIATOR);
-       ahc_lock(ahc, &flags);
-       ahc_set_width(ahc, &devinfo, width, AHC_TRANS_GOAL, FALSE);
-       ahc_unlock(ahc, &flags);
-}
-
 static void ahc_linux_get_dt(struct scsi_target *starget)
 {
        struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@@ -3479,10 +2772,15 @@
        unsigned long flags;
        struct ahc_syncrate *syncrate;
 
+       if (dt) {
+               period = 9;     /* 12.5ns is the only period valid for DT */
+               ppr_options |= MSG_EXT_PPR_DT_REQ;
+       } else if (period == 9)
+               period = 10;    /* if resetting DT, period must be >= 25ns */
+
        ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
                            starget->channel + 'A', ROLE_INITIATOR);
-       syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,
-                                    dt ? AHC_SYNCRATE_DT : 
AHC_SYNCRATE_ULTRA2);
+       syncrate = ahc_find_syncrate(ahc, &period, 
&ppr_options,AHC_SYNCRATE_DT);
        ahc_lock(ahc, &flags);
        ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset,
                         ppr_options, AHC_TRANS_GOAL, FALSE);
@@ -3514,7 +2812,6 @@
        unsigned int ppr_options = tinfo->curr.ppr_options
                & ~MSG_E