# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	v2.6.0-test1 -> 1.1534 
#	drivers/pci/hotplug/acpiphp_pci.c	1.7     -> 1.8    
#	arch/sparc64/kernel/pci.c	1.30    -> 1.31   
#	sound/oss/ac97_plugin_ad1980.c	1.1     -> 1.2    
#	drivers/scsi/arm/oak.c	1.20    -> 1.22   
#	arch/ia64/kernel/fsys.S	1.16    -> 1.17   
#	drivers/scsi/megaraid.c	1.50    -> 1.51   
#	drivers/block/ps2esdi.c	1.65    -> 1.66   
#	drivers/input/keyboard/sunkbd.c	1.12    -> 1.13   
#	  drivers/scsi/imm.h	1.10    -> 1.11   
#	drivers/ide/legacy/hd.c	1.20    -> 1.21   
#	include/asm-ppc/hardirq.h	1.21    -> 1.22   
#	drivers/media/common/saa7146_vbi.c	1.3     -> 1.5    
#	drivers/block/swim_iop.c	1.24    -> 1.25   
#	include/linux/dm-ioctl.h	1.2     -> 1.3    
#	drivers/block/as-iosched.c	1.5     -> 1.8    
#	  drivers/scsi/ips.c	1.60    -> 1.61   
#	arch/mips64/kernel/setup.c	1.7     -> 1.8    
#	drivers/usb/misc/usblcd.c	1.10    -> 1.11   
#	include/asm-ppc/processor.h	1.31    -> 1.32   
#	drivers/media/dvb/frontends/Makefile	1.5     -> 1.7    
#	drivers/media/dvb/ttpci/av7110.h	1.2     -> 1.3    
#	drivers/usb/storage/protocol.c	1.11    -> 1.12   
#	include/asm-v850/teg.h	1.2     -> 1.4    
#	drivers/mtd/mtd_blkdevs.c	1.4     -> 1.5    
#	sound/oss/emu10k1/8010.h	1.3     -> 1.4    
#	 net/atm/signaling.h	1.1     -> 1.2    
#	drivers/s390/net/qeth.h	1.1     -> 1.2    
#	drivers/scsi/pas16.c	1.11    -> 1.13   
#	include/asm-generic/sections.h	1.1     -> 1.2    
#	 include/net/ip_vs.h	1.3     -> 1.4    
#	      kernel/ksyms.c	1.209   -> 1.210  
#	drivers/cdrom/gscd.c	1.33    -> 1.34   
#	include/asm-ppc/uaccess.h	1.8     -> 1.9    
#	drivers/char/watchdog/i810-tco.c	1.17    -> 1.19   
#	include/linux/nfs_mount.h	1.3     -> 1.4    
#	arch/sparc/kernel/setup.c	1.19    -> 1.20   
#	drivers/usb/serial/ipaq.h	1.8     -> 1.9    
#	arch/parisc/kernel/ioctl32.c	1.12    -> 1.13   
#	include/media/saa7146.h	1.3     -> 1.4    
#	drivers/pci/quirks.c	1.29    -> 1.30   
#	drivers/scsi/pci2220i.c	1.23    -> 1.24   
#	arch/ppc/mm/mem_pieces.c	1.6     -> 1.7    
#	include/linux/elevator.h	1.25    -> 1.26   
#	drivers/net/irda/vlsi_ir.c	1.17    -> 1.18   
#	drivers/scsi/scsi_pc98.c	1.3     -> 1.4    
#	include/scsi/scsi_device.h	1.2     -> 1.3    
#	drivers/usb/storage/jumpshot.c	1.18    -> 1.19   
#	drivers/message/fusion/mptctl.c	1.15    -> 1.16   
#	  arch/ia64/Makefile	1.55    -> 1.56   
#	drivers/scsi/oktagon_esp.c	1.10    -> 1.11   
#	drivers/telephony/ixj.c	1.24    -> 1.25   
#	arch/i386/kernel/cpu/mtrr/main.c	1.28    -> 1.29   
#	drivers/scsi/aha152x.c	1.32    -> 1.34   
#	drivers/block/ioctl.c	1.55    -> 1.57   
#	 drivers/scsi/fcal.c	1.11    -> 1.12   
#	drivers/scsi/hosts.c	1.80    -> 1.83   
#	drivers/scsi/cpqfcTSinit.c	1.39    -> 1.40   
#	drivers/scsi/aacraid/comminit.c	1.5     -> 1.6    
#	sound/oss/emu10k1/efxmgr.c	1.5     -> 1.6    
#	drivers/media/video/mxb.c	1.5     -> 1.7    
#	drivers/scsi/pc980155.c	1.1     -> 1.2    
#	drivers/scsi/mac53c94.c	1.5     -> 1.6    
#	drivers/usb/gadget/net2280.c	1.11    -> 1.12   
#	drivers/scsi/scsi_proc.c	1.28    -> 1.29   
#	drivers/scsi/aic7xxx/aic7xxx_osm.c	1.43    -> 1.45   
#	drivers/char/watchdog/pcwd.c	1.23    -> 1.24   
#	include/linux/times.h	1.3     -> 1.4    
#	include/media/saa7146_vv.h	1.3     -> 1.5    
#	drivers/scsi/jazz_esp.c	1.8     -> 1.9    
#	drivers/video/vesafb.c	1.32    -> 1.33   
#	init/do_mounts_initrd.c	1.1     -> 1.2    
#	drivers/scsi/mac_scsi.c	1.6     -> 1.7    
#	drivers/scsi/sun3_scsi.c	1.17    -> 1.18   
#	drivers/scsi/cpqfcTScontrol.c	1.8     -> 1.9    
#	include/linux/ext3_jbd.h	1.13    -> 1.14   
#	drivers/usb/host/ohci-hcd.c	1.43    -> 1.44   
#	arch/s390/kernel/setup.c	1.23    -> 1.24   
#	drivers/media/dvb/dvb-core/dvb_net.h	1.4     -> 1.5    
#	drivers/scsi/arm/cumana_1.c	1.19    -> 1.21   
#	drivers/video/pvr2fb.c	1.14    -> 1.15   
#	arch/v850/kernel/rte_cb.c	1.4     -> 1.6    
#	drivers/scsi/lasi700.c	1.12    -> 1.14   
#	sound/oss/emu10k1/audio.c	1.17    -> 1.18   
#	drivers/net/wan/comx-hw-comx.c	1.11    -> 1.12   
#	fs/partitions/nec98.c	1.2     -> 1.3    
#	   fs/umsdos/ioctl.c	1.5     -> 1.6    
#	       kernel/fork.c	1.131   -> 1.134  
#	include/linux/sched.h	1.155   -> 1.156  
#	include/asm-v850/ma.h	1.1     -> 1.3    
#	drivers/block/ll_rw_blk.c	1.192   -> 1.194  
#	        kernel/sys.c	1.50    -> 1.52   
#	drivers/scsi/ibmmca.c	1.21    -> 1.22   
#	drivers/scsi/arm/queue.c	1.10    -> 1.11   
#	drivers/scsi/bvme6000.c	1.6     -> 1.7    
#	include/linux/hfs_sysdep.h	1.9     -> 1.10   
#	drivers/video/Makefile	1.85    -> 1.86   
#	drivers/acpi/utilities/utglobal.c	1.27    -> 1.28   
#	  drivers/md/Kconfig	1.3     -> 1.4    
#	include/asm-ia64/mmu_context.h	1.13    -> 1.14   
#	drivers/media/dvb/frontends/alps_bsrv2.c	1.6     -> 1.7    
#	drivers/media/dvb/ttpci/budget-ci.c	1.3     -> 1.4    
#	include/linux/serial_core.h	1.24    -> 1.25   
#	arch/v850/kernel/head.S	1.3     -> 1.4    
#	drivers/scsi/NCR_Q720.c	1.1     -> 1.3    
#	arch/h8300/kernel/setup.c	1.1     -> 1.2    
#	drivers/ieee1394/sbp2.c	1.37    -> 1.38   
#	include/asm-i386/thread_info.h	1.12    -> 1.13   
#	arch/sparc64/prom/bootstr.c	1.3     -> 1.4    
#	drivers/media/dvb/frontends/grundig_29504-401.c	1.5     -> 1.6    
#	arch/ia64/kernel/setup.c	1.52    -> 1.53   
#	Documentation/pnp.txt	1.3     -> 1.4    
#	sound/oss/emu10k1/cardmo.c	1.4     -> 1.5    
#	 fs/proc/proc_misc.c	1.81    -> 1.84   
#	drivers/media/dvb/ttpci/budget-patch.c	1.3     -> 1.5    
#	drivers/scsi/NCR_D700.c	1.14    -> 1.16   
#	 sound/isa/cmi8330.c	1.15    -> 1.16   
#	drivers/media/dvb/ttpci/Makefile	1.1     -> 1.2    
#	arch/sparc/kernel/process.c	1.28    -> 1.29   
#	drivers/scsi/dc395x.c	1.8     -> 1.10   
#	drivers/scsi/sym53c416.c	1.18    -> 1.19   
#	drivers/block/cpqarray.c	1.77    -> 1.78   
#	include/asm-v850/nb85e_timer_c.h	1.1     -> 1.2     include/asm-v850/v850e_timer_c.h (moved)
#	sound/oss/dmasound/dmasound_core.c	1.12    -> 1.13   
#	drivers/block/floppy.c	1.79    -> 1.80   
#	drivers/media/dvb/frontends/Kconfig	1.5     -> 1.7    
#	include/scsi/scsi_host.h	1.2     -> 1.5    
#	drivers/block/ataflop.c	1.40    -> 1.41   
#	drivers/cdrom/cdrom.c	1.37    -> 1.38   
#	drivers/scsi/53c700.c	1.37    -> 1.39   
#	drivers/pci/hotplug/cpci_hotplug.h	1.2     -> 1.3    
#	arch/v850/kernel/ma.c	1.3     -> 1.4    
#	drivers/sbus/char/envctrl.c	1.15    -> 1.16   
#	drivers/media/dvb/dvb-core/dvb_demux.c	1.6     -> 1.8    
#	drivers/cdrom/sbpcd.c	1.45    -> 1.46   
#	include/asm-v850/rte_ma1_cb.h	1.2     -> 1.4    
#	     fs/devfs/base.c	1.95    -> 1.97   
#	         init/main.c	1.104   -> 1.105  
#	fs/intermezzo/sysctl.c	1.9     -> 1.10   
#	drivers/scsi/g_NCR5380.c	1.20    -> 1.21   
#	drivers/usb/class/usblp.c	1.50    -> 1.52   
#	arch/s390/kernel/entry.S	1.30    -> 1.31   
#	arch/s390/kernel/entry64.S	1.3     -> 1.4    
#	arch/mips/momentum/ocelot_c/setup.c	1.1     -> 1.2    
#	drivers/char/watchdog/machzwd.c	1.18    -> 1.19   
#	arch/arm26/kernel/setup.c	1.2     -> 1.3    
#	drivers/media/dvb/dvb-core/dvb_net.c	1.5     -> 1.7    
#	include/asm-ppc/unistd.h	1.24    -> 1.25   
#	include/asm-ia64/atomic.h	1.6     -> 1.7    
#	drivers/scsi/i91uscsi.c	1.5     -> 1.6    
#	arch/v850/kernel/nb85e_utils.c	1.2     -> 1.3     arch/v850/kernel/v850e_utils.c (moved)
#	drivers/scsi/scsi_sysfs.c	1.24    -> 1.26   
#	drivers/acpi/executer/exutils.c	1.20    -> 1.21   
#	  fs/cifs/cifsglob.h	1.11    -> 1.12   
#	drivers/serial/sunsu.c	1.36    -> 1.37   
#	arch/ppc/platforms/residual.c	1.10    -> 1.11   
#	arch/x86_64/mm/init.c	1.20    -> 1.21   
#	drivers/media/dvb/dvb-core/dvbdev.c	1.12    -> 1.13   
#	drivers/telephony/Kconfig	1.2     -> 1.3    
#	sound/oss/emu10k1/midi.h	1.2     -> 1.3    
#	arch/ia64/kernel/time.c	1.27.1.1 -> 1.29   
#	drivers/acorn/block/mfmhd.c	1.50    -> 1.51   
#	include/asm-v850/sim85e2c.h	1.2     -> 1.3    
#	drivers/block/Kconfig	1.6     -> 1.8    
#	include/linux/blkdev.h	1.116   -> 1.118  
#	drivers/scsi/NCR53C9x.c	1.25    -> 1.26   
#	net/ipv6/xfrm6_policy.c	1.9     -> 1.10   
#	       kernel/time.c	1.15    -> 1.16   
#	drivers/net/fc/iph5526.c	1.26    -> 1.27   
#	include/acpi/platform/acenv.h	1.17    -> 1.18   
#	 drivers/block/nbd.c	1.64    -> 1.66   
#	drivers/media/dvb/dvb-core/dvb_frontend.c	1.6     -> 1.7    
#	drivers/usb/net/ax8817x.c	1.2     -> 1.3    
#	drivers/block/cciss_scsi.c	1.16    -> 1.17   
#	drivers/acpi/tables/tbinstal.c	1.19    -> 1.20   
#	   fs/jffs2/Makefile	1.7     -> 1.8    
#	sound/oss/emu10k1/irqmgr.h	1.3     -> 1.4    
#	 sound/oss/btaudio.c	1.16    -> 1.17   
#	drivers/serial/core.c	1.67    -> 1.68   
#	drivers/net/wan/sdladrv.c	1.8     -> 1.9    
#	  drivers/scsi/ips.h	1.29    -> 1.30   
#	arch/mips/sibyte/cfe/setup.c	1.1     -> 1.2    
#	drivers/cdrom/optcd.c	1.29    -> 1.30   
#	   drivers/scsi/sr.c	1.85    -> 1.87   
#	drivers/scsi/aha1740.c	1.22    -> 1.26   
#	drivers/media/dvb/frontends/alps_tdlb7.c	1.5     -> 1.6    
#	drivers/char/ftape/lowlevel/fdc-io.c	1.9     -> 1.10   
#	    kernel/suspend.c	1.41    -> 1.42   
#	 drivers/scsi/scsi.h	1.88    -> 1.89   
#	include/asm-generic/percpu.h	1.7     -> 1.9    
#	arch/arm/mach-clps711x/autcpu12.c	1.4     -> 1.5    
#	arch/ia64/kernel/entry.S	1.44    -> 1.46   
#	drivers/usb/storage/usb.c	1.73    -> 1.74   
#	drivers/scsi/ini9100u.c	1.16    -> 1.17   
#	drivers/net/wan/syncppp.c	1.13    -> 1.14   
#	include/asm-v850/processor.h	1.5     -> 1.6    
#	drivers/char/nwbutton.h	1.2     -> 1.3    
#	arch/m68k/mm/sun3mmu.c	1.6     -> 1.7    
#	net/ipv4/ipvs/Kconfig	1.2     -> 1.3    
#	drivers/md/dm-ioctl.c	1.27    -> 1.30   
#	arch/mips/mm/fault.c	1.6     -> 1.7    
#	drivers/usb/image/scanner.c	1.62    -> 1.65   
#	  drivers/net/ni65.c	1.16    -> 1.17   
#	drivers/scsi/scsi_module.c	1.4     -> 1.5    
#	drivers/scsi/mvme147.c	1.6     -> 1.7    
#	   drivers/pci/pci.c	1.57    -> 1.58   
#	arch/mips/momentum/ocelot_g/setup.c	1.1     -> 1.2    
#	drivers/scsi/mca_53c9x.c	1.8     -> 1.9    
#	  sound/oss/Makefile	1.22    -> 1.24   
#	drivers/char/ftape/lowlevel/ftape-calibr.c	1.4     -> 1.5    
#	 fs/cifs/transport.c	1.13    -> 1.14   
#	      net/atm/proc.c	1.20    -> 1.21   
#	     drivers/md/md.c	1.173   -> 1.174  
#	drivers/scsi/ncr53c8xx.c	1.31    -> 1.32   
#	drivers/scsi/advansys.c	1.34    -> 1.35   
#	include/asm-v850/anna.h	1.2     -> 1.5    
#	drivers/scsi/inia100.c	1.24    -> 1.25   
#	drivers/char/watchdog/shwdt.c	1.13    -> 1.15   
#	fs/jbd/transaction.c	1.70    -> 1.73   
#	       net/atm/pvc.c	1.13    -> 1.14   
#	drivers/parisc/led.c	1.9     -> 1.10   
#	arch/v850/kernel/nb85e_intc.c	1.3     -> 1.4     arch/v850/kernel/v850e_intc.c (moved)
#	        mm/bootmem.c	1.18    -> 1.19   
#	drivers/usb/serial/visor.c	1.63    -> 1.64   
#	drivers/scsi/u14-34f.c	1.29    -> 1.30   
#	drivers/media/dvb/Kconfig	1.2     -> 1.3    
#	drivers/media/dvb/dvb-core/dvbdev.h	1.6     -> 1.8    
#	sound/oss/emu10k1/hwaccess.c	1.4     -> 1.5    
#	include/asm-v850/nb85e_timer_d.h	1.2     -> 1.3     include/asm-v850/v850e_timer_d.h (moved)
#	 fs/intermezzo/vfs.c	1.22    -> 1.23   
#	drivers/media/dvb/ttpci/budget-core.c	1.3     -> 1.4    
#	    kernel/extable.c	1.7     -> 1.8    
#	drivers/pci/hotplug/acpiphp_glue.c	1.15    -> 1.16   
#	arch/i386/kernel/io_apic.c	1.75    -> 1.76   
#	       fs/ext3/acl.c	1.12    -> 1.13   
#	arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c	1.1     -> 1.2    
#	drivers/acorn/block/fd1772.c	1.36    -> 1.37   
#	drivers/usb/storage/sddr55.c	1.8     -> 1.9    
#	drivers/scsi/pluto.c	1.12    -> 1.13   
#	drivers/cdrom/sonycd535.c	1.35    -> 1.36   
#	arch/sparc64/kernel/setup.c	1.38    -> 1.39   
#	include/asm-v850/machdep.h	1.2     -> 1.4    
#	  sound/oss/ad1889.c	1.3     -> 1.4    
#	include/asm-v850/cacheflush.h	1.2     -> 1.3    
#	include/asm-ia64/processor.h	1.47    -> 1.48   
#	drivers/pcmcia/ti113x.h	1.11    -> 1.12   
#	include/linux/nfs_fs.h	1.46    -> 1.47   
#	drivers/scsi/aacraid/commctrl.c	1.2     -> 1.3    
#	drivers/scsi/aic7xxx/aic7xxx_osm.h	1.49    -> 1.50   
#	drivers/block/swim3.c	1.28    -> 1.29   
#	drivers/media/video/Makefile	1.18    -> 1.19   
#	sound/oss/emu10k1/hwaccess.h	1.8     -> 1.9    
#	drivers/block/floppy98.c	1.8     -> 1.9    
#	arch/sparc64/mm/init.c	1.46    -> 1.48   
#	drivers/scsi/fd_mcs.c	1.17    -> 1.18   
#	drivers/scsi/amiga7xx.c	1.6     -> 1.7    
#	drivers/scsi/fastlane.c	1.10    -> 1.11   
#	 include/linux/ide.h	1.60    -> 1.61   
#	drivers/scsi/nsp32.c	1.15    -> 1.17   
#	arch/sparc64/kernel/head.S	1.17    -> 1.18   
#	   net/sunrpc/clnt.c	1.39    -> 1.40   
#	drivers/scsi/arm/fas216.c	1.21    -> 1.23   
#	drivers/scsi/aacraid/linit.c	1.19    -> 1.20   
#	drivers/char/ftape/zftape/zftape-init.c	1.18    -> 1.19   
#	drivers/net/wireless/ray_cs.c	1.18    -> 1.19   
#	drivers/acpi/tables.c	1.13    -> 1.14   
#	drivers/usb/storage/transport.h	1.28    -> 1.29   
#	drivers/usb/image/scanner.h	1.36    -> 1.38   
#	drivers/acpi/tables/tbconvrt.c	1.23    -> 1.24   
#	drivers/scsi/atp870u.c	1.23    -> 1.24   
#	    net/atm/br2684.c	1.3     -> 1.4    
#	drivers/message/fusion/mptscsih.c	1.24    -> 1.25   
#	       net/netsyms.c	1.87    -> 1.88   
#	drivers/media/video/dpc7146.c	1.3     -> 1.5    
#	net/ipv6/xfrm6_state.c	1.6     -> 1.7    
#	drivers/pci/hotplug/Kconfig	1.9     -> 1.10   
#	drivers/usb/serial/usb-serial.c	1.83    -> 1.84   
#	drivers/scsi/aic7xxx_old.c	1.50    -> 1.51   
#	include/asm-ia64/system.h	1.39    -> 1.40   
#	include/asm-ia64/tlb.h	1.15    -> 1.16   
#	  sound/isa/es18xx.c	1.18    -> 1.19   
#	arch/ia64/kernel/module.c	1.7     -> 1.8    
#	drivers/usb/gadget/zero.c	1.6     -> 1.7    
#	drivers/char/watchdog/softdog.c	1.17    -> 1.18   
#	drivers/fc4/fcp_impl.h	1.2     -> 1.3    
#	 include/linux/usb.h	1.81    -> 1.82   
#	drivers/pci/hotplug/cpci_hotplug_core.c	1.7     -> 1.8    
#	drivers/scsi/aacraid/aachba.c	1.19    -> 1.20   
#	drivers/usb/storage/protocol.h	1.6     -> 1.7    
#	drivers/scsi/seagate.c	1.20    -> 1.21   
#	include/asm-v850/rte_cb.h	1.3     -> 1.4    
#	include/asm-v850/asm.h	1.3     -> 1.4    
#	 arch/ia64/pci/pci.c	1.35    -> 1.36   
#	arch/ia64/hp/sim/simscsi.c	1.14    -> 1.15   
#	     fs/binfmt_elf.c	1.49    -> 1.50   
#	drivers/scsi/blz2060.c	1.9     -> 1.10   
#	drivers/s390/block/dasd.c	1.63    -> 1.64   
#	   arch/v850/Kconfig	1.15    -> 1.16   
#	   drivers/scsi/sg.c	1.59    -> 1.60   
#	arch/ia64/kernel/ia64_ksyms.c	1.32    -> 1.33   
#	drivers/scsi/aacraid/dpcsup.c	1.3     -> 1.4    
#	drivers/sbus/char/jsflash.c	1.30    -> 1.31   
#	drivers/usb/usb-skeleton.c	1.39    -> 1.40   
#	drivers/pcmcia/ricoh.h	1.7     -> 1.8    
#	     drivers/md/dm.h	1.7     -> 1.9    
#	net/sunrpc/auth_gss/auth_gss.c	1.9     -> 1.10   
#	drivers/char/ip2/i2os.h	1.2     -> 1.3    
#	drivers/scsi/sr_vendor.c	1.11    -> 1.12   
#	 drivers/ide/Kconfig	1.16    -> 1.17   
#	drivers/usb/net/catc.c	1.27    -> 1.28   
#	drivers/block/amiflop.c	1.41    -> 1.42   
#	drivers/cdrom/mcdx.c	1.32    -> 1.33   
#	sound/oss/emu10k1/passthrough.c	1.8     -> 1.9    
#	arch/s390/kernel/s390_ext.c	1.4     -> 1.5    
#	drivers/block/genhd.c	1.90    -> 1.91   
#	 include/linux/pci.h	1.99    -> 1.102  
#	drivers/s390/net/qeth_mpc.h	1.1     -> 1.2    
#	arch/ia64/kernel/iosapic.c	1.28    -> 1.29   
#	 drivers/scsi/osst.c	1.47    -> 1.48   
#	arch/i386/kernel/setup.c	1.86    -> 1.88   
#	drivers/char/watchdog/sc520_wdt.c	1.9     -> 1.10   
#	drivers/usb/core/hcd-pci.c	1.15    -> 1.17   
#	drivers/scsi/NCR53c406a.c	1.23    -> 1.24   
#	drivers/scsi/AM53C974.c	1.15    -> 1.16   
#	arch/um/drivers/ubd_kern.c	1.32    -> 1.33   
#	  drivers/char/ip2.c	1.6     -> 1.7    
#	include/asm-v850/nb85e_utils.h	1.1     -> 1.2     include/asm-v850/v850e_utils.h (moved)
#	arch/mips/sibyte/swarm/setup.c	1.1     -> 1.2    
#	drivers/serial/Makefile	1.17    -> 1.18   
#	arch/ia64/kernel/acpi.c	1.43    -> 1.44   
#	drivers/scsi/mac_esp.c	1.12    -> 1.13   
#	include/asm-v850/nb85e_cache.h	1.4     -> 1.5     include/asm-v850/v850e_cache.h (moved)
#	   fs/nfs/nfs3proc.c	1.25    -> 1.26   
#	include/asm-v850/nb85e.h	1.1     -> 1.2     include/asm-v850/v850e.h (moved)
#	drivers/scsi/scsi_syms.c	1.42    -> 1.44   
#	drivers/usb/storage/isd200.c	1.31    -> 1.32   
#	arch/ppc64/kernel/XmPciLpEvent.c	1.2     -> 1.3    
#	drivers/char/ftape/lowlevel/ftape-format.c	1.1     -> 1.2    
#	arch/sparc64/kernel/time.c	1.42    -> 1.43   
#	drivers/usb/storage/scsiglue.c	1.49    -> 1.50   
#	drivers/scsi/scsi_lib.c	1.99    -> 1.104  
#	 include/linux/tty.h	1.18    -> 1.19   
#	net/xfrm/xfrm_policy.c	1.39    -> 1.40   
#	     kernel/compat.c	1.18    -> 1.19   
#	      net/core/dev.c	1.89    -> 1.90   
#	drivers/ide/ide-dma.c	1.17    -> 1.18   
#	drivers/media/common/saa7146_fops.c	1.4     -> 1.5    
#	arch/v850/kernel/nb85e_timer_d.c	1.1     -> 1.2     arch/v850/kernel/v850e_timer_d.c (moved)
#	drivers/usb/core/usb.c	1.127   -> 1.128  
#	drivers/media/dvb/frontends/ves1820.c	1.6     -> 1.7    
#	arch/v850/kernel/anna.c	1.3     -> 1.6    
#	sound/oss/emu10k1/passthrough.h	1.4     -> 1.5    
#	drivers/s390/cio/device_fsm.c	1.6     -> 1.7    
#	arch/h8300/mm/init.c	1.1     -> 1.2    
#	drivers/media/dvb/dvb-core/dvb_functions.h	1.1     -> 1.2    
#	drivers/scsi/aha1542.c	1.29    -> 1.30   
#	drivers/scsi/arm/arxescsi.c	1.21    -> 1.22   
#	drivers/scsi/arm/acornscsi.c	1.32    -> 1.34   
#	drivers/scsi/ultrastor.c	1.19    -> 1.20   
#	arch/v850/kernel/intv.S	1.3     -> 1.4    
#	drivers/scsi/pcmcia/qlogic_stub.c	1.15    -> 1.17   
#	include/linux/namespace.h	1.5     -> 1.7    
#	drivers/scsi/aic7xxx/aiclib.c	1.5     -> 1.6    
#	sound/oss/emu10k1/cardmi.c	1.5     -> 1.6    
#	drivers/scsi/a2091.c	1.10    -> 1.11   
#	drivers/usb/net/usbnet.c	1.58    -> 1.59   
#	drivers/usb/storage/scsiglue.h	1.6     -> 1.7    
#	arch/i386/kernel/cpu/mtrr/cyrix.c	1.3     -> 1.4    
#	arch/v850/kernel/sim85e2c.c	1.2     -> 1.3     arch/v850/kernel/sim85e2.c (moved)
#	    fs/cifs/cifsfs.c	1.22    -> 1.23   
#	drivers/pnp/isapnp/core.c	1.39    -> 1.40   
#	drivers/s390/cio/chsc.c	1.12    -> 1.13   
#	include/asm-v850/fpga85e2c.h	1.2     -> 1.4    
#	        usr/Makefile	1.8     -> 1.9    
#	    fs/nfsd/nfssvc.c	1.40    -> 1.41   
#	drivers/media/dvb/ttpci/budget.c	1.3     -> 1.5    
#	drivers/scsi/aic7xxx/aic79xx_osm.c	1.47    -> 1.48   
#	 net/ipv6/tcp_ipv6.c	1.64    -> 1.66   
#	arch/ppc/platforms/4xx/beech.c	1.1     -> 1.2    
#	     fs/ext3/xattr.c	1.22    -> 1.24   
#	net/xfrm/xfrm_user.c	1.31    -> 1.32   
#	arch/mips/vr41xx/tanbac-tb0229/setup.c	1.1     -> 1.2    
#	drivers/usb/media/dabusb.c	1.29    -> 1.30   
#	drivers/pcmcia/hd64465_ss.c	1.13    -> 1.14   
#	    drivers/fc4/fc.c	1.11    -> 1.12   
#	arch/sparc/mm/srmmu.c	1.34    -> 1.35   
#	drivers/s390/block/dasd_ioctl.c	1.17    -> 1.18   
#	arch/ppc/platforms/pmac_cpufreq.c	1.4     -> 1.5    
#	Documentation/magic-number.txt	1.4     -> 1.6    
#	drivers/usb/core/hcd.c	1.67    -> 1.68   
#	drivers/scsi/dmx3191d.c	1.13    -> 1.14   
#	drivers/media/dvb/Makefile	1.3     -> 1.4    
#	arch/ppc/platforms/4xx/walnut.c	1.8     -> 1.9    
#	arch/ppc64/mm/init.c	1.47    -> 1.48   
#	drivers/scsi/aacraid/sa.c	1.4     -> 1.5    
#	arch/m68k/mm/motorola.c	1.6     -> 1.7    
#	  drivers/scsi/ppa.c	1.24    -> 1.25   
#	sound/oss/emu10k1/voicemgr.c	1.4     -> 1.5    
#	sound/oss/emu10k1/voicemgr.h	1.4     -> 1.5    
#	drivers/scsi/scsicam.c	1.13    -> 1.14   
#	drivers/char/agp/i460-agp.c	1.25    -> 1.26   
#	drivers/scsi/pcmcia/fdomain_stub.c	1.16    -> 1.18   
#	 drivers/char/pcxx.c	1.16    -> 1.17   
#	            fs/bio.c	1.48    -> 1.49   
#	         MAINTAINERS	1.155   -> 1.156  
#	drivers/ieee1394/amdtp.c	1.14    -> 1.15   
#	drivers/usb/net/rtl8150.c	1.28    -> 1.29   
#	drivers/pcmcia/yenta_socket.c	1.33    -> 1.34   
#	drivers/s390/cio/qdio.c	1.7     -> 1.8    
#	drivers/media/common/saa7146_hlp.c	1.3     -> 1.5    
#	drivers/scsi/scsi_debug.c	1.39    -> 1.42   
#	include/asm-v850/ma1.h	1.1     -> 1.2    
#	drivers/block/cryptoloop.c	1.1     -> 1.2    
#	       net/atm/lec.c	1.29    -> 1.31   
#	drivers/char/istallion.c	1.29    -> 1.30   
#	drivers/scsi/aic7xxx/aic79xx_osm.h	1.33    -> 1.34   
#	 drivers/cdrom/mcd.c	1.32    -> 1.33   
#	drivers/acpi/tables/tbrsdt.c	1.10    -> 1.11   
#	 drivers/scsi/gdth.c	1.30    -> 1.31   
#	arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c	1.1     -> 1.2    
#	drivers/char/watchdog/acquirewdt.c	1.21    -> 1.22   
#	   scripts/ver_linux	1.10    -> 1.11   
#	      fs/lockd/svc.c	1.22    -> 1.23   
#	arch/v850/vmlinux.lds.S	1.11    -> 1.13   
#	     net/ipv6/esp6.c	1.17    -> 1.18   
#	drivers/char/watchdog/wdt_pci.c	1.22    -> 1.23   
#	arch/ppc/platforms/4xx/sycamore.c	1.3     -> 1.4    
#	drivers/pci/hotplug/cpci_hotplug_pci.c	1.11    -> 1.13   
#	drivers/usb/class/cdc-acm.c	1.46    -> 1.47   
#	     fs/vfat/namei.c	1.34    -> 1.35   
#	   drivers/scsi/st.c	1.66    -> 1.67   
#	drivers/scsi/ide-scsi.c	1.26    -> 1.27   
#	drivers/block/z2ram.c	1.25    -> 1.26   
#	drivers/usb/storage/usb.h	1.34    -> 1.36   
#	drivers/media/common/saa7146_video.c	1.4     -> 1.6    
#	drivers/scsi/eata_pio.c	1.19    -> 1.20   
#	drivers/acpi/tables/tbget.c	1.19    -> 1.20   
#	      fs/namespace.c	1.48    -> 1.49   
#	drivers/atm/atmtcp.c	1.10    -> 1.12   
#	       net/atm/svc.c	1.15    -> 1.18   
#	drivers/scsi/arm/powertec.c	1.28    -> 1.29   
#	arch/m68knommu/kernel/setup.c	1.5     -> 1.6    
#	    init/do_mounts.h	1.4     -> 1.5    
#	drivers/scsi/sr_ioctl.c	1.29    -> 1.30   
#	 drivers/scsi/mesh.c	1.9     -> 1.10   
#	arch/m68k/apollo/dn_ints.c	1.8     -> 1.9    
#	drivers/media/dvb/ttpci/av7110.c	1.3     -> 1.5    
#	drivers/scsi/pci2000.c	1.18    -> 1.19   
#	   net/atm/pppoatm.c	1.7     -> 1.8    
#	arch/m68knommu/mm/init.c	1.1     -> 1.2    
#	            Makefile	1.417   -> 1.418  
#	arch/s390/kernel/compat_ioctl.c	1.4     -> 1.5    
#	arch/mips/ramdisk/Makefile	1.1     -> 1.2    
#	arch/v850/kernel/teg.c	1.1     -> 1.2    
#	drivers/cdrom/sjcd.c	1.26    -> 1.27   
#	drivers/scsi/zalon.c	1.4     -> 1.6    
#	drivers/scsi/sym53c8xx.c	1.37    -> 1.39   
#	drivers/block/paride/pf.c	1.40    -> 1.42   
#	   net/sunrpc/xprt.c	1.62    -> 1.63   
#	drivers/scsi/blz1230.c	1.10    -> 1.11   
#	drivers/scsi/wd33c93.c	1.14    -> 1.15   
#	drivers/scsi/qlogicpti.c	1.18    -> 1.19   
#	      net/ipv6/ah6.c	1.18    -> 1.19   
#	drivers/scsi/psi240i.c	1.12    -> 1.13   
#	drivers/acpi/processor.c	1.39    -> 1.40   
#	include/asm-ia64/elf.h	1.12    -> 1.13   
#	drivers/scsi/scsi_priv.h	1.15    -> 1.17   
#	net/wanrouter/wanmain.c	1.16    -> 1.17   
#	drivers/scsi/aha1542.h	1.8     -> 1.9    
#	drivers/char/watchdog/sbc60xxwdt.c	1.24    -> 1.25   
#	drivers/cdrom/cdu31a.c	1.36    -> 1.37   
#	drivers/char/watchdog/i810-tco.h	1.4     -> 1.6    
#	drivers/scsi/sun3x_esp.c	1.11    -> 1.12   
#	arch/v850/kernel/nb85e_cache.c	1.1     -> 1.2     arch/v850/kernel/v850e_cache.c (moved)
#	include/asm-v850/stat.h	1.4     -> 1.5    
#	sound/oss/emu10k1/mixer.c	1.9     -> 1.10   
#	drivers/scsi/dec_esp.c	1.8     -> 1.9    
#	drivers/scsi/fdomain.c	1.23    -> 1.24   
#	 init/do_mounts_rd.c	1.5     -> 1.6    
#	 fs/partitions/efi.h	1.4     -> 1.5    
#	drivers/scsi/constants.c	1.11    -> 1.12   
#	drivers/scsi/aacraid/commsup.c	1.5     -> 1.6    
#	drivers/message/i2o/i2o_block.c	1.54    -> 1.55   
#	drivers/media/common/saa7146_core.c	1.4     -> 1.5    
#	drivers/media/dvb/frontends/nxt6000.c	1.2     -> 1.3    
#	drivers/ide/legacy/hd98.c	1.4     -> 1.5    
#	drivers/usb/net/kaweth.c	1.49    -> 1.50   
#	arch/ppc64/kernel/prom.c	1.29    -> 1.30   
#	drivers/scsi/arm/cumana_2.c	1.29    -> 1.30   
#	  drivers/scsi/dtc.c	1.11    -> 1.12   
#	net/xfrm/xfrm_state.c	1.32    -> 1.33   
#	     kernel/module.c	1.87    -> 1.90   
#	 arch/s390/mm/init.c	1.16    -> 1.17   
#	drivers/scsi/qlogicfc.c	1.33    -> 1.34   
#	drivers/scsi/in2000.c	1.21    -> 1.22   
#	drivers/usb/gadget/net2280.h	1.2     -> 1.3    
#	include/asm-ppc/pci.h	1.19    -> 1.20   
#	drivers/net/wan/sdlamain.c	1.18    -> 1.19   
#	    net/atm/common.h	1.9     -> 1.12   
#	drivers/scsi/a3000.c	1.9     -> 1.10   
#	drivers/net/pcmcia/Kconfig	1.5     -> 1.6    
#	arch/i386/pci/visws.c	1.10    -> 1.12   
#	   net/ipv4/ip_gre.c	1.27    -> 1.28   
#	drivers/s390/cio/device.c	1.8     -> 1.9    
#	drivers/s390/block/xpram.c	1.42    -> 1.43   
#	arch/ia64/ia32/ia32_ioctl.c	1.12    -> 1.13   
#	drivers/acpi/tables/tbxfroot.c	1.17    -> 1.18   
#	arch/ppc64/kernel/iSeries_irq.c	1.2     -> 1.3    
#	    net/ipv6/route.c	1.50    -> 1.51   
#	net/ipv4/tcp_input.c	1.44    -> 1.45   
#	include/acpi/acconfig.h	1.40    -> 1.41   
#	drivers/usb/class/bluetty.c	1.46    -> 1.47   
#	drivers/char/stallion.c	1.31    -> 1.32   
#	include/asm-ia64/percpu.h	1.8     -> 1.11   
#	   drivers/scsi/sd.c	1.126   -> 1.129  
#	drivers/s390/char/tape_block.c	1.5     -> 1.6    
#	drivers/net/seeq8005.c	1.11    -> 1.12   
#	arch/m68k/atari/stram.c	1.24    -> 1.25   
#	arch/ppc/kernel/time.c	1.22    -> 1.23   
#	 arch/i386/mm/init.c	1.50    -> 1.52   
#	include/asm-v850/system.h	1.4     -> 1.5    
#	arch/mips/sibyte/sb1250/prom.c	1.1     -> 1.2    
#	drivers/block/DAC960.c	1.60    -> 1.61   
#	drivers/s390/block/dasd_genhd.c	1.25    -> 1.27   
#	drivers/usb/storage/unusual_devs.h	1.48    -> 1.49   
#	 net/atm/signaling.c	1.13    -> 1.17   
#	      fs/nfs/inode.c	1.82    -> 1.84   
#	drivers/block/elevator.c	1.46    -> 1.48   
#	           mm/slab.c	1.93    -> 1.95   
#	     drivers/md/dm.c	1.24    -> 1.27   
#	include/linux/module.h	1.66    -> 1.68   
#	arch/alpha/kernel/irq.c	1.22    -> 1.23   
#	drivers/scsi/cpqfcTSworker.c	1.16    -> 1.17   
#	drivers/usb/serial/ftdi_sio.c	1.44    -> 1.45   
#	drivers/message/i2o/i2o_scsi.c	1.20    -> 1.21   
#	drivers/media/dvb/ttpci/budget-av.c	1.3     -> 1.5    
#	include/asm-v850/nb85e_intc.h	1.2     -> 1.3     include/asm-v850/v850e_intc.h (moved)
#	drivers/scsi/cyberstorm.c	1.9     -> 1.10   
#	drivers/scsi/scsi_scan.c	1.97    -> 1.99   
#	drivers/s390/cio/device.h	1.4     -> 1.5    
#	      kernel/sched.c	1.202   -> 1.203  
#	arch/s390/kernel/compat_linux.c	1.4     -> 1.5    
#	drivers/block/deadline-iosched.c	1.21    -> 1.22   
#	drivers/block/paride/pd.c	1.49    -> 1.50   
#	include/asm-v850/rte_nb85e_cb.h	1.2     -> 1.4    
#	drivers/char/watchdog/wdt977.c	1.15    -> 1.17   
#	   arch/sh/mm/init.c	1.13    -> 1.14   
#	  drivers/acpi/osl.c	1.40    -> 1.41   
#	drivers/usb/storage/sddr09.c	1.24    -> 1.25   
#	sound/oss/emu10k1/cardwo.c	1.10    -> 1.11   
#	drivers/scsi/sim710.c	1.16    -> 1.18   
#	arch/v850/kernel/rte_ma1_cb.c	1.4     -> 1.5    
#	  drivers/block/xd.c	1.54    -> 1.55   
#	drivers/char/busmouse.c	1.8     -> 1.9    
#	drivers/ide/ide-io.c	1.13    -> 1.15   
#	drivers/media/dvb/frontends/grundig_29504-491.c	1.5     -> 1.6    
#	       net/atm/mpc.c	1.20    -> 1.22   
#	drivers/scsi/dpt_i2o.c	1.32    -> 1.33   
#	arch/ppc/kernel/irq.c	1.29    -> 1.30   
#	arch/x86_64/mm/numa.c	1.4     -> 1.5    
#	include/linux/atmdev.h	1.18    -> 1.21   
#	drivers/scsi/mvme16x.c	1.6     -> 1.7    
#	drivers/usb/serial/ipaq.c	1.30    -> 1.31   
#	drivers/scsi/cyberstormII.c	1.9     -> 1.10   
#	include/asm-v850/as85ep1.h	1.1     -> 1.4    
#	   sound/oss/Kconfig	1.9     -> 1.11   
#	arch/sparc64/kernel/sparc64_ksyms.c	1.50    -> 1.51   
#	arch/i386/pci/legacy.c	1.11    -> 1.12   
#	drivers/media/video/pms.c	1.11    -> 1.12   
#	drivers/media/dvb/dvb-core/dvb_functions.c	1.2     -> 1.3    
#	drivers/media/common/Makefile	1.1     -> 1.2    
#	 include/linux/blk.h	1.36    -> 1.37   
#	drivers/acpi/hardware/hwregs.c	1.24    -> 1.25   
#	drivers/serial/nb85e_uart.c	1.12    -> 1.13    drivers/serial/v850e_uart.c (moved)
#	  drivers/scsi/ppa.h	1.9     -> 1.10   
#	include/asm-s390/irq.h	1.9     -> 1.10   
#	 arch/s390/defconfig	1.25    -> 1.26   
#	drivers/usb/serial/ftdi_sio.h	1.6     -> 1.7    
#	 drivers/net/Kconfig	1.35    -> 1.36   
#	 arch/m68k/mm/init.c	1.10    -> 1.11   
#	arch/ppc64/boot/Makefile	1.14    -> 1.15   
#	 drivers/scsi/eata.c	1.34    -> 1.35   
#	drivers/pci/setup-res.c	1.18    -> 1.19   
#	 arch/mips/mm/init.c	1.9     -> 1.10   
#	drivers/acpi/thermal.c	1.24    -> 1.25   
#	     fs/cifs/CHANGES	1.23    -> 1.24   
#	arch/m68k/q40/q40ints.c	1.12    -> 1.13   
#	   drivers/net/eql.c	1.9     -> 1.10   
#	include/asm-s390/siginfo.h	1.5     -> 1.6    
#	drivers/usb/host/uhci-hcd.c	1.36    -> 1.37   
#	include/asm-s390/dma.h	1.3     -> 1.4    
#	drivers/scsi/pcmcia/aha152x_stub.c	1.15    -> 1.17   
#	arch/sparc64/lib/atomic.S	1.2     -> 1.3    
#	 drivers/scsi/t128.c	1.12    -> 1.13   
#	  sound/oss/ad1816.c	1.11    -> 1.12   
#	arch/v850/kernel/fpga85e2c.c	1.2     -> 1.4    
#	net/ipv4/ipvs/ip_vs_ctl.c	1.1     -> 1.2    
#	   fs/cifs/connect.c	1.26    -> 1.27   
#	drivers/cdrom/cm206.c	1.33    -> 1.34   
#	arch/alpha/mm/init.c	1.17    -> 1.18   
#	net/ipv4/ipvs/ip_vs_conn.c	1.3     -> 1.4    
#	drivers/pci/Makefile	1.33    -> 1.34   
#	fs/partitions/check.c	1.114   -> 1.116  
#	arch/ppc/kernel/misc.S	1.44    -> 1.45   
#	drivers/char/watchdog/ib700wdt.c	1.14    -> 1.15   
#	drivers/serial/Kconfig	1.12    -> 1.13   
#	drivers/pci/hotplug.c	1.18    -> 1.20   
#	drivers/scsi/gvp11.c	1.10    -> 1.11   
#	drivers/cdrom/aztcd.c	1.29    -> 1.30   
#	      net/ipv6/sit.c	1.26    -> 1.27   
#	drivers/media/video/Kconfig	1.7     -> 1.8    
#	       net/atm/raw.c	1.4     -> 1.7    
#	include/asm-sparc64/atomic.h	1.3     -> 1.4    
#	 net/ipv6/addrconf.c	1.57    -> 1.58   
#	arch/ia64/kernel/perfmon.c	1.52    -> 1.53   
#	 drivers/char/moxa.c	1.24    -> 1.25   
#	drivers/usb/host/ohci-q.c	1.41    -> 1.42   
#	  drivers/pci/pool.c	1.14    -> 1.15   
#	drivers/scsi/3w-xxxx.c	1.34    -> 1.35   
#	 fs/lockd/clntlock.c	1.7     -> 1.8    
#	arch/arm26/mm/init.c	1.3     -> 1.4    
#	drivers/char/watchdog/indydog.c	1.6     -> 1.7    
#	include/asm-v850/highres_timer.h	1.1     -> 1.2    
#	include/linux/netdevice.h	1.45    -> 1.46   
#	    kernel/profile.c	1.4     -> 1.5    
#	   fs/compat_ioctl.c	1.3     -> 1.4    
#	drivers/scsi/BusLogic.c	1.21    -> 1.22   
#	drivers/scsi/sgiwd93.c	1.8     -> 1.9    
#	 include/pcmcia/ss.h	1.23    -> 1.24   
#	arch/ppc/kernel/syscalls.c	1.11    -> 1.12   
#	arch/v850/kernel/rte_nb85e_cb.c	1.2     -> 1.3    
#	drivers/usb/misc/usbtest.c	1.16    -> 1.17   
#	drivers/scsi/arm/ecoscsi.c	1.19    -> 1.21   
#	include/linux/kernel_stat.h	1.11    -> 1.12   
#	        fs/cifs/TODO	1.6     -> 1.7    
#	arch/v850/kernel/as85ep1.c	1.2     -> 1.5    
#	arch/v850/sim85e2c.ld	1.3     -> 1.4     arch/v850/sim85e2.ld (moved)
#	      fs/cifs/misc.c	1.9     -> 1.10   
#	net/ipv4/ipvs/ip_vs_xmit.c	1.1     -> 1.2    
#	drivers/scsi/scsi_ioctl.c	1.20    -> 1.21   
#	drivers/media/common/saa7146_i2c.c	1.3     -> 1.5    
#	arch/sparc64/mm/fault.c	1.16    -> 1.17   
#	arch/ia64/scripts/toolchain-flags	1.2     -> 1.3    
#	drivers/ide/ppc/mpc8xx.c	1.5     -> 1.6    
#	drivers/block/cciss.c	1.83    -> 1.84   
#	drivers/parport/parport_pc.c	1.39    -> 1.40   
#	sound/oss/emu10k1/main.c	1.16    -> 1.18   
#	drivers/usb/gadget/ether.c	1.5     -> 1.7    
#	drivers/block/paride/pcd.c	1.34    -> 1.35   
#	      net/atm/clip.c	1.18    -> 1.20   
#	drivers/pci/setup-bus.c	1.17    -> 1.18   
#	  drivers/net/ni65.h	1.2     -> 1.3    
#	sound/oss/emu10k1/efxmgr.h	1.5     -> 1.6    
#	include/scsi/scsi_request.h	1.3     -> 1.4    
#	drivers/scsi/qlogicisp.c	1.21    -> 1.22   
#	drivers/md/dm-table.c	1.19    -> 1.20   
#	arch/ia64/kernel/ptrace.c	1.29    -> 1.30   
#	  drivers/scsi/esp.c	1.30    -> 1.31   
#	drivers/usb/net/pegasus.c	1.50    -> 1.51   
#	drivers/scsi/pcmcia/nsp_cs.c	1.23    -> 1.25   
#	drivers/s390/cio/cio.c	1.14    -> 1.16   
#	drivers/scsi/wd7000.c	1.27    -> 1.28   
#	include/asm-v850/nb85e_uart.h	1.2     -> 1.3     include/asm-v850/v850e_uart.h (moved)
#	drivers/serial/sunzilog.c	1.32    -> 1.33   
#	arch/ia64/kernel/init_task.c	1.10    -> 1.11   
#	drivers/scsi/arm/eesox.c	1.29    -> 1.30   
#	arch/ia64/kernel/smp.c	1.25    -> 1.26   
#	include/asm-i386/hw_irq.h	1.21    -> 1.23   
#	drivers/usb/image/hpusbscsi.c	1.31    -> 1.33   
#	  drivers/scsi/imm.c	1.23    -> 1.24   
#	arch/v850/kernel/gbus_int.c	1.6     -> 1.8    
#	drivers/block/acsi.c	1.51    -> 1.52   
#	drivers/char/ip2/i2lib.c	1.7     -> 1.8    
#	include/linux/elfcore.h	1.3     -> 1.4    
#	drivers/block/umem.c	1.39    -> 1.40   
#	drivers/scsi/sym53c8xx_2/sym_glue.h	1.9     -> 1.10   
#	drivers/scsi/qla1280.c	1.38    -> 1.40   
#	include/linux/loop.h	1.16    -> 1.17   
#	drivers/scsi/qlogicfas.c	1.22    -> 1.24   
#	drivers/scsi/atari_scsi.c	1.9     -> 1.10   
#	net/ipv6/xfrm6_input.c	1.11    -> 1.12   
#	arch/v850/kernel/Makefile	1.7     -> 1.8    
#	include/asm-v850/ptrace.h	1.2     -> 1.3    
#	    fs/nfs/nfs3xdr.c	1.25    -> 1.26   
#	include/asm-ppc/ipc.h	1.4     -> 1.5    
#	drivers/usb/image/microtek.c	1.32    -> 1.34   
#	     net/ipv4/ipip.c	1.30    -> 1.31   
#	drivers/s390/net/qeth.c	1.1     -> 1.2    
#	drivers/char/ip2main.c	1.39    -> 1.40   
#	include/linux/nfs_fs_sb.h	1.10    -> 1.11   
#	drivers/scsi/aacraid/rx.c	1.3     -> 1.4    
#	sound/oss/emu10k1/recmgr.c	1.4     -> 1.5    
#	arch/v850/kernel/highres_timer.c	1.1     -> 1.2    
#	drivers/scsi/53c7xx.c	1.18    -> 1.19   
#	drivers/scsi/sun3_scsi_vme.c	1.6     -> 1.7    
#	include/asm-v850/entry.h	1.2     -> 1.3    
#	include/asm-s390/dma-mapping.h	1.1     -> 1.2    
#	drivers/usb/storage/debug.h	1.6     -> 1.7    
#	drivers/scsi/sym53c8xx_2/sym_glue.c	1.26    -> 1.27   
#	    net/atm/common.c	1.32    -> 1.38   
#	drivers/scsi/tmscsim.c	1.21    -> 1.22   
#	               (new)	        -> 1.1     drivers/media/video/hexium_orion.c
#	               (new)	        -> 1.1     drivers/media/dvb/ttusb-budget/Kconfig
#	               (new)	        -> 1.1     drivers/media/dvb/frontends/tda1004x.c
#	               (new)	        -> 1.1     include/asm-v850/v850e2.h
#	               (new)	        -> 1.1     drivers/media/dvb/ttusb-dec/ttusb_dec.h
#	               (new)	        -> 1.1     drivers/md/dm-ioctl-v4.c
#	               (new)	        -> 1.1     drivers/media/dvb/frontends/mt312.h
#	               (new)	        -> 1.1     include/asm-v850/sim85e2s.h
#	               (new)	        -> 1.1     include/linux/dm-ioctl-v4.h
#	               (new)	        -> 1.2     drivers/media/dvb/frontends/mt312.c
#	               (new)	        -> 1.2     drivers/media/dvb/b2c2/Makefile
#	               (new)	        -> 1.1     drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h
#	               (new)	        -> 1.1     include/asm-v850/v850e_uartb.h
#	               (new)	        -> 1.1     drivers/media/dvb/ttpci/ttpci-eeprom.h
#	               (new)	        -> 1.1     drivers/media/dvb/ttusb-dec/Kconfig
#	               (new)	        -> 1.1     drivers/pci/remove.c
#	               (new)	        -> 1.1     include/asm-sparc64/sections.h
#	               (new)	        -> 1.1     sound/oss/hal2.h
#	               (new)	        -> 1.1     drivers/media/video/hexium_gemini.c
#	               (new)	        -> 1.1     include/asm-v850/serial.h
#	               (new)	        -> 1.1     include/asm-v850/rte_me2_cb.h
#	               (new)	        -> 1.1     arch/v850/rte_me2_cb.ld
#	               (new)	        -> 1.1     drivers/media/video/hexium_gemini.h
#	               (new)	        -> 1.1     arch/ia64/scripts/check-model.c
#	               (new)	        -> 1.1     arch/v850/kernel/me2.c
#	               (new)	        -> 1.1     include/asm-i386/local.h
#	               (new)	        -> 1.1     drivers/media/dvb/ttusb-dec/fdump.c
#	               (new)	        -> 1.1     arch/v850/kernel/rte_me2_cb.c
#	               (new)	        -> 1.1     drivers/media/dvb/ttusb-dec/Makefile
#	               (new)	        -> 1.1     include/asm-sparc64/local.h
#	               (new)	        -> 1.1     drivers/media/dvb/b2c2/Kconfig
#	               (new)	        -> 1.1     arch/v850/kernel/v850e2_cache.c
#	               (new)	        -> 1.1     include/asm-v850/v850e2_cache.h
#	               (new)	        -> 1.1     drivers/media/dvb/ttpci/ttpci-eeprom.c
#	               (new)	        -> 1.1     drivers/media/common/saa7146_vv_ksyms.c
#	               (new)	        -> 1.2     drivers/media/dvb/b2c2/skystar2.c
#	               (new)	        -> 1.1     sound/oss/hal2.c
#	               (new)	        -> 1.2     sound/oss/harmony.c
#	               (new)	        -> 1.1     drivers/media/video/hexium_orion.h
#	               (new)	        -> 1.1     include/asm-generic/local.h
#	               (new)	        -> 1.1     include/asm-v850/sim85e2.h
#	               (new)	        -> 1.1     include/asm-v850/v850e_uarta.h
#	               (new)	        -> 1.2     include/asm-ia64/local.h
#	               (new)	        -> 1.2     sound/oss/kahlua.c
#	               (new)	        -> 1.1     drivers/media/dvb/ttusb-dec/ttusb_dec.c
#	               (new)	        -> 1.1     drivers/media/video/hexium.h
#	               (new)	        -> 1.1     include/asm-v850/me2.h
#	               (new)	        -> 1.1     drivers/media/dvb/ttusb-dec/dec2000_frontend.c
#	               (new)	        -> 1.1     drivers/md/dm-ioctl-v1.c
#	               (new)	        -> 1.1     drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
#	               (new)	        -> 1.1     drivers/media/dvb/ttusb-budget/Makefile
#	               (new)	        -> 1.1     include/linux/dm-ioctl-v1.h
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/07/13	torvalds@home.osdl.org	1.1455.2.4
# Linux 2.6.0-test1
# 
# First "test" kernel. Same naming we used for 2.4.0 - there it took
# from May to December to get to the real version. Let's see if we
# can do it faster this time.
# --------------------------------------------
# 03/07/13	davem@kernel.bkbits.net	1.1455.1.3
# Merge davem@nuts.ninka.net:/home/davem/src/BK/net-2.5
# into kernel.bkbits.net:/home/davem/net-2.5
# --------------------------------------------
# 03/07/13	david@csse.uwa.edu.au	1.1455.2.5
# [PATCH] USB: Adding DSS-20 SyncStation to ftdi_sio
# 
# Patch for 2.4.22 ftdi_sio to add DSS-20 SyncStation to ftdi_sio - the
# SyncStation is the usb cradle for the Sony Ericsson P800 phone.
# --------------------------------------------
# 03/07/13	greg@kroah.com	1.1455.3.1
# Merge bk://soma.bkbits.net/linux-2.5-cpci
# into kroah.com:/home/linux/BK/pci-2.5
# --------------------------------------------
# 03/07/13	ganesh@vxindia.veritas.com	1.1455.2.6
# [PATCH] USB: more ids for ipaq
# 
# 3 more device ids added to ipaq.c/ipaq.h
# 
#  Added ids for the Rover P5, Toshiba E310 and E335. Thanks to
#  Matthijs van der Molen, Pavel Stoliarov, Tod B. Schmidt and
#  Matt Hartley.
# --------------------------------------------
# 03/07/13	nkiesel@tbdnetworks.com	1.1455.3.2
# [PATCH] PCI: fixup for compile error in pci/legacy.c
# 
# the last patch forgot to fix the debug code.
# --------------------------------------------
# 03/07/13	greg@kroah.com	1.1455.3.3
# PCI: fix up error for when CONFIG_PCI=n and scsi.h is included.
# --------------------------------------------
# 03/07/14	maneesh@in.ibm.com	1.1455.1.4
# [PATCH] vfsmount_lock-fix
# 
# This fixes one place where I missed the replacing dcache_lock with
# vfsmount_lock in put_namespace().
# 
# Tested with CLONE_NEWNS flag also.
# --------------------------------------------
# 03/07/14	randy.dunlap@verizon.net	1.1455.1.5
# [PATCH] syncppp: incomplete function prototype
# 
# This fixes this warning:
# 
#   syncppp.c:165: warning: function declaration isn't a prototype
# 
# by adding "void" as the function parameter list.
# --------------------------------------------
# 03/07/14	randy.dunlap@verizon.net	1.1455.1.6
# [PATCH] reduce stack usage in wanrouter
# 
# From Jorn Engel <joern@wohnheim.fh-wedel.de> and Randy Dunlap.
# 
# It reduces stack usage in the WAN router by about 0x500 bytes
# (from 0x520 to 0x24 when I did it in April).
# --------------------------------------------
# 03/07/14	randy.dunlap@verizon.net	1.1455.1.7
# [PATCH] unchecked return code of copy_to_user in read_profile
# 
# From Daniele Bellucci <bellucda@tiscali.it>.
# 
# Check the copy_to_user() return code in read_profile().
# --------------------------------------------
# 03/07/14	randy.dunlap@verizon.net	1.1455.1.8
# [PATCH] busmouse: fix memory leak and misc_register failure
# 
# From Flavio B. Leitner. <fbl@netbank.com.br>
# 
# Fix a memory leak and an unchecked return code in the busmouse driver.
# --------------------------------------------
# 03/07/14	alex@ssi.bg	1.1455.1.9
# [PATCH] Fix irq handling of IO-APIC edge IRQs on UP
# 
# send_IPI_self is needed to resend irqs with IRQ_PENDING status when
# enabled.
# 
# Checked with Ingo, and it's in 2.4-ac for some time.
# 
# This should fix ide lost interrupts on UP with IO-APIC
# 
# Ide trigers it this way:
#  - disable_irq
#  - do stuff that triggers IRQ.
#  - irq is IRQ_PENDING
#  - enable_irq
#  - IRQ is lost, needs to be resend.
# 
# I'll send the patch to fixup IDE disable_irq logic to Bart.
# --------------------------------------------
# 03/07/14	chyang@clusterfs.com	1.1455.1.10
# [PATCH] unresolved symbol with moduled intermezzo
# 
# This solves the unresolved symbol problem with modular intermezzo.  Also
# update the MAINTAINERS entry.
# --------------------------------------------
# 03/07/14	jgarzik@pobox.com	1.1455.1.11
# [PATCH] Large PCI bus numbers
# 
# ppc64 machines can have PCI bus numbers larger than 8 bits, but it looks
# like pci_device_to_OF_node already handles this case, in both 2.4 and
# 2.5.
# 
# We just need the space to store them.
# --------------------------------------------
# 03/07/14	lethal@linux-sh.org	1.1455.1.12
# [PATCH] pvr2fb update
# 
# Here's an update for pvr2fb (with a patch this time), which makes it compile
# again.
# --------------------------------------------
# 03/07/14	lethal@linux-sh.org	1.1455.1.13
# [PATCH] PCMCIA: Update hd64465 driver
# 
# This patch updates the sh-specific hd64465 pcmcia driver for the new API, as
# well as fixing up some other issues (such as remap_page_range() abuse -- we
# remap through P3 area instead) which caused it not to compile. Changes by
# Dominik Brodowski and myself.
# --------------------------------------------
# 03/07/14	lethal@linux-sh.org	1.1455.1.14
# [PATCH] shwdt update
# 
# This patch includes quite a few changes and updates for the shwdt driver (which
# brings it in sync with LinuxSH CVS HEAD). This fixes up support for the SH-2,
# and also fixes up some timer brain-damage.
# --------------------------------------------
# 03/07/14	agrover@groveronline.com	1.1461
# ACPI: Dynamically allocate SDT list (suggested by Andi Kleen)
# --------------------------------------------
# 03/07/14	agrover@groveronline.com	1.1462
# Merge groveronline.com:/root/bk/linux-2.5
# into groveronline.com:/root/bk/linux-acpi
# --------------------------------------------
# 03/07/14	agrover@groveronline.com	1.1463
# ACPI: Update version, and other trivialities
# --------------------------------------------
# 03/07/14	greg@kroah.com	1.1455.2.7
# [PATCH] USB: fixed up pci slot_name accesses in usb code
# --------------------------------------------
# 03/07/14	greg@kroah.com	1.1455.2.8
# [PATCH] USB: fixed up pci slot_name accesses in usb gadget code
# --------------------------------------------
# 03/07/14	willy@debian.org	1.1388.5.3
# [PATCH] ia64: Add some devinits to pci.c
# 
# These functions can all be devinit as they're all called from functions
# which are themselves devinit.
# --------------------------------------------
# 03/07/14	greg@kroah.com	1.1455.3.4
# [PATCH] PCI: remove usages of pci slot_name from the pci core code.
# --------------------------------------------
# 03/07/14	greg@kroah.com	1.1455.3.5
# [PATCH] PCI: remove usages of pci slot_name from acpi pci hotplug driver
# --------------------------------------------
# 03/07/14	greg@kroah.com	1.1455.1.15
# Merge kroah.com:/home/greg/linux/BK/bleed-2.5
# into kroah.com:/home/greg/linux/BK/gregkh-2.5
# --------------------------------------------
# 03/07/14	greg@kroah.com	1.1455.4.1
# Merge kroah.com:/home/greg/linux/BK/bleed-2.5
# into kroah.com:/home/greg/linux/BK/pci-2.5
# --------------------------------------------
# 03/07/14	davidm@tiger.hpl.hp.com	1.1455.5.1
# Merge tiger.hpl.hp.com:/data1/bk/vanilla/linux-2.5
# into tiger.hpl.hp.com:/data1/bk/lia64/to-linus-2.5
# --------------------------------------------
# 03/07/14	mdharm-usb@one-eyed-alien.net	1.1455.1.16
# [PATCH] USB: convert ISD200 and Jumpshot to DMA-safe buffer
# 
# This patch converts the ISD200 and Jumpshot drivers to use the new DMA-safe
# buffer.
# 
# 
# I'd also like to take a moment to thank Alan Stern, who writes many of
# these patches.  Without his help, many of the improvements everyone has
# seen over the 2.5.x series would not have been possible.
# --------------------------------------------
# 03/07/14	mdharm-usb@one-eyed-alien.net	1.1455.1.17
# [PATCH] USB: remove now-dead mode-translation code
# 
# This patch removes all of the mode-translation logic.  It's no longer
# needed, as the upper-level drivers now all issue the proper 10-byte
# commands.  This is a large patch, but what it's doing is removing a great
# deal of unneeded code -- about 650+ lines removed, according to diffstat.
# 
# Those of you who are having some trouble getting your DVD-RAMs detected
# properly should have all your problems solved by an upcoming patch from the
# SCSI folks.  It may look like that problem is related to this patch, but it
# isn't -- it's a side-effect of another SCSI patch to consolidate code.
# 
# Special thanks to James Bottomley for being patient enough to work with me
# on these issues on the SCSI layer.
# 
# This, BTW, makes US_FL_MODE_XLATE a NOP.  The symbol is kept for the
# purpose of allowing unusual_devs.h to be consistent between 2.4 and 2.5
# 
# There are still a few places where more code could (potentially) be
# removed.  I need to mull over the UFI specification to be sure, tho.
# --------------------------------------------
# 03/07/14	albertogli@telpin.com.ar	1.1455.6.1
# [IPVS]: Fix typo in Kconfig file.
# --------------------------------------------
# 03/07/14	ak@muc.de	1.1455.6.2
# [NET]: Turn softnet_data into per-cpu data.
# --------------------------------------------
# 03/07/14	chas@cmf.nrl.navy.mil	1.1455.6.3
# [ATM]: Cleanup pppoatm_ioctl_hook.
# --------------------------------------------
# 03/07/14	chas@cmf.nrl.navy.mil	1.1455.6.4
# [ATM]: Cleanup br2684_ioctl_hook.
# --------------------------------------------
# 03/07/14	kunihiro@ipinfusion.com	1.1455.6.5
# [IPSEC/IPV6]: Add missing email address to my copyrights.
# --------------------------------------------
# 03/07/14	willy@debian.org	1.1455.5.2
# [PATCH] ia64: use has_8259 in acpi_register_irq()
# 
# acpi_madt is marked as __initdata, so an attempt to use
# acpi_register_irq() after we discarded init sections would cause us to
# dereference a random location.  Everywhere else uses has_8259 anyway.
# --------------------------------------------
# 03/07/15	paulus@samba.org	1.1455.7.1
# Merge samba.org:/home/paulus/kernel/linux-2.5
# into samba.org:/home/paulus/kernel/for-linus-ppc
# --------------------------------------------
# 03/07/14	davidm@tiger.hpl.hp.com	1.1455.5.3
# ia64: Set the PRT entry's irq member in iosapic_parse_prt().
# --------------------------------------------
# 03/07/14	davidm@tiger.hpl.hp.com	1.1455.5.4
# ia64: Small fixes for 2.6.0-test1 merge.
# --------------------------------------------
# 03/07/15	davem@nuts.ninka.net	1.1455.6.6
# [TCP/IPV6]: Check for anycast where we check for multicast.
# --------------------------------------------
# 03/07/15	paulus@samba.org	1.1455.7.2
# PPC32: Add some more system calls - tgkill, utimes, [f]statfs64.
# 
# Patch from Anton Blanchard.  Also reserves a syscall for swapcontext
# and updates the _syscallN macros.
# --------------------------------------------
# 03/07/15	paulus@samba.org	1.1455.7.3
# PPC32: Add SEMTIMEDOP.  Patch from Anton Blanchard.
# --------------------------------------------
# 03/07/15	paulus@samba.org	1.1455.7.4
# PPC32: Eliminate duplicate variable declarations in arch/ppc/kernel/time.c
# --------------------------------------------
# 03/07/15	paulus@samba.org	1.1455.7.5
# PPC32: Fix compilation of powermac CPU frequency switching support.
# --------------------------------------------
# 03/07/15	greg@kroah.com	1.1455.4.2
# [PATCH] PCI: fix problem with pci remove functions not being built if CONFIG_HOTPLUG was not set
# 
# This fixes a build problem on sparc, and hopefully will prevent this from
# happening in the future...
# --------------------------------------------
# 03/07/15	greg@kroah.com	1.1455.1.18
# [PATCH] USB: remove some warnings when building the documentation.
# --------------------------------------------
# 03/07/15	greg@kroah.com	1.1455.1.19
# [PATCH] USB: flush all in-flight urbs _before_ disconnect() is called.
# 
# This solves the module unload problem for some usb-serial drivers
# (like visor.c and ftdi_sio.c), and makes usb drivers much simpler.
# --------------------------------------------
# 03/07/15	greg@kroah.com	1.1455.1.20
# [PATCH] USB: fix up bluetty driver's tty and devfs names.
# --------------------------------------------
# 03/07/15	greg@kroah.com	1.1455.1.21
# [PATCH] USB: fix up cdc-acm driver's tty and devfs names.
# --------------------------------------------
# 03/07/15	davidm@tiger.hpl.hp.com	1.1455.5.5
# ia64: Change per-CPU implementation so that __get_cpu_var() returns the
# 	canonical address (l-value).  To get the virtually mapped
# 	alias (which is more efficient), use __ia64_per_cpu_var().  The
# 	latter is safe only if the address of the l-value is never passed
# 	to another CPU (i.e., not stored in any global place).
# 	For extremely efficient, portable per-CPU variables, there is
# 	now a new API local.h which was introduced by Rusty Russell.
# 	To use this, declare a variable of type local_t as a per-CPU
# 	variable and then use {__,}cpu_local_FOO() to manipulate such
# 	variables.  This patch also updated the atomic interface with
# 	a 64-bit counter.
# --------------------------------------------
# 03/07/15	david-b@pacbell.net	1.1455.1.22
# [PATCH] USB: ohci minor tweaks
# 
# Two small updates:
# 
#   - Report short control reads correctly in an exotic case
#     that our regression tests cover.  (Haven't run them with
#     ohci for a long time, it seems...)
# 
#   - IRQ non-delivery bugs (ACPI, APIC, etc) can prevent urbs
#     from unlinking.  This prints a warning when that sort of
#     non-USB bug is biting.
# --------------------------------------------
# 03/07/15	david-b@pacbell.net	1.1455.1.23
# [PATCH] USB: usb net drivers SET_NETDEV_DEV
# 
# I noticed that Viro's "use alloc_etherdev" patch left a
# small problem:  only "usbnet" did SET_NETDEV_DEV, and
# that used the wrong driver model device.
# 
# This has all the usb network drivers use SET_NETDEV_DEV,
# so the /sys/class/net/*/{device,driver} files link to the
# relevant usb interface and to its device driver.
# --------------------------------------------
# 03/07/15	david-b@pacbell.net	1.1455.1.24
# [PATCH] USB: ethernet gadget learns about pxa2xx udc
# 
# The original code needed some updates to work properly with
# the USB Device Controller found in Intel's PXA 2xx processors.
# 
#    - SET_INTERFACE is effectively unusable.  So the driver
#      now has a "minimalist" mode, with none of the bells and
#      whistles of CDC.
# 
#    - The config symbol will be CONFIG_USB_PXA2XX, since the
#      same controller (modulo errata) is in several processors
#      other than the "older" pxa250.
# 
# For the record, that "minimalist" mode was the original idea
# behind this driver ... implementing CDC was a win for interop
# since most non-MSFT host operating systems support it already,
# without needing a new driver.
# 
# There were also a few other minor updates:
# 
#    - Net2280:  queue depth shrank a bit, don't use the same
#      endpoint numbers for the IN and OUT sides.  (CATC doesn't
#      let filters consider direction, just numbers.)
# 
#    - Join the Jihad!  Abolish register_netdev()!!  This just
#      nests the gadget-private data structures inside the
#      netdev data structure, instead of the other way around.
# 
#    - Minor cleanups.
# --------------------------------------------
# 03/07/15	david-b@pacbell.net	1.1455.1.25
# [PATCH] USB: usbtest, autoconfigure from descriptors
# 
# Not all gadget controllers support ep2in-bulk and ep2out-bulk,
# unlike the EZ-USB (non-FX2) devices or the net2280.
# 
# So this patch teaches "usbtest" how to look at the descriptors
# it's given, and use the appropriate endpoints.  This helps
# support Linux test devices using hardware like the pxa2xx UDC,
# and other controllers.
# --------------------------------------------
# 03/07/15	david-b@pacbell.net	1.1455.1.26
# [PATCH] USB: gadget zero learns about pxa2xx udc
# 
# The original code needed some updates to work properly with
# the USB Device Controller found in Intel's PXA 2xx processors.
# 
#   - SET_INTERFACE and SET_CONFIGURATION involve hardware
#     automagic:  all endpoints get reset.  This is a PITA,
#     and will likely get more work.  (Seems like the reset
#     is only partial, hosts need to CLEAR_HALT themselves...)
# 
#     What this does is to handle -ECONNABORTED notifications
#     from pxa2xx_udc, in those cases.  In general, gadget
#     drivers need to reset endpoints themselves, since the
#     lower levels (hardware!) won't know how the endpoints
#     are allocated between interfaces and altsettings.
# 
#   - The config symbol will be CONFIG_USB_PXA2XX, since the
#     same controller (modulo errata) is in several processors
#     other than the "older" pxa250.
# 
#   - This also adds an "i/o pattern" parameter, so that it
#     can continue to use the "all zeroes" pattern or switch
#     to something else.  The initial "something else" is an
#     easily predicted "mod63" pattern.
# --------------------------------------------
# 03/07/15	henning@meier-geinitz.de	1.1455.1.27
# [PATCH] USB: fix open/probe race in scanner driver
# 
# This patch from Oliver Neukum fixes a race between open and
# probe.
# --------------------------------------------
# 03/07/15	henning@meier-geinitz.de	1.1455.1.28
# [PATCH] USB: New vendor/product ids for scanner driver
# 
# this patch adds new vendor/product ids for Avision, Canon, HP,
# Microtek and Relisys scanners.
# --------------------------------------------
# 03/07/15	davidm@tiger.hpl.hp.com	1.1455.5.6
# Fix patch breakage.
# --------------------------------------------
# 03/07/15	oliver@neukum.org	1.1455.1.29
# [PATCH] USB: fix race between open() and probe()
# 
# registering the device before setting the interface data can lead
# to a null pointer being followed in open(). This patch fixes that.
# --------------------------------------------
# 03/07/15	oliver@neukum.org	1.1455.1.30
# [PATCH] USB: fix layering violation in usblp
# 
# writing urb->status is a no go area for drivers.
# --------------------------------------------
# 03/07/15	stern@rowland.harvard.edu	1.1455.1.31
# [PATCH] USB: More unusual_devs.h entry updates
# 
# Here are more user-reported updates for unusual_devs.h.
# --------------------------------------------
# 03/07/15	greg@kroah.com	1.1455.1.32
# [PATCH] USB: fix a nasty use-after-free bug in the usb-serial core.
# --------------------------------------------
# 03/07/15	davidm@wailua.hpl.hp.com	1.1455.5.7
# ia64: Patch by Arun Sharma: Make execve()ing of ia32 tasks work again.
# 	The impact on native ia64 fork+execve performance as measured by
# 	LMbench is in the noise range (plus or minus 0.1%). The first two
# 	hunks in the patch are not together because we wanted to hide the
# 	memory latency.
# --------------------------------------------
# 03/07/15	kuznet@ms2.inr.ac.ru	1.1455.6.7
# [TCP/IPV6]: Another anycast check.
# --------------------------------------------
# 03/07/15	ja@ssi.bg	1.1455.6.8
# [IPV4/IPV6]: Fix use-after-free bugs in tunneling drivers.
# --------------------------------------------
# 03/07/15	shemminger@osdl.org	1.1455.6.9
# [NET]: Dynamic net_device for serial eql balancer.
# --------------------------------------------
# 03/07/15	chas@cmf.nrl.navy.mil	1.1455.6.10
# [ATM]: Use sk_state_change() and eliminate vcc->callback().
# --------------------------------------------
# 03/07/15	chas@cmf.nrl.navy.mil	1.1455.6.11
# [ATM]: Eliminate vcc->sleep in favor of sk->sk_sleep.
# --------------------------------------------
# 03/07/15	chas@cmf.nrl.navy.mil	1.1455.6.12
# [ATM]: Use sk_data_ready and sk_change_state instead of wake_up.
# --------------------------------------------
# 03/07/15	chas@cmf.nrl.navy.mil	1.1455.6.13
# [ATM]: Replace vcc->reply with sk->sk_err; implement sk_write_space.
# --------------------------------------------
# 03/07/15	greg@kroah.com	1.1455.1.33
# [PATCH] USB: fix memory leak in the visor driver.
# --------------------------------------------
# 03/07/15	rob@osinvestor.com	1.1455.8.1
# [SERIAL]: Do not use serio->private to track serio open status in sun drivers.
# 
# Issue discovered by Ricky Beam (jfbeam@bluetronic.net).
# --------------------------------------------
# 03/07/15	jfbeam@bluetronic.net	1.1455.8.2
# [SUNKBD]: Mark reset/layout as volatile.
# --------------------------------------------
# 03/07/16	davidm@tiger.hpl.hp.com	1.1455.5.8
# ia64: Put per-CPU data into .data.percpu section both for UP and MP.
# 	This ensures that per-CPU data is "addl"-addressable even
# 	on UP.
# --------------------------------------------
# 03/07/16	davem@cheetah.ninka.net	1.1455.9.1
# [SPARC64]: Fix pbus->sysdata interpretation in pci_domain_nr().
# --------------------------------------------
# 03/07/16	davem@nuts.ninka.net	1.1455.8.3
# [SPARC64]: Fix assumptions about data section ordering and objects ending up in .data vs .bss
# --------------------------------------------
# 03/07/16	davem@nuts.ninka.net	1.1455.8.4
# Merge cheetah:src/BK/sparc-2.5
# into nuts.ninka.net:/home/davem/src/BK/sparc-2.5
# --------------------------------------------
# 03/07/16	yoshfuji@linux-ipv6.org	1.1455.6.14
# [IPV6]: Get reference to neigh/dev when building ndisc DST.
# --------------------------------------------
# 03/07/16	wensong@linux-vs.org	1.1455.6.15
# [IPV4]: Add the defense timer for IPVS.
# --------------------------------------------
# 03/07/16	wensong@linux-vs.org	1.1455.6.16
# [IPV4]: Remove the unnecessay del_timer_sync call in IPVS connection expire.
# --------------------------------------------
# 03/07/16	wensong@linux-vs.org	1.1455.6.17
# [IPV4]: Do not use proto for route output in IPVS.
# --------------------------------------------
# 03/07/16	oliver@neukum.org	1.1455.1.34
# [PATCH] USB: fix irq urb in hpusbscsi
# 
# this fixes the completion handler for the interrupt urb in hpusbscsi.
# --------------------------------------------
# 03/07/16	oliver@neukum.org	1.1455.1.35
# [PATCH] USB: fix race between probe and open in skeleton
# 
# registering a device only partially initialised is quite bad an
# idea.
# --------------------------------------------
# 03/07/16	david-b@pacbell.net	1.1455.1.36
# [PATCH] USB: ethernet gadget, another pxa update
# 
#   - #ifdefs out some code that never runs on the pxa
#   - catches "alloc_etherdev Jihad" changes I somehow missed
# --------------------------------------------
# 03/07/16	oliver@neukum.org	1.1455.1.37
# [PATCH] USB: usblcd: race between open and read/write
# 
# usblcd registers a device before all buffers are allocated leading
# to a race resulting in NULL pointers being followed.
# This fixes it.
# --------------------------------------------
# 03/07/16	stern@rowland.harvard.edu	1.1455.1.38
# [PATCH] USB: I/O buffering for sddr09
# 
# This patch makes the sddr09 subdriver use proper DMA I/O buffering.
# --------------------------------------------
# 03/07/16	stern@rowland.harvard.edu	1.1455.1.39
# [PATCH] USB: Make sddr55 use proper I/O buffering
# 
# This patch makes the sddr55 subdriver use proper DMA I/O buffering.
# --------------------------------------------
# 03/07/16	jbarnes@sgi.com	1.1455.5.9
# [PATCH] ia64: fix GENERIC compile
# 
# This will fix the generic compile by removing sn2 from the list of
# targets, since it depends on the new discontig code, which hasn't gone
# in yet.
# --------------------------------------------
# 03/07/16	stevef@steveft21.ltcsamba	1.1444.8.1
# Fix inverted kmalloc parm ordering (noticed by Zwane) that caused oops on mounts of long server names (reported on bugzilla).  Fix multiuser mount option.
# --------------------------------------------
# 03/07/16	stevef@steveft21.ltcsamba	1.1455.10.1
# Merge bk://cifs.bkbits.net/linux-2.5cifs
# into steveft21.ltcsamba:/usr/src/bk/linux-2.5cifs
# --------------------------------------------
# 03/07/16	davidm@tiger.hpl.hp.com	1.1455.5.10
# ia64: If the compiler supports it, use attribute (model (small)) to
# 	tell the compiler that per-CPU variables can be addressed
# 	with "addl".
# 
# 	On the simulator kernel, this saves about 2776 bytes in the
# 	kernel image.  On a zx1 kernel, it saves about 5593 bytes.
# 	As per-CPU variables are used more, these savings will
# 	increase, of course.
# --------------------------------------------
# 03/07/17	paulus@samba.org	1.1455.7.6
# PPC32: Remove unused fields from irq_cpustat_t.
# --------------------------------------------
# 03/07/17	paulus@samba.org	1.1455.7.7
# PPC32: PCI mapping fixes for non-cache-coherent PPC machines.
# --------------------------------------------
# 03/07/17	paulus@samba.org	1.1455.7.8
# PPC32: Make FP exceptions enabled by default.
# --------------------------------------------
# 03/07/17	paulus@samba.org	1.1455.7.9
# PPC32: Change mm_segment_t definitions to simplify the code.
# --------------------------------------------
# 03/07/17	anton@samba.org	1.1358.11.10
# [PATCH] sym2 error handler sleeps with irqs off
# 
# The scsi error handler calls driver error handlers with the host_lock
# taken. We need to drop it before calling down() in the sym2 driver.
# --------------------------------------------
# 03/07/17	axboe@suse.de	1.1358.11.11
# [PATCH] Consolidate SCSI requeueing and add blk elevator hook
# 
# This patch removes the scsi mid layer dependency on __elv_add_request
# and introduces a new blk_requeue_request() function so the block
# layer specificially knows a requeue is in progress.
# 
# It also adds an elevator hook for elevators like AS which need to
# hook into the requeue for correct adjustment of internal counters.
# --------------------------------------------
# 03/07/17	torvalds@home.osdl.org	1.1455.11.1
# Revert PCI bus number size increase - it isn't even needed
# on 2.5+, since ppc64 can (and does) use the PCI domain numbers
# for this instead.
# 
# The PCI domain support should be back-ported to 2.4.x rather
# than having bigger PCI bus numbers.
# 
# Cset exclude: jgarzik@pobox.com|ChangeSet|20030714162217|61624
# --------------------------------------------
# 03/07/17	torvalds@home.osdl.org	1.1464
# Merge http://linux-acpi.bkbits.net/linux-acpi
# into home.osdl.org:/home/torvalds/v2.5/linux
# --------------------------------------------
# 03/07/17	B.Zolnierkiewicz@elka.pw.edu.pl	1.1465
# [PATCH] fix IDE irq disable logic
# 
# Since the IO-APIC irq disable fix went in we can now enable
# the proper IRQ disabling in the IDE driver again. That had
# been disabled due to the problems with UP IO-APIC.
# --------------------------------------------
# 03/07/17	B.Zolnierkiewicz@elka.pw.edu.pl	1.1466
# [PATCH] Fix dma timeout bugs
# 
# From Alexander Atanasov <alex@ssi.bg>
# 
# Fix DMA I/O and state machine fixes, error recovery
# --------------------------------------------
# 03/07/17	torvalds@home.osdl.org	1.1467
# Merge bk://kernel.bkbits.net/gregkh/linux/pci-2.5
# into home.osdl.org:/home/torvalds/v2.5/linux
# --------------------------------------------
# 03/07/17	thomr9am@ss1000.ms.mff.cuni.cz	1.1468
# [PATCH] fix emu10k1 removal oops
# 
# All of the cleanup functions in sound/oss/emu10k1/main.c were incorrectly
# marked as __devinit. This little one fixes it, so that the module no longer
# oopses when being removed.
# --------------------------------------------
# 03/07/17	torvalds@home.osdl.org	1.1469
# Merge bk://kernel.bkbits.net/davem/sparc-2.5
# into home.osdl.org:/home/torvalds/v2.5/linux
# --------------------------------------------
# 03/07/17	torvalds@home.osdl.org	1.1470
# Merge bk://kernel.bkbits.net/davem/net-2.5
# into home.osdl.org:/home/torvalds/v2.5/linux
# --------------------------------------------
# 03/07/17	torvalds@home.osdl.org	1.1471
# Add "clock_t_to_jiffies()" conversion function with
# some rather minimal overflow protection. 
# --------------------------------------------
# 03/07/17	mikpe@csd.uu.se	1.1472
# [PATCH] make clean should remove usr/initramfs_data.S
# 
# The kernel build leaves a temp file in linux/usr/ that make clean
# doesn't remove.  Fixed in the patch below.
# --------------------------------------------
# 03/07/17	petero2@telia.com	1.1473
# [PATCH] Incorrect timeout in CDROM_SEND_PACKET ioctl
# 
# The CDROM_SEND_PACKET ioctl passes a struct cdrom_generic_command from
# user space, which contains a timeout field.
# 
# The timeout is measured in jiffies, but the conversion from user to
# kernel jiffies is missing, which makes the timeout 10 times shorter than
# it should be in 2.5 kernels on x86.  This causes CDRW formatting with
# cdrwtool to fail.  The following patch fixes this problem.
# --------------------------------------------
# 03/07/17	hunold@convergence.de	1.1474
# [PATCH] Update the saa7146 driver core
# 
#  - fix WRITE_RPS0 and WRITE_RPS1 inlines, fix usage in mxb and budget
#    drivers
#  - export "saa7146_start_preview" and "saa7146_stop_preview" to allow
#    drivers to start and stop video overlay (necessary for analog module
#    support in the av7110 driver)
#  - fix i2c implementation: some frontend drivers transfer a huge amount
#    of firmware data (> 30kB), speed up the transmission by busy waiting
#    between byte transfers for bigger transmissions
#  - change ioctl function in various driver to accept a saa7146
#    filehandle instead of a saa714 device structure
# --------------------------------------------
# 03/07/17	hunold@convergence.de	1.1475
# [PATCH] Various small fixes in dvb-core
# 
#  - indentation fixes in dvb_demux.c
#  - include cleanup in various files
#  - simplify dvb/ttpci/Makefile
# --------------------------------------------
# 03/07/17	hunold@convergence.de	1.1476
# [PATCH] Major dvb net code cleanup, many fixes
# 
#  - code review and fix the old race condition in dev->set_multicast_list
#  - use tq_schedule instead of tq_immediate
#  - remove card_num and dev_num from struct dvb_net (now obsolete)
#  - prevent interface from being removed while it is in use
#  - allow add/remove only for the superuser
#  - set check-CRC flag on section filter to drop broken packets
#  - some more debug printfs in filter handling code
#  - cleaned up and commented packet reception handler
#  - fix formatting
# --------------------------------------------
# 03/07/17	hunold@convergence.de	1.1477
# [PATCH] Update dvb frontend drivers
# 
#  - grundig_29504-401.c: fix charge pump and band switch setting bug,
#    caught by Robert Schlabbach <robert_s@gmx.net>
#  - grundig_29504-401.c: pass apply_frontend_param() return value to
#    upper layers
#  - grundig_29504-401.c: try to make a more specific detection mechanism
#  - grundig_29504-491.c:remove bogus out-of-range check, FEC table index
#    is limited to 0...7 due to &= ~0x03 anyway...
#  - nxt6000.c: Patch by Paul Andreassen: Add Support for Comtech
#    DVBT-6k07 (PLL IC: SP5730)
#  - ves1820.c: use Robert Schlabbach's suggestions for CLKCONF (0x03) and
#    CARCONF (0x04)
#  - alps_bsrv2.c: don't enable voltage on init + inversion bugfix
# --------------------------------------------
# 03/07/17	hunold@convergence.de	1.1478
# [PATCH] Add Zarlink MT312 DVB-T frontend driver
# 
#  - Zarlink MT312 satellite channel decoder driver contributed by Andreas
#    Oberritter
# --------------------------------------------
# 03/07/17	hunold@convergence.de	1.1479
# [PATCH] Update the DVB budget drivers
# 
#  - follow changes in dvb_net, use new eeprom parse code to properly
#    detect the mac
#  - add new subvendor/subystem id pair
# --------------------------------------------
# 03/07/17	hunold@convergence.de	1.1480
# [PATCH] Update the DVB av7110 driver
# 
#  - Fix to 'Sharing SDRAM between TT re-insertion and OSD...' - OSD
#    didn't get the maximum available memory in one piece; needs new
#    firmware version 0x2616
#  - Improved performance when setting palette with full 256 color OSD
#  - read MAC from EEPROM if available, contributed by Michael Glaum
#    <mglaum@kvh.com>
#  - add some MODULE_PARM_DESC for modinfo
#  - add support for the "analog module" available for DVB-C cards: the
#    saa7113 is initialized and some more v4l2 ioctls are available.  you
#    can use "xawtv" now to switch between "dvb" and "analog" input.  when
#    you are one the "analog" input, you can tune in analog channels.
# --------------------------------------------
# 03/07/17	hunold@convergence.de	1.1481
# [PATCH] More saa7146 driver core updates
# 
#  - separate all EXPORT_SYMBOL stuff to saa7146_ksyms.c
#  - properly stop capturing when no more buffers are available (missing
#    register upload)
#  - make extension data a per-device member, not a per-extension member,
#    so that every device can have it's own private data (necessary for
#    DVB drivers which handle more than one device)
#  - implement field based capturing, ie.  capturing fields to different
#    capture buffers
#  - change default old of capture fields for ALTERNATE mode (comply with
#    bttv)
#  - follow these changes in various analog saa7146 based cards drivers
#    (mxb.c and dpc7146.c)
#  - follow these changes in various saa7146 based budget card drivers
# --------------------------------------------
# 03/07/17	hunold@convergence.de	1.1482
# [PATCH] Various kconfig and Makefile updates
# --------------------------------------------
# 03/07/17	hunold@convergence.de	1.1483
# [PATCH] Add a driver for the Technisat Skystar2 DVB card
# 
#  - add DVB driver for Technisat Skystar2 card, which is based on the
#    FlexCop2 chipset by B2C2
# --------------------------------------------
# 03/07/17	hunold@convergence.de	1.1484
# [PATCH] Add two drivers for Hexium frame grabber cards
# 
#  - add drivers for the Orion and Gemini frame grabber cards, based on
#    the saa7146.  For details, see http://www.hexium.hu/.  Thanks to
#    Michael Hunold <michael@mihu.de>.
# --------------------------------------------
# 03/07/17	hunold@convergence.de	1.1485
# [PATCH] More updates for the dvb core
# --------------------------------------------
# 03/07/17	hunold@convergence.de	1.1486
# [PATCH] Add TDA14500x DVB-T frontend driver
# 
#  - tda1004x DVB-T driver contributed by Andrew de Quincy and Robert
#    Schlalach
# --------------------------------------------
# 03/07/17	hunold@convergence.de	1.1487
# [PATCH] Update various other frontend drivers
# 
#  - In alps_tdlb7.c read SP8870 status reg to clear pending irqs in
#    FE_SET_FRONTEND, as suggested by Ragnar Sundblad to avoid frontend
#    hang-ups.
#  - the vp310 support in mt312.c support should be configured to 90Mhz,
#    too.  skystar2 driver with bugfixed master_xfer() should probably
#    work now.
# --------------------------------------------
# 03/07/17	hunold@convergence.de	1.1488
# [PATCH] Update the av7110 DVB driver
# 
#  - fix DMX_GET_STC to get the msb right
#  - follow changes in saa7146 driver core, separate some data for DVB-C
#    and DVB-S cards
# --------------------------------------------
# 03/07/17	hunold@convergence.de	1.1489
# [PATCH] Add two drivers for USB based DVB-T adapters
# 
#  - add two new usb dvb drivers:
#    o dvb-ttusb-budget.c for Technotrend/Hauppauge Nova-USB devices
#      (Thanks to Holger Waechtler <holger@convergence.de> and elix Domke
#      <tmbinc@gmx.net>)
#    o dvb-ttusb-dec.c for Technotrend/Hauppauge USB DEC2000-T devices
#      (Thanks to Alex Woods <linux-dvb@giblets.org>)
# --------------------------------------------
# 03/07/17	hunold@convergence.de	1.1490
# [PATCH] Update Technisat Skystar2 DVB driver
# 
# This is a follow-up patch to my latest patch series.  It fixes the
# problems and flaws Greg KH pointed out.
# 
# There was a typo in the Makefile, so the driver was never compiled.  But
# I assumed that it built without errors.  Doh!
# 
#  - update the Technisat Skystar2 driver:
#          - follow kernel coding rules, change comments
#          - change function return values from u32 to int where possible
#          - make all functions static
#          - comment out unused functions
#          - fix return values of functions to follow kernel rules
#          - removed bogus delay, read and write functions
# --------------------------------------------
# 03/07/17	torvalds@home.osdl.org	1.1491
# Merge bk://ppc.bkbits.net/for-linus-ppc
# into home.osdl.org:/home/torvalds/v2.5/linux
# --------------------------------------------
# 03/07/17	torvalds@home.osdl.org	1.1492
# Merge http://lia64.bkbits.net/to-linus-2.5
# into home.osdl.org:/home/torvalds/v2.5/linux
# --------------------------------------------
# 03/07/17	fcusack@fcusack.com	1.1493
# [PATCH] rpcsec_gss compatibility
# 
# start gss seq no at 1; netapp doesn't accept seq no 0.
# 
# Just as a data point, Solaris 9 client uses initial seq. no. 2.
# --------------------------------------------
# 03/07/17	fcusack@fcusack.com	1.1494
# [PATCH] Fix rpc_setbufsize() usage
# 
#  - fix null dereference on xprt->inet if (!connected), which happens if
#    a rpc cred wasn't available (root+auth_gss case)
#  - set bufsize on reconnect
# --------------------------------------------
# 03/07/17	fcusack@fcusack.com	1.1495
# [PATCH] Allow unattended nfs3/krb5 mounts
# 
# The comment in nfs_get_root() basically describes the patch:
# 
#     Some authentication types (gss/krb5, most notably)
#     are such that root won't be able to present a
#     credential for GETATTR (ie, getroot()).
# 
# An easy way (ie, without this patch) to have unattended mounts is to
# have a root/host@REALM (or similar) principal stashed in a keytab, which
# root (rather, gssd) can use.  However, this might not be desirable for
# many sites.  In any case, RFC2623 specifically describes the problem
# addressed here.
# 
# Notes:
# 
# - Root inode gets inum of 1.  This doesn't seem to matter, but may be
#   aesthetically unpleasing.  I wanted to choose an inum unlikely to
#   conflict with an existing inum (although NFS has specific support
#   for that).  It looks like more work than it's worth to change the
#   inum after the info is available.  AFAICT it's not critical info.
# 
# - Solaris has this "wierd" (but understandable)  behavior that after
#   mounting without a credential, the mount point is not visible at all
#   until an access is attempted with a credential.  This now-you-see-it-
#   now-you-don't behavior doesn't seem worthwhile to reproduce here.
# 
# - Unfortunately, MOUNT_VERSION must go to 5.  Some kernels with ver 4
#   do not understand pseudoflavor.  Keeping it at 4 means that the
#   userland mount can't know for sure whether the kernel accepted the
#   option or not.  (Unless I'm missing some hack that could be done.)
# 
# It works in my environment, against a netapp server (with the rpcsec_gss
# patch I provided earlier).
# --------------------------------------------
# 03/07/17	schwidefsky@de.ibm.com	1.1496
# [PATCH] s390: arch update
# 
#  - New default configuration.
#  - Fix get_tv32/put_tv32.
#  - Replace generic dma-mapping file with empty one.
#  - Remove wrong comment from dma.h.
# --------------------------------------------
# 03/07/17	schwidefsky@de.ibm.com	1.1497
# [PATCH] s390: irq stats.
# 
# Enable irq statistics for s390*. We defined NR_IRQS to 2, one for all i/o
# interrupts and one for all external interrupts.
# --------------------------------------------
# 03/07/17	schwidefsky@de.ibm.com	1.1498
# [PATCH] s390: dasd driver.
# 
# Remove put_disk from dasd_destroy_partitions. This is done in dasd_free_device.
# --------------------------------------------
# 03/07/17	schwidefsky@de.ibm.com	1.1499
# [PATCH] s390: common i/o layer.
# 
#  - Fix two memory leaks.
#  - Clear pending status in cio_enable_subchannel.
#  - Don't call device_unregister from interrupt context.
#  - Fix refcounting problems on static device structures for the ccw console.
#  - Delete timeouts for qdio after successful startup.
# --------------------------------------------
# 03/07/17	schwidefsky@de.ibm.com	1.1500
# [PATCH] s390: qeth network driver.
# 
#  - Reset netdevice to defaults in offline processing.
#  - Fix checksumming.
#  - Fix routing status display.
#  - Get rid of _ccw_device_get_device_number in qeth.
#  - Inline some functions to save stack space.
# --------------------------------------------
# 03/07/17	schwidefsky@de.ibm.com	1.1501
# [PATCH] s390: siginfo_t for s390x.
# 
# Correct size of siginfo_t for s390x (from 136 to 128).
# --------------------------------------------
# 03/07/17	bunk@fs.tum.de	1.1502
# [PATCH] remove all #include <blk.h>'s
# 
# This causes blk.h to print a warning and removes all uses of blk.h.
# I've tested the compilation in 2.6.0-test1 with a .config that tries to
# compile as many drivers as possible.
# --------------------------------------------
# 03/07/17	linux@thorsten-knabe.de	1.1503
# [PATCH] sound/oss/ad1816.c update
# 
# This fixes various problems with the AD1816 sound driver:
# 
#  - Compilation errors with CONFIG_PNP enabled fixed.
#  - PNP specific code rewritten.
#  - SMP fixes.
#  - DMA resource handling fixes.
#  - Other minor code cleanup.
# --------------------------------------------
# 03/07/17	torvalds@home.osdl.org	1.1504
# Merge bk://cifs.bkbits.net/linux-2.5cifs
# into home.osdl.org:/home/torvalds/v2.5/linux
# --------------------------------------------
# 03/07/17	jasper@vs19.net	1.1505
# [PATCH] Fix up unattended nfs3/krb5 mounts
# 
# The patch from Frank was missing the auth flavor argument to
# nfs_sb_init().  Trivial fix follows.
# 
# [ Side note: the code mixes the spellings 'flavor' and 'flavour', which
#   is somewhat confusing.  That should probably be fixed to avoid confusion. ]
# --------------------------------------------
# 03/07/17	stern@rowland.harvard.edu	1.1455.1.40
# [PATCH] USB: Handle over current inputs on all Intel controllers
# 
# This patch for the UHCI driver changes the test for over current inputs,
# which can cause false Resume indications with some of Intel's USB
# controllers.  Previously the code only checked for one specific controller
# chip, but now another one has turned up that exhibits the same flaw.  It
# seems best just to check for Intel being the manufacturer, especially
# since it doesn't hurt to check for the condition when it isn't present or
# is only temporary.
# --------------------------------------------
# 03/07/17	henning@meier-geinitz.de	1.1455.1.41
# [PATCH] USB: unlink interrupt URBs in scanner driver
# 
# Clean up irq urb when not enough memory is available.
# --------------------------------------------
# 03/07/17	oliver@neukum.org	1.1455.1.42
# [PATCH] USB: fix race between probe and open in dabusb
# 
# the driver is registering the device too early, so that open may
# see a partially initialised device.
# --------------------------------------------
# 03/07/17	david-b@pacbell.net	1.1455.1.43
# [PATCH] USB: better locking in hcd_endpoint_disable()
# 
# You'll recall there was a change to the locking in that code after
# it was submitted.  This is a better fix to that issue.
# 
# "Obviously correct", though I've not run with this in ages.
# --------------------------------------------
# 03/07/17	greg@kroah.com	1.1506
# Merge kroah.com:/home/greg/linux/BK/bleed-2.5
# into kroah.com:/home/greg/linux/BK/gregkh-2.5
# --------------------------------------------
# 03/07/18	jejb@jet.(none)	1.1507
# Merge jet.(none):/home1/jejb/BK/scsi-misc-2.5
# into jet.(none):/home1/jejb/BK/scsi-for-linus-2.5
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.1
# [PATCH] Allow LBD on architectures that support it
# 
# From: Milton Miller <miltonm@bga.com>
# 
# Enable the CONFIG_LBD option for the architectures which appear to support
# it.
# 
# It is not actually tested for those architectures, but it's not likely to
# be unless we do this...
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.2
# [PATCH] misc fixes
# 
# - i460-agp linkage fix ("Luck, Tony" <tony.luck@intel.com>)
# 
# - Don't reimplement offsetof() in hfs
# 
# - NBD warning fix
# 
# - Remove unneeded null-pointer test in journal_stop (Andreas Gruenbacher)
# 
# - remove debug stuff in journal_dirty_metadata()
# 
# - slab.c typo fixes (Lev Makhlis <mlev@despammed.com>)
# 
# - In devfs_mk_cdev() error path, don't print `buf' until we've written
#   something into it.  (Reported by Gergely Nagy <algernon@gandalph.mad.hu>)
# 
# - Two ISA sound drivers had their kmalloc() args reversed (Spotted by Steve
#   French)
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.3
# [PATCH] parport_pc.c compile warning
# 
# From: Shane Shrybman <shrybman@sympatico.ca>
# 
# This fixes the following warning:
# 
# drivers/parport/parport_pc.c:98: warning: `verbose_probing' defined but
# not used
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.4
# [PATCH] ext3 extended attribute fixes
# 
# From: Andreas Gruenbacher <agruen@suse.de>
# 
# - Fix transaction credit exhaustion BUG.
# 
# - ext3_journal_get_write_access_credits failures break out of the loop in
#   1058, so <ce> is not released properly.
# 
# - <credits> must be reset after journal_release_buffer() in line 1072.
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.5
# [PATCH] Ext3 xattr credits fix for quotas
# 
# From: Andreas Gruenbacher <agruen@suse.de>
# 
# The xattr and acl code are not properly reserving credits for quotas.
# EXT3_DATA_TRANS_BLOCKS is an overestimate of the credits required including
# quotas.  Make it a little more tight, and use it in the xattr and acl code
# to be quota safe.
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.6
# [PATCH] ioctl(BLKBSZSET) fix and cleanup
# 
# From: Lou Langholtz <ldl@aros.net>
# 
# - set_blocksize() already does those size checks.
# 
# - test the set_blocksize() return value: it can fail if the requested
#   blocksize is less that the hard sector size.
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.7
# [PATCH] pass regs into dump_fpu() in elf coredump
# 
# From: Pete Zaitcev <zaitcev@redhat.com>
# 
# sparc32 needs the registers passed into dump_fpu().
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.8
# [PATCH] is_devfsd_or_child() deadlock fix
# 
# From: Andrey Borzenkov <arvidjaar@mail.ru>
# 
# The code that did proper check existed in 2.4 and was removed in 2.5 for
# whatever reason. The patch restores it slightly modified as below.
# 
# 2.4 code looks somewhat unclean in that
# 
# - it traverses task list without lock.
# 
# - it starts from current->real_parent but nothing prevents current be
#   init_task itself.  This hung for me on 2.5 during boot.  May be 2.4 does
#   something differently.
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.9
# [PATCH] remove task_cache entirely
# 
# From: Manfred Spraul <manfred@colorfullife.com>
# 
# kernel/fork.c contains a disabled cache for task stuctures.  task
# structures are placed into the task cache only if "tsk==current", and
# "tsk==current" is impossible.  There is even a WARN_ON against that in
# __put_task_struct().
# 
# So remove it entirely - it's dead code.
# 
# One problem is that order-1 allocations are not cached per-cpu - we can
# use kmalloc for the stack.
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.10
# [PATCH] use kmalloc for ia32 stacks
# 
# From: William Lee Irwin III <wli@holomorphy.com>
# 
# I've been slab allocating the stack on i386 for some time, and it has gone
# without incident in pgcl, -wli, -mjb (?), and so on.  kmalloc() is fine;
# there isn't any particularly compelling reason for a dedicated slab as
# there's no preconstruction to do, though it can be arranged.
# 
# Basically, it works, there's no obvious reason not to, and (even better)
# it's not totally invisible to the VM and even makes overhead reportable.
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.11
# [PATCH] fix removable partitioned media with devfs
# 
# From: Andrey Borzenkov <arvidjaar@mail.ru>
# 
# Current 2.5 does not register any device node in devfs for empty media
# (capacity == 0) case.  This makes removables unusable with devfs.
# Partition rescan is done only on bdev open, but without any device node for
# device it is impossible to open it.
# 
# In 2.4 it was finally solved by always registering .../disc node as
# representation for "whole" disk and using devfsd action to force partition
# rescan on access to (non-existing) partition name.  For primary names it
# was handled internally by devfs - it kept track of removable devices in
# directory and initiated partition rescan when name was not found.
# 
# Both are obviously broken now.  You can't do partition rescan because no
# node is registered at all and internal handling was removed.  Very nice.
# 
# The attached patch makes resgister_disk always register at least disc node.
#  This now works for old and new compat names as per devfsd configuration;
# canonical names are still broken:
# 
#   {pts/3}% ll /dev/scsi/host1/bus0/target4/lun0/part4
#   ls: /dev/scsi/host1/bus0/target4/lun0/part4: No such file or directory
# 
# but it can be fixed using the same technique as above so I won't push it.
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.12
# [PATCH] fix return of compat_sys_sched_getaffinity
# 
# From: Anton Blanchard <anton@samba.org>
# 
# On success getaffinity should return the size of mask.  It looks like
# Randy's patch (which fixed a bogus return) missed this bit.
# 
# In reality I'm not sure if we care, and with cpu bitmasks this stuff is
# going to break.
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.13
# [PATCH] Fix two bugs with process limits (RLIMIT_NPROC)
# 
# From: Neil Brown <neilb@cse.unsw.edu.au>
# 
# 1/ If a setuid process swaps it's real and effective uids and then forks,
#  the fork fails if the new realuid has more processes
#  than the original process was limited to.
#  This is particularly a problem if a user with a process limit
#  (e.g. 256) runs a setuid-root program which does setuid() + fork()
#  (e.g. lprng) while root already has more than 256 process (which
#  is quite possible).
# 
#  The root problem here is that a limit which should be a per-user
#  limit is being implemented as a per-process limit with
#  per-process (e.g. CAP_SYS_RESOURCE) controls.
#  Being a per-user limit, it should be that the root-user can over-ride
#  it, not just some process with CAP_SYS_RESOURCE.
# 
#  This patch adds a test to ignore process limits if the real user is root.
# 
# 2/ When a root-owned process (e.g. cgiwrap) sets up process limits and then
#   calls setuid, the setuid should fail if the user would then be running
#   more than rlim_cur[RLIMIT_NPROC] processes, but it doesn't.  This patch
#   adds an appropriate test.  With this patch, and per-user process limit
#   imposed in cgiwrap really works.
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.14
# [PATCH] unline most of put_namespace()
# 
# It has five callsites, and is big.
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.15
# [PATCH] CONFIG_BLK_DEV_CRYPTOLOOP needs CONFIG_CRYPTO
# 
# From: Brett <generica@email.com>
# 
# CONFIG_BLK_DEV_CRYPTOLOOP needs CONFIG_CRYPTO
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.16
# [PATCH] slab: print stuff when the wrong cache is used
# 
# From: Manfred Spraul <manfred@colorfullife.com>
# 
# Some extra diagnostics when someone passes the wrong object type
# into kmem_cache_free().  To help some bug which Manfred is chasing.
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.17
# [PATCH] settimeofday() fixes
# 
# From: davem
# 
# - sys_stime() takes an int*, but it should be a time_t*: they have different
#   sizes on (for example) sparc64.
# 
# - sys_settimeofday() is confusing timevals with timespecs.  They have
#   different sizes on sparc64 and the time keeps on getting set to epoch.
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.18
# [PATCH] visws: fix PCI breakage
# 
# From: Andrey Panin <pazke@donpac.ru>
# 
# This fixes Visws PCI code which was broken since 2.5.73.
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.19
# [PATCH] vesafb fix
# 
# From: Gerd Knorr <kraxel@suse.de>
# 
# The patch below fixes some vesafb issues.  Changes:
# 
# * fixed struct screen_info in tty.h to use portable types.  "unsigned
#   long" for 32bit values doesn't work on hammer machines ...
# 
# * limited the framebuffer memory used by vesafb to 16 MB.  This avoids
#   that vesafb's ioremap() eats plenty of kernel address space for no real
#   benefit if the gfx card has very much memory (some have 128 MB or more,
#   ia32 has 128 MB address space for vmalloc and ioremap ...).
# 
# * mtrr is enabled by default.  That should improve the vesafb performance
#   a lot.  Also added a option to disable mtrr.
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.20
# [PATCH] watchdog: i810-tco support
# 
# From: Wim Van Sebroeck <wim@iguana.be>
# 
# Adds support for the 82801EB and 82801ER I/O Controller Hub's (ICH5 &
# ICH5R).  This will add watchdog support for the i865 and i875 motherboard
# chipsets.  It also removes some extra trailing spaces in the source files.
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.21
# [PATCH] CLONE_STOPPED
# 
# From: Ulrich Drepper <drepper@redhat.com>
# 
# CLONE_STOPPED: start a thread in a stopped state.  Required for NTPL.
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.22
# [PATCH] dm: 'wait for event' race
# 
# From: Joe Thornber <thornber@sistina.com>
# 
# There was a race associated with the 'wait for a significant event'
# functionality.
# 
# Basically userland could read the status table, then wait for another
# event, but the event it was waiting for could have occurred in the gap
# between reading and waiting.
# 
# To solve this we assign identifiers to events, in order to successfully
# wait for an event both userland and the kernel driver must be in agreement
# about what the last event identifier was.  If they don't agree the wait
# call will return immediately, allowing userland to re-read the status and
# see what it missed.
# 
# The new ioctl interface will use this properly.
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.23
# [PATCH] dm: v4 ioctl interface
# 
# From: Joe Thornber <thornber@sistina.com>
# 
# v4 of the ioctl interface.  Note there never was a v2 or a v3 except in an
# unofficial EVMS way.
# 
# This works correctly with the 64-bit dev_t patches in -mm kernels.
# 
# There is now a config option to allow the user to select v1 or v4, it
# defaults to v1.  dm-ioctl.[hc] just #includes dm-ioctl-v[14].[hc] depending
# on the config option.
# 
# If you want to use v4 you will have to update your tools
# (libdevmapper/lvm).  The latest tools at the time of writing are:
# 
# dmsetup + libdevmapper + replacement kernel patches for 2.4.20 & 2.4.21:
# 
#   ftp://ftp.sistina.com/pub/LVM2/device-mapper/device-mapper-testing-new-version4-interface.tgz
# 
# Updated LVM2 tools to work with the above:
# 
#   ftp://ftp.sistina.com/pub/LVM2/tools/LVM2.0-testing.tgz
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.24
# [PATCH] fix bootmem allocator on machines with holes in
# 
# From: Anton Blanchard <anton@samba.org>
# 
# If the memory we are trying to allocate is too large to fit in the current
# region, we should skip to the end.  We currently search the available
# bitmap, find the area is too small, increment the start by incr and try
# again.  This resulted in an apparent lockup on a 64GB machine that had a
# 3GB IO hole starting at 1GB (and the mem_map array would not fit in the
# first region).
# 
# Also use ALIGN macro instead of an open coded version.
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.25
# [PATCH] Update Documentation/magic-numbers.txt
# 
# From: <ffrederick@prov-liege.be>
# 
# Update Documentation/magic-numbers.txt
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.26
# [PATCH] fix as-iosched do_div()
# 
# For CONFIG_LBD=n case it was passing a u32 into do_div().
# --------------------------------------------
# 03/07/18	akpm@osdl.org	1.1506.1.27
# [PATCH] "Fix" AS i/o hang with aacraid driver
# 
# From: Mark Haverkamp <markh@osdl.org>
# 
# Mark says:
# 
#   "Daniel McNeil and I have been debugging a hang with the aacraid driver
#    using the as I/O scheduler."
# 
#    We found that scsi_request_fn would de-queue a request and later
#    re-queued it.  This left the as_data->nr_dispatched variable in an
#    inconsistent state (it was never being decremented back to zero).
# 
#    We added a call to elv_completed_request to clean up the state before
#    re-adding the request.  This has fixed our hang problem."
# 
# It affects other SCSI drivers, but less frequently.  We're assuming this is
# the cause of several "everything got stuck in D state" reports.
# 
# A very long design discussion has ensued.  We don't have a suitably tested fix
# ready so I think it is best to put Mark's one-liner in there for now, fix it
# for real when everyone gets back from OLS.
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.1
# [PATCH] alpha illegal->invalid
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.2
# [PATCH] mtrr printk levels
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.3
# [PATCH] mtrr fixes
# 
# Fix cyrix mtrr ((ZoltÃ¡n BÃ¶szÃ¶rmÃ©nyi)
# Back port 2.4 handling for the Intel bug
# Add printk levels
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.4
# [PATCH] fix visws pci (visws specific code)
# 
# (Andrey Panin)
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.5
# [PATCH] another batch of "invalid" not "illegal" fixes
# 
# (Steven Cole)
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.6
# [PATCH] POSIX doesnt guarantee head -2, only head -n 2
# 
# (and some build environments are set up to be poxixly correct)
# 
# (Teemu Tervo)
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.7
# [PATCH] head -n 2 for ppc64
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.8
# [PATCH] updated magic number tables
# 
# (Fabian Frederick)
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.9
# [PATCH] pnp layer seems to document wrong file name
# 
# (Jochen Hein)
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.10
# [PATCH] first cut ftape conversion
# 
# (Paulo Andre)
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.11
# [PATCH] clean up ip2 glue (not yet ported tho)
# 
# (Adriank Bunk)
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.12
# [PATCH] move watchdogs to __module_get now it exists
# 
# (Jan Dittmer)
# 
# Also add the 82801EB/ER 	(Wim Van Sebroeck)
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.13
# [PATCH] fix all the paths in ide Kconfig docs
# 
# (Helge Hafting)
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.14
# [PATCH] convert ewrk3 for new locking etc
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.15
# [PATCH] clarify AXNET kconfig as per 2.4
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.16
# [PATCH] use cpu_relax in seq8005
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.17
# [PATCH] re-enable seq8005
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.18
# [PATCH] forward port 2.4 Zoom video support
# 
# Also apply the right fix to the yenta hang problem
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.19
# [PATCH] make isapnp request its port properly
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.20
# [PATCH] function is long gone, kill prototype
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.21
# [PATCH] pas16 build fix
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.22
# [PATCH] fix qlogicfas build warning
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.23
# [PATCH] undefined shifts in qla1280
# 
# C doesn't define >> by 32 for 32bit systems, and on some gcc leaves
# you with the original value...
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.24
# [PATCH] sym53c8xxx wasnt updated to new irq code etc
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.25
# [PATCH] serial proc gives info on keycounts which can sometiems be abused
# 
# For 2.4.x we made the file r-------- but for 2.6 we can do a nicer job
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.26
# [PATCH] xjack pcmcia needs .. pcmcia
# 
# (Taral)
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.27
# [PATCH] restore console log level when jbd raises it
# 
# (Vita Samel)
# 
# maybe the set function should return the old value instead ?
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.28
# [PATCH] fix jffs2 build
# 
# (Jamie Hicks)
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.29
# [PATCH] fix a doc error and misleading printk
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.30
# [PATCH] remove a now false comment
# 
# (Frank Cusack)
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.31
# [PATCH] fix a copy_user return
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.32
# [PATCH] fix failed sethostname corrupting the data
# 
# (Stephan Maciej)
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.33
# [PATCH] correct author of ad1980 plugin
# 
# (Overzealous C&P of Red Hat license template 8))
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.34
# [PATCH] fix make rpm versioning
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.35
# [PATCH] fix ver_linux for 2.6
# 
# (Steven Cole)
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.36
# [PATCH] fix unused symbol in ad1889
# 
# (Francois Romieu)
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.37
# [PATCH] btaudio uses memset so should be strlcpy
# 
# (I've got a patch pending from someone to redo the lot using memset so
# its safe from padding suprises)
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.38
# [PATCH] illegal->invalid for dmasound
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.39
# [PATCH] emu10k further updates/bug fixes
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.40
# [PATCH] Add HAL2 driver
# 
# (Ladislav Michl)
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.41
# [PATCH] Add Harmony OSS driver
# 
# (Jean-Christoph Vaugeois, Matthieu Delahaye,Helge Deller, Alex deVries)
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.42
# [PATCH] Kahlua audio driver
# --------------------------------------------
# 03/07/18	alan@lxorguk.ukuu.org.uk	1.1455.12.43
# [PATCH] Makefile bits for audio resync
# --------------------------------------------
# 03/07/18	torvalds@home.osdl.org	1.1506.1.28
# Manual merge
# --------------------------------------------
# 03/07/18	miles@lsi.nec.co.jp	1.1506.1.29
# [PATCH] Rename `nb85e' to `v850e' on v850
# 
# The term `nb85e' is incorrect (caused by my confusion when starting the
# v850 port), so this renames all occurances to `v850e'.
# 
# Because this change renames some files too, it contains a number of
# whole-file add/removes.
# --------------------------------------------
# 03/07/18	miles@lsi.nec.co.jp	1.1506.1.30
# [PATCH] Refactor v850 UART driver
# 
# The v850 family contains several related-but-not-identical on-chip
# UARTs.  This patch factors out the common code and uses it to implement
# both types (only one was supported before).
# 
# Also, this patch changes the way the v850 UART is initialized, to use
# the same method as other linux serial drivers.
# 
# This patch renames the UART code to be `v850e_uart' rather than
# `nb85e_uart', as the former is more correct.  As this change renames
# some files too, the patch contains a number of whole-file add/removes.
# --------------------------------------------
# 03/07/18	miles@lsi.nec.co.jp	1.1506.1.31
# [PATCH] Cleanup v850 cache-flushing code a bit
# 
# (1) Add support for the V850E/ME2 processor
# 
# (2) Clean up the cache-flushing function naming a bit
# 
# (3) Similar to previous patches, rename everything from `nb85e' to `v850e'.
#     This patch renames some files, and so contains a number of whole-file
#     add/removes.
# --------------------------------------------
# 03/07/18	miles@lsi.nec.co.jp	1.1506.1.32
# [PATCH] Add another layer of indirection for irq numbering with v850 `gbus' irqs
# 
# This allows ports that support the v850 RTE-CB `GBUS' interrupts to use
# both them and processor-board-specific interrupts at the same time.
# --------------------------------------------
# 03/07/18	miles@lsi.nec.co.jp	1.1506.1.33
# [PATCH] Add v850 RTE-V850E/ME2-CB port
# 
# This adds a port to the V850E/ME2 processor, and the `SolutionGear mini'
# RTE-V850E/ME2-CB evaluation board.
# --------------------------------------------
# 03/07/18	miles@lsi.nec.co.jp	1.1506.1.34
# [PATCH] Add v850 `sim85e2s' port, and cleanup v850e2 code
# 
# This patch adds support for the `sim85e2s' simulation of the NA85E2S
# processor implementation.  As part of this, cache-flushing support for
# the common v850e2 cache implementation is added.
# 
# It also cleans up a bunch of code that was duplicated between different
# v850e2 processors.
# --------------------------------------------
# 03/07/18	miles@lsi.nec.co.jp	1.1506.1.35
# [PATCH] Update v850 config/makefile
# 
# This updates the v850 Kconfig and kernel/Makefile to reflect preceding
# changes.
# --------------------------------------------
# 03/07/18	miles@lsi.nec.co.jp	1.1506.1.36
# [PATCH] v850 miscellanea
# 
# Some updated copyright noticed and an unnecessary variable deleted.
# --------------------------------------------
# 03/07/18	miles@lsi.nec.co.jp	1.1506.1.37
# [PATCH] Rename config option CONFIG_V850E_MA1_HIGHRES_TIMER on v850
# 
# This feature is not actually MA1-specific, so get rid of the `MA1' in
# the name.
# --------------------------------------------
# 03/07/18	miles@lsi.nec.co.jp	1.1506.1.38
# [PATCH] Update AS85EP1 port on v850
# --------------------------------------------
# 03/07/18	miles@lsi.nec.co.jp	1.1506.1.39
# [PATCH] On v850, use a long jump to start_kernel
# 
# This allows the low-level start code to be located far away from the
# rest of the kernel, which is sometimes necessary.
# --------------------------------------------
# 03/07/18	jejb@jet.(none)	1.1508
# back out akpm's "fix" for AS
# --------------------------------------------
# 03/07/18	jejb@jet.(none)	1.1509
# Put the requeue hack back into as-iosched.c
# --------------------------------------------
# 03/07/18	torvalds@home.osdl.org	1.1510
# Merge bk://linux-scsi.bkbits.net/scsi-for-linus-2.6
# into home.osdl.org:/home/torvalds/v2.5/linux
# --------------------------------------------
# 03/07/18	romieu@fr.zoreil.com	1.1511
# [PATCH] Fix error path in kahlua driver
# 
# Memory leak fix: hw_config is allocated before the call to sb_dsp_detect.
# --------------------------------------------
# 03/07/18	romieu@fr.zoreil.com	1.1512
# [PATCH] Unchecked copy_to_user disturb harmony
# 
# Fix an assortment of unchecked copy_to_user().
# --------------------------------------------
# 03/07/18	romieu@fr.zoreil.com	1.1513
# [PATCH] add new sound drivers to Makefile/Kconfig
# 
# Adds kahlua, harmony and hal2 drivers to the build options.
# --------------------------------------------
# 03/07/18	torvalds@home.osdl.org	1.1514
# Fix vfat shortname character logic that had wrong signedness
# tests.
# 
# From Dennis Vshivkov: 
# 
#   "whenever I was trying to create a file using only national
#    characters for its name, it was always created with an
#    uppercased shortname (provided that the name was not too
#    long for 8.3, of course). Everything was fine with latin
#    filenames, though."
# 
# The bug is that we check "buf[0]" as an unsigned character, but
# "buf" is just "char *", which (depending on architecture and
# compiler options) tends to be signed.
# --------------------------------------------
# 03/07/18	rusty@rustcorp.com.au	1.1515
# [PATCH] Allow struct members inside percpu macros
# 
# The current percpu macros do not allow __get_cpu_var(foo.val1)
# which makes building macros on top of them really difficult.  The
# reason for this is the __per_cpu postfix appended to per-cpu
# variables, designed to catch direct uses.  Prepend it instead.
# --------------------------------------------
# 03/07/18	rusty@rustcorp.com.au	1.1516
# [PATCH] Centralize Linker Symbols
# 
# Richard Henderson point out a while back that linker generated symbols
# should be declared as: "char _text[]" so that the compiler can't make
# assumptions about them sitting in small sections, etc.
# 
# Centralize these defintions in asm/sections.h (where some already
# are on x86).
# --------------------------------------------
# 03/07/18	rusty@rustcorp.com.au	1.1517
# [PATCH] introduce "local_t" - cpu-local atomic variables
# 
# Introduces local_t, a type which is like atomic_t, but the
# operations are only atomic from a single CPU's point of view
# (ie. atomic against interrupts and softirqs). Some architectures
# (eg. i386) can implement these very efficiently.
# 
# There are special operations for the case of a local operation on a
# per-cpu variable (which is common), which some architectures can
# implement efficiently (eg. IA64 keeps all per-cpu variables mapped
# at the same address, so no address arithmetic is needed).
# 
# The generic implementation given here simply uses atomics on 32-bit
# archs, three variables on others.  x86 is already implemented specially.
# --------------------------------------------
# 03/07/18	rusty@rustcorp.com.au	1.1518
# [PATCH] Resolve module local_t conflict
# 
# Uses local_t for module reference counts.
# --------------------------------------------
# 03/07/18	rusty@rustcorp.com.au	1.1519
# [PATCH] Sparc64 local_t support
# 
# These are the local_t bits for sparc64.
# 
# Other platforms such as PPC64 and Alpha (and in fact any "load locked/
# store conditional" like platform other than IA64), probably want to do
# something similar.
# --------------------------------------------
# 03/07/18	rusty@rustcorp.com.au	1.1520
# [PATCH] Make rmmod -f taint kernel.
# 
# Somehow, the code which taints the kernel when rmmod -f is used got
# lost.  Restore it.
# --------------------------------------------
# 03/07/18	rusty@rustcorp.com.au	1.1521
# [PATCH] module_put_and_exit
# 
# Author: Neil Brown
# 
# Define module_put_and_exit() and use it for nfsd/lockd
# 
# Both nfsd and lockd have threads which expect to hold a reference
# to the module while the thread is running.  In order for the thread
# to be able to put_module() the module before exiting, the
# put_module code must be call from outside the module.
# 
# This patch provides module_put_and_exit in non-modular code which a
# thread-in-a-module can call.  It also gets nfsd and lockd to use it
# as appropriate.
# 
# Note that in lockd, we can __get_module in the thread itself as the
# creator of the thread is waiting for the thread to startup.
# 
# In nfsd and for the 'reclaimer' threaded started by locked, we
# __get_module first and put_module if the thread failed to start.
# --------------------------------------------
# 03/07/18	rusty@rustcorp.com.au	1.1522
# [PATCH] Delete init/cleanup_module prototypes in obscure places.
# 
# A few places pre-declare "int module_init(void);" and "void
# module_cleanup(void);".  Other than being obsolete, this is
# unneccessary (it's in init.h anyway).
# 
# There are still about 100 places which still use the
# obsolete-since-2.2 "a function named module_init() magically gets
# called": this change frees us up implement that via a macro.
# --------------------------------------------
# 03/07/18	rusty@rustcorp.com.au	1.1523
# [PATCH] Make percpu_modcopy a macro
# 
# davidm@hpl.hp.com writes:
#   "I'm working on updating the ia64 tree with local_t etc.  One
#    thing that would really help me: could you make
#    asm-generic/percpu_modcopy() a macro?  The routine depends on
#    cpu_possible(), but I can't including smp.h in percpu.h since
#    that would lead to recusive header-file dependencies (and in my
#    opinion, percpu.h should be more "primitive" than smp.h, so that
#    it can be included virtually everywhere)."
# --------------------------------------------
# 03/07/18	hch@infradead.org	1.1524
# [PATCH] Use before initialisation in devfs_mk_cdev()
# 
# As noted by Gergely Nagy:
# 
#   "devfs_mk_cdev() first checks the mode passed to it, and if it thinks
#    it is not a char device, it prints a warning and aborts.  Now, this
#    printing involves the local variable `buf' (char buf[64]), which is
#    not initialised at that point."
# 
# The same problem also affects devfs_mk_bdev.
# 
# Fixed thus.
# --------------------------------------------
# 03/07/19	rddunlap@osdl.org	1.1525
# [PATCH] janitor: drivers/telephony/ixj
# 
# From: Daniele Bellucci <bellucda@tiscali.it>
# 
# This is an audit (copy_*_user), cleanup, and coding-style fix
# for this driver.
# --------------------------------------------
# 03/07/19	randy.dunlap@verizon.net	1.1526
# [PATCH] janitor: audit misc_register in wdt977
# 
# From: Daniele Bellucci <bellucda@tiscali.it>
# 
# Add a check to misc_register() in the wdt977 driver.
# --------------------------------------------
# 03/07/19	randy.dunlap@verizon.net	1.1527
# [PATCH] janitor: copy_to_user in media/video/pms
# 
# From: Daniele Bellucci <bellucda@tiscali.it>
# 
# Add a status check to copy_to_user() in a media/video driver.
# --------------------------------------------
# 03/07/19	randy.dunlap@verizon.net	1.1528
# [PATCH] janitor: copy_to_user in net/irda/vlsi_ir
# 
# From:  Matthew Wilcox <willy@debian.org> and Daniele Bellucci <bellucda@tiscali.it>
# 
# Fix an unchecked copy_to_user() in net/irda/vlsi_ir.c.
# --------------------------------------------
# 03/07/19	rddunlap@osdl.org	1.1529
# [PATCH] janitor: copy_to_user in wireless/ray_cs ioctl
# 
# From: Daniele Bellucci <bellucda@tiscali.it>
# 
# Fix an unchecked copy_to_user in ray_cs ioctl.
# --------------------------------------------
# 03/07/19	rddunlap@osdl.org	1.1530
# [PATCH] janitor: unchecked copy/put_user in umsdos ioctl
# 
# author:  Daniele Bellucci <bellucda@tiscali.it>
# 
# Fix a series of unchecked copy/put_user()s in umsdos ioctl.
# --------------------------------------------
# 03/07/19	rddunlap@osdl.org	1.1531
# [PATCH] janitor: unchecked copy_to_user in drivers/sbus/char/envctrl
# 
# author: Daniele Bellucci <bellucda@tiscali.it>
# 
# Fix several unchecked copy_to_user()s in sbus/char/envctrl
# --------------------------------------------
# 03/07/19	rddunlap@osdl.org	1.1532
# [PATCH] janitor: unchecked copy_from_user in ieee1394/amdtp
# 
# author: Daniele Bellucci <bellucda@tiscali.it>
# 
# Fix an unchecked copy_from_user in ieee1394/amdtp.
# --------------------------------------------
# 03/07/19	rddunlap@osdl.org	1.1533
# [PATCH] janitor: unchecked copy_from_user in parisc/led.c
# 
# author: Daniele Bellucci <bellucda@tiscali.it>
# --------------------------------------------
# 03/07/19	rddunlap@osdl.org	1.1534
# [PATCH] janitor: mem leak and copy_from_user in wan/comx driver
# 
# author: Daniele Bellucci <bellucda@tiscali.it>
# 
# Fix a memory leak and checks a copy_from_user in wan/comx driver.
# --------------------------------------------
#
diff -Nru a/Documentation/magic-number.txt b/Documentation/magic-number.txt
--- a/Documentation/magic-number.txt	Sat Jul 19 12:54:25 2003
+++ b/Documentation/magic-number.txt	Sat Jul 19 12:54:25 2003
@@ -51,6 +51,13 @@
 					<pasky@ucw.cz>
 					03 Nov 2002
 
+Updated the magic table to Linux 2.5.74.
+
+					Fabian Frederick
+					<ffrederick@users.sourceforge.net>
+					09 Jul 2003
+
+
 Magic Name            Number      Structure            File
 ===========================================================================
 PG_MAGIC              'P'         pg_{read,write}_hdr include/linux/pg.h
@@ -62,10 +69,12 @@
 HDLC_MAGIC            0x239e      n_hdlc            drivers/char/n_hdlc.c
 APM_BIOS_MAGIC        0x4101      apm_user          arch/i386/kernel/apm.c
 CYCLADES_MAGIC        0x4359      cyclades_port     include/linux/cyclades.h
+DB_MAGIC              0x4442      fc_info           drivers/net/iph5526_novram.c
+DL_MAGIC              0x444d      fc_info           drivers/net/iph5526_novram.c
 FASYNC_MAGIC          0x4601      fasync_struct     include/linux/fs.h
+FF_MAGIC              0x4646      fc_info           drivers/net/iph5526_novram.c
 ISICOM_MAGIC          0x4d54      isi_port          include/linux/isicom.h
-PTY_MAGIC             0x5001      (none at the moment)
-                                                    drivers/char/pty.c
+PTY_MAGIC             0x5001                        drivers/char/pty.c
 PPP_MAGIC             0x5002      ppp               include/linux/if_pppvar.h
 SERIAL_MAGIC          0x5301      async_struct      include/linux/serial.h
 SSTATE_MAGIC          0x5302      serial_state      include/linux/serial.h
@@ -81,9 +90,9 @@
 MGSLPC_MAGIC          0x5402      mgslpc_info       drivers/char/pcmcia/synclink_cs.c
 TTY_LDISC_MAGIC       0x5403      tty_ldisc         include/linux/tty_ldisc.h
 USB_SERIAL_MAGIC      0x6702      usb_serial        drivers/usb/serial/usb-serial.h
+FULL_DUPLEX_MAGIC     0x6969                        drivers/net/tulip/de2104x.c
 USB_BLUETOOTH_MAGIC   0x6d02      usb_bluetooth     drivers/usb/class/bluetty.c
-RFCOMM_TTY_MAGIC      0x6d02      (note at the moment)
-                                                    net/bluetooth/rfcomm/tty.c
+RFCOMM_TTY_MAGIC      0x6d02                        net/bluetooth/rfcomm/tty.c
 USB_SERIAL_PORT_MAGIC 0x7301      usb_serial_port   drivers/usb/serial/usb-serial.h
 CG_MAGIC              0x00090255  ufs_cylinder_group include/linux/ufs_fs.h
 A2232_MAGIC           0x000a2232  gs_port           drivers/char/ser_a2232.h
@@ -91,6 +100,7 @@
 RPORT_MAGIC           0x00525001  r_port            drivers/char/rocket_int.h
 LSEMAGIC              0x05091998  lse               drivers/fc4/fc.c
 GDTIOCTL_MAGIC        0x06030f07  gdth_iowr_str     drivers/scsi/gdth_ioctl.h
+RIEBL_MAGIC           0x09051990                    drivers/net/atarilance.c
 RIO_MAGIC             0x12345678  gs_port           drivers/char/rio/rio_linux.c
 SX_MAGIC              0x12345678  gs_port           drivers/char/sx.h
 NBD_REQUEST_MAGIC     0x12560953  nbd_request       include/linux/nbd.h
@@ -120,6 +130,7 @@
 GDA_MAGIC             0x58464552  gda               include/asm-mips64/sn/gda.h
 RED_MAGIC1            0x5a2cf071  (any)             mm/slab.c
 STL_PORTMAGIC         0x5a7182c9  stlport           include/linux/stallion.h
+EEPROM_MAGIC_VALUE    0X5ab478d2  lanai_dev         drivers/atm/lanai.c
 HDLCDRV_MAGIC         0x5ac6e778  hdlcdrv_state     include/linux/hdlcdrv.h
 EPCA_MAGIC            0x5c6df104  channel           include/linux/epca.h
 PCXX_MAGIC            0x5c6df104  channel           drivers/char/pcxx.h
@@ -127,9 +138,11 @@
 I810_STATE_MAGIC      0x63657373  i810_state        sound/oss/i810_audio.c
 TRIDENT_STATE_MAGIC   0x63657373  trient_state      sound/oss/trident.c
 M3_CARD_MAGIC         0x646e6f50  m3_card           sound/oss/maestro3.c
+FW_HEADER_MAGIC       0x65726F66  fw_header         drivers/atm/fore200e.h
 SLOT_MAGIC            0x67267321  slot              drivers/hotplug/cpqphp.h
 SLOT_MAGIC            0x67267322  slot              drivers/hotplug/acpiphp.h
 LO_MAGIC              0x68797548  nbd_device        include/linux/nbd.h
+OPROFILE_MAGIC        0x6f70726f  super_block       drivers/oprofile/oprofilefs.h
 M3_STATE_MAGIC        0x734d724d  m3_state          sound/oss/maestro3.c
 STL_PANELMAGIC        0x7ef621a1  stlpanel          include/linux/stallion.h
 VMALLOC_MAGIC         0x87654320  snd_alloc_track   sound/core/memory.c
@@ -137,11 +150,15 @@
 PWC_MAGIC             0x89DC10AB  pwc_device        drivers/usb/media/pwc.h
 NBD_REPLY_MAGIC       0x96744668  nbd_reply         include/linux/nbd.h
 STL_BOARDMAGIC        0xa2267f52  stlbrd            include/linux/stallion.h
+ENI155_MAGIC          0xa54b872d  midway_eprom	    drivers/atm/eni.h
 SCI_MAGIC             0xbabeface  gs_port           drivers/char/sh-sci.h
 CODA_MAGIC            0xC0DAC0DA  coda_file_info    include/linux/coda_fs_i.h
+DPMEM_MAGIC           0xc0ffee11  gdt_pci_sram      drivers/scsi/gdth.h
 STLI_PORTMAGIC        0xe671c7a1  stliport          include/linux/istallion.h
 YAM_MAGIC             0xF10A7654  yam_port          drivers/net/hamradio/yam.c
 CCB_MAGIC             0xf2691ad2  ccb               drivers/scsi/ncr53c8xx.c
+QUEUE_MAGIC_FREE      0xf7e1c9a3  queue_entry       drivers/scsi/arm/queue.c
+QUEUE_MAGIC_USED      0xf7e1cc33  queue_entry       drivers/scsi/arm/queue.c
 HTB_CMAGIC            0xFEFAFEF1  htb_class         net/sched/sch_htb.c
 NMI_MAGIC             0x48414d4d455201 nmi_s        include/asm-mips64/sn/nmi.h
 
diff -Nru a/Documentation/pnp.txt b/Documentation/pnp.txt
--- a/Documentation/pnp.txt	Sat Jul 19 12:54:23 2003
+++ b/Documentation/pnp.txt	Sat Jul 19 12:54:23 2003
@@ -22,7 +22,7 @@
 In addition to the standard driverfs file the following are created in each 
 device's directory:
 id - displays a list of support EISA IDs
-possible - displays possible resource configurations
+options - displays possible resource configurations
 resources - displays currently allocated resources and allows resource changes
 
 -activating a device
@@ -60,7 +60,7 @@
 - Notice the string "DISABLED".  THis means the device is not active.
 
 3.) check the device's possible configurations (optional)
-# cat possible
+# cat options
 Dependent: 01 - Priority acceptable
     port 0x3f0-0x3f0, align 0x7, size 0x6, 16-bit address decoding
     port 0x3f7-0x3f7, align 0x0, size 0x1, 16-bit address decoding
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	Sat Jul 19 12:54:25 2003
+++ b/MAINTAINERS	Sat Jul 19 12:54:25 2003
@@ -973,7 +973,7 @@
 S:	Supported
 
 INTERMEZZO FILE SYSTEM
-P:	Chen Yang
+P:	Cluster File Systems	
 M:	intermezzo-devel@lists.sf.net
 W:	http://www.inter-mezzo.org/
 L:	intermezzo-discuss@lists.sourceforge.net
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Sat Jul 19 12:54:26 2003
+++ b/Makefile	Sat Jul 19 12:54:26 2003
@@ -781,7 +781,8 @@
 	tar -cvz $(RCS_TAR_IGNORE) -f $(KERNELPATH).tar.gz $(KERNELPATH)/. ; \
 	rm $(KERNELPATH) ; \
 	cd $(TOPDIR) ; \
-	$(CONFIG_SHELL) $(srctree)/scripts/mkversion > .version ; \
+	$(CONFIG_SHELL) $(srctree)/scripts/mkversion > .tmp_version ; \
+	mv -f .tmp_version .version; \
 	$(RPM) -ta $(TOPDIR)/../$(KERNELPATH).tar.gz ; \
 	rm $(TOPDIR)/../$(KERNELPATH).tar.gz
 
diff -Nru a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
--- a/arch/alpha/kernel/irq.c	Sat Jul 19 12:54:26 2003
+++ b/arch/alpha/kernel/irq.c	Sat Jul 19 12:54:26 2003
@@ -601,7 +601,7 @@
 	if ((unsigned) irq > ACTUAL_NR_IRQS && illegal_count < MAX_ILLEGAL_IRQS ) {
 		irq_err_count++;
 		illegal_count++;
-		printk(KERN_CRIT "device_interrupt: illegal interrupt %d\n",
+		printk(KERN_CRIT "device_interrupt: invalid interrupt %d\n",
 		       irq);
 		return;
 	}
diff -Nru a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
--- a/arch/alpha/mm/init.c	Sat Jul 19 12:54:28 2003
+++ b/arch/alpha/mm/init.c	Sat Jul 19 12:54:28 2003
@@ -20,9 +20,6 @@
 #include <linux/init.h>
 #include <linux/bootmem.h> /* max_low_pfn */
 #include <linux/vmalloc.h>
-#ifdef CONFIG_BLK_DEV_INITRD
-#include <linux/blk.h>
-#endif
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
diff -Nru a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c
--- a/arch/arm/mach-clps711x/autcpu12.c	Sat Jul 19 12:54:24 2003
+++ b/arch/arm/mach-clps711x/autcpu12.c	Sat Jul 19 12:54:24 2003
@@ -21,7 +21,6 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/blk.h>
 #include <linux/mm.h>
 
 #include <asm/hardware.h>
diff -Nru a/arch/arm26/kernel/setup.c b/arch/arm26/kernel/setup.c
--- a/arch/arm26/kernel/setup.c	Sat Jul 19 12:54:23 2003
+++ b/arch/arm26/kernel/setup.c	Sat Jul 19 12:54:23 2003
@@ -14,7 +14,7 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/utsname.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/console.h>
 #include <linux/bootmem.h>
 #include <linux/seq_file.h>
diff -Nru a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c
--- a/arch/arm26/mm/init.c	Sat Jul 19 12:54:29 2003
+++ b/arch/arm26/mm/init.c	Sat Jul 19 12:54:29 2003
@@ -22,7 +22,7 @@
 #include <linux/init.h>
 #include <linux/initrd.h>
 #include <linux/bootmem.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 
 #include <asm/segment.h>
 #include <asm/mach-types.h>
diff -Nru a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c
--- a/arch/h8300/kernel/setup.c	Sat Jul 19 12:54:23 2003
+++ b/arch/h8300/kernel/setup.c	Sat Jul 19 12:54:23 2003
@@ -35,7 +35,6 @@
 #include <asm/irq.h>
 
 #ifdef CONFIG_BLK_DEV_INITRD
-#include <linux/blk.h>
 #include <asm/pgtable.h>
 #endif
 
diff -Nru a/arch/h8300/mm/init.c b/arch/h8300/mm/init.c
--- a/arch/h8300/mm/init.c	Sat Jul 19 12:54:25 2003
+++ b/arch/h8300/mm/init.c	Sat Jul 19 12:54:25 2003
@@ -23,9 +23,6 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/types.h>
-#ifdef CONFIG_BLK_DEV_RAM
-#include <linux/blk.h>
-#endif
 #include <linux/ptrace.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
diff -Nru a/arch/i386/kernel/cpu/mtrr/cyrix.c b/arch/i386/kernel/cpu/mtrr/cyrix.c
--- a/arch/i386/kernel/cpu/mtrr/cyrix.c	Sat Jul 19 12:54:25 2003
+++ b/arch/i386/kernel/cpu/mtrr/cyrix.c	Sat Jul 19 12:54:25 2003
@@ -330,16 +330,16 @@
 	set_mtrr_done(&ctxt);	/* flush cache and disable MAPEN */
 
 	if (ccrc[5])
-		printk("mtrr: ARR usage was not enabled, enabled manually\n");
+		printk(KERN_INFO "mtrr: ARR usage was not enabled, enabled manually\n");
 	if (ccrc[3])
-		printk("mtrr: ARR3 cannot be changed\n");
+		printk(KERN_INFO "mtrr: ARR3 cannot be changed\n");
 /*
     if ( ccrc[1] & 0x80) printk ("mtrr: SMM memory access through ARR3 disabled\n");
     if ( ccrc[1] & 0x04) printk ("mtrr: SMM memory access disabled\n");
     if ( ccrc[1] & 0x02) printk ("mtrr: SMM mode disabled\n");
 */
 	if (ccrc[6])
-		printk("mtrr: ARR3 was write protected, unprotected\n");
+		printk(KERN_INFO "mtrr: ARR3 was write protected, unprotected\n");
 }
 
 static struct mtrr_ops cyrix_mtrr_ops = {
diff -Nru a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c
--- a/arch/i386/kernel/cpu/mtrr/main.c	Sat Jul 19 12:54:22 2003
+++ b/arch/i386/kernel/cpu/mtrr/main.c	Sat Jul 19 12:54:22 2003
@@ -64,7 +64,7 @@
 static void set_mtrr(unsigned int reg, unsigned long base,
 		     unsigned long size, mtrr_type type);
 
-static unsigned int arr3_protected;
+extern int arr3_protected;
 
 void set_mtrr_ops(struct mtrr_ops * ops)
 {
@@ -75,23 +75,25 @@
 /*  Returns non-zero if we have the write-combining memory type  */
 static int have_wrcomb(void)
 {
-	struct pci_dev *dev = NULL;
-
-	/* WTF is this?
-	 * Someone, please shoot me.
-	 */
-
-	/* ServerWorks LE chipsets have problems with write-combining 
-	   Don't allow it and leave room for other chipsets to be tagged */
-
+	struct pci_dev *dev;
+	
 	if ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8, NULL)) != NULL) {
-		if ((dev->vendor == PCI_VENDOR_ID_SERVERWORKS) &&
-		    (dev->device == PCI_DEVICE_ID_SERVERWORKS_LE)) {
-			printk(KERN_INFO
-			       "mtrr: Serverworks LE detected. Write-combining disabled.\n");
+		/* ServerWorks LE chipsets have problems with write-combining 
+		   Don't allow it and leave room for other chipsets to be tagged */
+		if (dev->vendor == PCI_VENDOR_ID_SERVERWORKS &&
+		    dev->device == PCI_DEVICE_ID_SERVERWORKS_LE) {
+			printk(KERN_INFO "mtrr: Serverworks LE detected. Write-combining disabled.\n");
 			return 0;
 		}
-	}
+		/* Intel 450NX errata # 23. Non ascending cachline evictions to
+		   write combining memory may resulting in data corruption */
+		if (dev->vendor == PCI_VENDOR_ID_INTEL &&
+		    dev->device == PCI_DEVICE_ID_INTEL_82451NX)
+		{
+			printk(KERN_INFO "mtrr: Intel 450NX MMC detected. Write-combining disabled.\n");
+			return 0;
+		}
+	}		
 	return (mtrr_if->have_wrcomb ? mtrr_if->have_wrcomb() : 0);
 }
 
@@ -121,7 +123,7 @@
 	max = num_var_ranges;
 	if ((usage_table = kmalloc(max * sizeof *usage_table, GFP_KERNEL))
 	    == NULL) {
-		printk("mtrr: could not allocate\n");
+		printk(KERN_ERR "mtrr: could not allocate\n");
 		return;
 	}
 	for (i = 0; i < max; i++)
@@ -310,7 +312,7 @@
 		return error;
 
 	if (type >= MTRR_NUM_TYPES) {
-		printk("mtrr: type: %u illegal\n", type);
+		printk(KERN_WARNING "mtrr: type: %u invalid\n", type);
 		return -EINVAL;
 	}
 
@@ -322,7 +324,7 @@
 	}
 
 	if (base & size_or_mask || size & size_or_mask) {
-		printk("mtrr: base or size exceeds the MTRR width\n");
+		printk(KERN_WARNING "mtrr: base or size exceeds the MTRR width\n");
 		return -EINVAL;
 	}
 
@@ -348,7 +350,7 @@
 		if (ltype != type) {
 			if (type == MTRR_TYPE_UNCACHABLE)
 				continue;
-			printk ("mtrr: type mismatch for %lx000,%lx000 old: %s new: %s\n",
+			printk (KERN_WARNING "mtrr: type mismatch for %lx000,%lx000 old: %s new: %s\n",
 			     base, size, attrib_to_str(ltype),
 			     attrib_to_str(type));
 			goto out;
@@ -364,7 +366,7 @@
 		set_mtrr(i, base, size, type);
 		usage_table[i] = 1;
 	} else
-		printk("mtrr: no more MTRRs available\n");
+		printk(KERN_INFO "mtrr: no more MTRRs available\n");
 	error = i;
  out:
 	up(&main_lock);
@@ -412,8 +414,8 @@
 	 char increment)
 {
 	if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
-		printk("mtrr: size and base must be multiples of 4 kiB\n");
-		printk("mtrr: size: 0x%lx  base: 0x%lx\n", size, base);
+		printk(KERN_WARNING "mtrr: size and base must be multiples of 4 kiB\n");
+		printk(KERN_DEBUG "mtrr: size: 0x%lx  base: 0x%lx\n", size, base);
 		return -EINVAL;
 	}
 	return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type,
@@ -458,28 +460,28 @@
 			}
 		}
 		if (reg < 0) {
-			printk("mtrr: no MTRR for %lx000,%lx000 found\n", base,
+			printk(KERN_DEBUG "mtrr: no MTRR for %lx000,%lx000 found\n", base,
 			       size);
 			goto out;
 		}
 	}
 	if (reg >= max) {
-		printk("mtrr: register: %d too big\n", reg);
+		printk(KERN_WARNING "mtrr: register: %d too big\n", reg);
 		goto out;
 	}
 	if (is_cpu(CYRIX) && !use_intel()) {
 		if ((reg == 3) && arr3_protected) {
-			printk("mtrr: ARR3 cannot be changed\n");
+			printk(KERN_WARNING "mtrr: ARR3 cannot be changed\n");
 			goto out;
 		}
 	}
 	mtrr_if->get(reg, &lbase, &lsize, &ltype);
 	if (lsize < 1) {
-		printk("mtrr: MTRR %d not used\n", reg);
+		printk(KERN_WARNING "mtrr: MTRR %d not used\n", reg);
 		goto out;
 	}
 	if (usage_table[reg] < 1) {
-		printk("mtrr: reg: %d has count=0\n", reg);
+		printk(KERN_WARNING "mtrr: reg: %d has count=0\n", reg);
 		goto out;
 	}
 	if (--usage_table[reg] < 1)
@@ -508,8 +510,8 @@
 mtrr_del(int reg, unsigned long base, unsigned long size)
 {
 	if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
-		printk("mtrr: size and base must be multiples of 4 kiB\n");
-		printk("mtrr: size: 0x%lx  base: 0x%lx\n", size, base);
+		printk(KERN_INFO "mtrr: size and base must be multiples of 4 kiB\n");
+		printk(KERN_DEBUG "mtrr: size: 0x%lx  base: 0x%lx\n", size, base);
 		return -EINVAL;
 	}
 	return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
@@ -677,7 +679,7 @@
 			break;
 		}
 	}
-	printk("mtrr: v%s\n",MTRR_VERSION);
+	printk(KERN_INFO "mtrr: v%s\n",MTRR_VERSION);
 
 	if (mtrr_if) {
 		set_num_var_ranges();
diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
--- a/arch/i386/kernel/io_apic.c	Sat Jul 19 12:54:24 2003
+++ b/arch/i386/kernel/io_apic.c	Sat Jul 19 12:54:24 2003
@@ -682,6 +682,21 @@
 
 #else /* !SMP */
 static inline void move_irq(int irq) { }
+
+void send_IPI_self(int vector)
+{
+	unsigned int cfg;
+
+	/*
+	 * Wait for idle.
+	 */
+	apic_wait_icr_idle();
+	cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL;
+	/*
+	 * Send the IPI. The write to APIC_ICR fires this off.
+	 */
+	apic_write_around(APIC_ICR, cfg);
+}
 #endif /* defined(CONFIG_SMP) */
 
 
diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
--- a/arch/i386/kernel/setup.c	Sat Jul 19 12:54:25 2003
+++ b/arch/i386/kernel/setup.c	Sat Jul 19 12:54:25 2003
@@ -42,6 +42,7 @@
 #include <asm/edd.h>
 #include <asm/setup.h>
 #include <asm/arch_hooks.h>
+#include <asm/sections.h>
 #include "setup_arch_pre.h"
 #include "mach_resources.h"
 
@@ -100,7 +101,7 @@
 extern void dmi_scan_machine(void);
 extern void generic_apic_probe(char *);
 extern int root_mountflags;
-extern char _text, _etext, _edata, _end;
+extern char _end[];
 
 unsigned long saved_videomode;
 
@@ -520,7 +521,7 @@
 			acpi_disabled = 1;
 
 		/* "acpismp=force" turns on ACPI again */
-		else if (!memcmp(from, "acpismp=force", 14))
+		if (c == ' ' && !memcmp(from, "acpismp=force", 13))
 			acpi_disabled = 0;
 
 		/*
@@ -676,7 +677,7 @@
 	 * partially used pages are not usable - thus
 	 * we are rounding upwards:
 	 */
-	start_pfn = PFN_UP(__pa(&_end));
+	start_pfn = PFN_UP(__pa(_end));
 
 	find_max_pfn();
 
@@ -947,15 +948,15 @@
 
 	if (!MOUNT_ROOT_RDONLY)
 		root_mountflags &= ~MS_RDONLY;
-	init_mm.start_code = (unsigned long) &_text;
-	init_mm.end_code = (unsigned long) &_etext;
-	init_mm.end_data = (unsigned long) &_edata;
-	init_mm.brk = (unsigned long) &_end;
-
-	code_resource.start = virt_to_phys(&_text);
-	code_resource.end = virt_to_phys(&_etext)-1;
-	data_resource.start = virt_to_phys(&_etext);
-	data_resource.end = virt_to_phys(&_edata)-1;
+	init_mm.start_code = (unsigned long) _text;
+	init_mm.end_code = (unsigned long) _etext;
+	init_mm.end_data = (unsigned long) _edata;
+	init_mm.brk = (unsigned long) _end;
+
+	code_resource.start = virt_to_phys(_text);
+	code_resource.end = virt_to_phys(_etext)-1;
+	data_resource.start = virt_to_phys(_etext);
+	data_resource.end = virt_to_phys(_edata)-1;
 
 	parse_cmdline_early(cmdline_p);
 
@@ -977,7 +978,7 @@
 	generic_apic_probe(*cmdline_p);
 #endif	
 
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
 	/*
 	 * Parse the ACPI tables for possible boot-time SMP configuration.
 	 */
diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c
--- a/arch/i386/mm/init.c	Sat Jul 19 12:54:26 2003
+++ b/arch/i386/mm/init.c	Sat Jul 19 12:54:26 2003
@@ -20,9 +20,6 @@
 #include <linux/swap.h>
 #include <linux/smp.h>
 #include <linux/init.h>
-#ifdef CONFIG_BLK_DEV_INITRD
-#include <linux/blk.h>
-#endif
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
 #include <linux/bootmem.h>
@@ -565,7 +562,7 @@
 		free_page(addr);
 		totalram_pages++;
 	}
-	printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
+	printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (__init_end - __init_begin) >> 10);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
diff -Nru a/arch/i386/pci/legacy.c b/arch/i386/pci/legacy.c
--- a/arch/i386/pci/legacy.c	Sat Jul 19 12:54:27 2003
+++ b/arch/i386/pci/legacy.c	Sat Jul 19 12:54:27 2003
@@ -24,7 +24,7 @@
 		for (devfn = 0; devfn < 256; devfn += 8) {
 			if (!raw_pci_ops->read(0, n, devfn, PCI_VENDOR_ID, 2, &l) &&
 			    l != 0x0000 && l != 0xffff) {
-				DBG("Found device at %02x:%02x [%04x]\n", n, dev->devfn, l);
+				DBG("Found device at %02x:%02x [%04x]\n", n, devfn, l);
 				printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
 				pci_scan_bus(n, &pci_root_ops, NULL);
 				break;
diff -Nru a/arch/i386/pci/visws.c b/arch/i386/pci/visws.c
--- a/arch/i386/pci/visws.c	Sat Jul 19 12:54:26 2003
+++ b/arch/i386/pci/visws.c	Sat Jul 19 12:54:26 2003
@@ -17,7 +17,7 @@
 
 int broken_hp_bios_irq9;
 
-extern struct pci_ops pci_direct_conf1;
+extern struct pci_raw_ops pci_direct_conf1;
 
 static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; }
 
@@ -101,8 +101,9 @@
 	printk(KERN_INFO "PCI: Lithium bridge A bus: %u, "
 		"bridge B (PIIX4) bus: %u\n", pci_bus1, pci_bus0);
 
-	pci_scan_bus(pci_bus0, &pci_direct_conf1, NULL);
-	pci_scan_bus(pci_bus1, &pci_direct_conf1, NULL);
+	raw_pci_ops = &pci_direct_conf1;
+	pci_scan_bus(pci_bus0, &pci_root_ops, NULL);
+	pci_scan_bus(pci_bus1, &pci_root_ops, NULL);
 	pci_fixup_irqs(visws_swizzle, visws_map_irq);
 	pcibios_resource_survey();
 	return 0;
diff -Nru a/arch/ia64/Makefile b/arch/ia64/Makefile
--- a/arch/ia64/Makefile	Sat Jul 19 12:54:21 2003
+++ b/arch/ia64/Makefile	Sat Jul 19 12:54:21 2003
@@ -66,8 +66,7 @@
 drivers-$(CONFIG_PCI)		+= arch/ia64/pci/
 drivers-$(CONFIG_IA64_HP_SIM)	+= arch/ia64/hp/sim/
 drivers-$(CONFIG_IA64_HP_ZX1)	+= arch/ia64/hp/common/ arch/ia64/hp/zx1/
-drivers-$(CONFIG_IA64_GENERIC)	+= arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ \
-				   arch/ia64/sn/
+drivers-$(CONFIG_IA64_GENERIC)	+= arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/
 
 boot := arch/ia64/boot
 
diff -Nru a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
--- a/arch/ia64/hp/sim/simscsi.c	Sat Jul 19 12:54:25 2003
+++ b/arch/ia64/hp/sim/simscsi.c	Sat Jul 19 12:54:25 2003
@@ -9,7 +9,7 @@
  * 99/12/18 David Mosberger	Added support for READ10/WRITE10 needed by linux v2.3.33
  */
 #include <linux/config.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
diff -Nru a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c
--- a/arch/ia64/ia32/ia32_ioctl.c	Sat Jul 19 12:54:26 2003
+++ b/arch/ia64/ia32/ia32_ioctl.c	Sat Jul 19 12:54:26 2003
@@ -52,7 +52,7 @@
 #include <linux/raw.h>
 #include <linux/smb_fs.h>
 #include <linux/blkpg.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/elevator.h>
 #include <linux/rtc.h>
 #include <linux/pci.h>
diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
--- a/arch/ia64/kernel/acpi.c	Sat Jul 19 12:54:25 2003
+++ b/arch/ia64/kernel/acpi.c	Sat Jul 19 12:54:25 2003
@@ -720,7 +720,7 @@
 {
 	int vector = 0;
 
-	if (acpi_madt->flags.pcat_compat && (gsi < 16))
+	if (has_8259 && (gsi < 16))
 		return isa_irq_to_vector(gsi);
 
 	if (!iosapic_register_intr)
diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
--- a/arch/ia64/kernel/entry.S	Sat Jul 19 12:54:24 2003
+++ b/arch/ia64/kernel/entry.S	Sat Jul 19 12:54:24 2003
@@ -61,7 +61,17 @@
 	mov out2=in2			// envp
 	add out3=16,sp			// regs
 	br.call.sptk.many rp=sys_execve
-.ret0:	cmp4.ge p6,p7=r8,r0
+.ret0:
+#ifdef CONFIG_IA32_SUPPORT
+	/*
+	 * Check if we're returning to ia32 mode. If so, we need to restore ia32 registers
+	 * from pt_regs.
+	 */
+	adds r16=PT(CR_IPSR)+16,sp
+	;;
+	ld8 r16=[r16]
+#endif
+	cmp4.ge p6,p7=r8,r0
 	mov ar.pfs=loc1			// restore ar.pfs
 	sxt4 r8=r8			// return 64-bit result
 	;;
@@ -89,6 +99,12 @@
 	ldf.fill f23=[sp];	ldf.fill f24=[sp];	mov f25=f0
 	ldf.fill f26=[sp];	ldf.fill f27=[sp];	mov f28=f0
 	ldf.fill f29=[sp];	ldf.fill f30=[sp];	mov f31=f0
+#ifdef CONFIG_IA32_SUPPORT
+	tbit.nz p6,p0=r16, IA64_PSR_IS_BIT
+	movl loc0=ia64_ret_from_ia32_execve
+	;;
+(p6)	mov rp=loc0
+#endif
 	br.ret.sptk.many rp
 END(ia64_execve)
 
@@ -688,7 +704,7 @@
 	mov b7=r0		// clear b7
 	;;
 (pUStk) st1 [r14]=r3
-	movl r17=THIS_CPU(ia64_phys_stacked_size_p8)
+	addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0
 	;;
 	mov r16=ar.bsp		// get existing backing store pointer
 	srlz.i			// ensure interruption collection is off
@@ -701,6 +717,19 @@
 	br.cond.sptk.many rbs_switch
 END(ia64_leave_syscall)
 
+#ifdef CONFIG_IA32_SUPPORT
+GLOBAL_ENTRY(ia64_ret_from_ia32_execve)
+	PT_REGS_UNWIND_INFO(0)
+	adds r2=PT(R8)+16,sp			// r2 = &pt_regs.r8
+	adds r3=PT(R10)+16,sp			// r3 = &pt_regs.r10
+	;;
+	.mem.offset 0,0
+	st8.spill [r2]=r8	// store return value in slot for r8 and set unat bit
+	.mem.offset 8,0
+	st8.spill [r3]=r0	// clear error indication in slot for r10 and set unat bit
+END(ia64_ret_from_ia32_execve_syscall)
+	// fall through
+#endif /* CONFIG_IA32_SUPPORT */
 GLOBAL_ENTRY(ia64_leave_kernel)
 	PT_REGS_UNWIND_INFO(0)
 	/*
@@ -841,7 +870,7 @@
 	shr.u r18=r19,16	// get byte size of existing "dirty" partition
 	;;
 	mov r16=ar.bsp		// get existing backing store pointer
-	movl r17=THIS_CPU(ia64_phys_stacked_size_p8)
+	addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0
 	;;
 	ld4 r17=[r17]		// r17 = cpu_data->phys_stacked_size_p8
 (pKStk)	br.cond.dpnt skip_rbs_switch
diff -Nru a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
--- a/arch/ia64/kernel/fsys.S	Sat Jul 19 12:54:21 2003
+++ b/arch/ia64/kernel/fsys.S	Sat Jul 19 12:54:21 2003
@@ -165,7 +165,7 @@
 	.altrp b6
 	.body
 	add r9=TI_FLAGS+IA64_TASK_SIZE,r16
-	movl r3=THIS_CPU(cpu_info)
+	addl r3=THIS_CPU(cpu_info),r0
 
 	mov.m r31=ar.itc		// put time stamp into r31 (ITC) == now		(35 cyc)
 #ifdef CONFIG_SMP
@@ -177,7 +177,7 @@
 	movl r19=xtime			// xtime is a timespec struct
 
 	ld8 r10=[r10]			// r10 <- __per_cpu_offset[0]
-	movl r21=THIS_CPU(cpu_info)
+	addl r21=THIS_CPU(cpu_info),r0
 	;;
 	add r10=r21, r10		// r10 <- &cpu_data(time_keeper_id)
 	tbit.nz p8,p0 = r2, IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT_BIT
diff -Nru a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
--- a/arch/ia64/kernel/ia64_ksyms.c	Sat Jul 19 12:54:25 2003
+++ b/arch/ia64/kernel/ia64_ksyms.c	Sat Jul 19 12:54:25 2003
@@ -64,9 +64,10 @@
 #endif
 
 #include <asm/processor.h>
-EXPORT_SYMBOL(cpu_info__per_cpu);
+EXPORT_SYMBOL(per_cpu__cpu_info);
 #ifdef CONFIG_SMP
 EXPORT_SYMBOL(__per_cpu_offset);
+EXPORT_SYMBOL(per_cpu__local_per_cpu_offset);
 #endif
 EXPORT_SYMBOL(kernel_thread);
 
diff -Nru a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c
--- a/arch/ia64/kernel/init_task.c	Sat Jul 19 12:54:30 2003
+++ b/arch/ia64/kernel/init_task.c	Sat Jul 19 12:54:30 2003
@@ -2,7 +2,7 @@
  * This is where we statically allocate and initialize the initial
  * task.
  *
- * Copyright (C) 1999, 2002 Hewlett-Packard Co
+ * Copyright (C) 1999, 2002-2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
@@ -34,7 +34,7 @@
 		struct thread_info thread_info;
 	} s;
 	unsigned long stack[KERNEL_STACK_SIZE/sizeof (unsigned long)];
-} init_task_mem __attribute__((section(".data.init_task"))) = {{
+} init_task_mem asm ("init_task_mem") __attribute__((section(".data.init_task"))) = {{
 	.task =		INIT_TASK(init_task_mem.s.task),
 	.thread_info =	INIT_THREAD_INFO(init_task_mem.s.task)
 }};
diff -Nru a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
--- a/arch/ia64/kernel/iosapic.c	Sat Jul 19 12:54:25 2003
+++ b/arch/ia64/kernel/iosapic.c	Sat Jul 19 12:54:25 2003
@@ -717,6 +717,7 @@
 			register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW,
 				      IOSAPIC_LEVEL);
 		}
+		entry->irq = vector;
 		snprintf(pci_id, sizeof(pci_id), "%02x:%02x:%02x[%c]",
 			 entry->id.segment, entry->id.bus, entry->id.device, 'A' + entry->pin);
 
diff -Nru a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
--- a/arch/ia64/kernel/module.c	Sat Jul 19 12:54:24 2003
+++ b/arch/ia64/kernel/module.c	Sat Jul 19 12:54:24 2003
@@ -164,7 +164,7 @@
 apply_imm64 (struct module *mod, struct insn *insn, uint64_t val)
 {
 	if (slot(insn) != 2) {
-		printk(KERN_ERR "%s: illegal slot number %d for IMM64\n",
+		printk(KERN_ERR "%s: invalid slot number %d for IMM64\n",
 		       mod->name, slot(insn));
 		return 0;
 	}
@@ -176,7 +176,7 @@
 apply_imm60 (struct module *mod, struct insn *insn, uint64_t val)
 {
 	if (slot(insn) != 2) {
-		printk(KERN_ERR "%s: illegal slot number %d for IMM60\n",
+		printk(KERN_ERR "%s: invalid slot number %d for IMM60\n",
 		       mod->name, slot(insn));
 		return 0;
 	}
diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
--- a/arch/ia64/kernel/perfmon.c	Sat Jul 19 12:54:29 2003
+++ b/arch/ia64/kernel/perfmon.c	Sat Jul 19 12:54:29 2003
@@ -566,7 +566,7 @@
 
 
 #define pfm_wait_task_inactive(t)	wait_task_inactive(t)
-#define pfm_get_cpu_var(v)		__get_cpu_var(v)
+#define pfm_get_cpu_var(v)		__ia64_per_cpu_var(v)
 #define pfm_get_cpu_data(a,b)		per_cpu(a, b)
 typedef	irqreturn_t	pfm_irq_handler_t;
 #define PFM_IRQ_HANDLER_RET(v)	do {  \
diff -Nru a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
--- a/arch/ia64/kernel/ptrace.c	Sat Jul 19 12:54:30 2003
+++ b/arch/ia64/kernel/ptrace.c	Sat Jul 19 12:54:30 2003
@@ -42,7 +42,7 @@
 	(IA64_PSR_UM | IA64_PSR_DB | IA64_PSR_IS | IA64_PSR_ID | IA64_PSR_DD | IA64_PSR_RI)
 #define IPSR_READ_MASK	IPSR_WRITE_MASK
 
-#define PTRACE_DEBUG	1
+#define PTRACE_DEBUG	0
 
 #if PTRACE_DEBUG
 # define dprintk(format...)	printk(format)
diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
--- a/arch/ia64/kernel/setup.c	Sat Jul 19 12:54:23 2003
+++ b/arch/ia64/kernel/setup.c	Sat Jul 19 12:54:23 2003
@@ -56,6 +56,7 @@
 #endif
 
 DEFINE_PER_CPU(struct cpuinfo_ia64, cpu_info);
+DEFINE_PER_CPU(unsigned long, local_per_cpu_offset);
 DEFINE_PER_CPU(unsigned long, ia64_phys_stacked_size_p8);
 unsigned long ia64_cycles_per_usec;
 struct ia64_boot_param *ia64_boot_param;
@@ -709,6 +710,8 @@
 			memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
 			__per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start;
 			cpu_data += PERCPU_PAGE_SIZE;
+
+			per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
 		}
 	}
 	cpu_data = __per_cpu_start + __per_cpu_offset[smp_processor_id()];
@@ -716,19 +719,18 @@
 	cpu_data = __phys_per_cpu_start;
 #endif /* !CONFIG_SMP */
 
-	cpu_info = cpu_data + ((char *) &__get_cpu_var(cpu_info) - __per_cpu_start);
-#ifdef CONFIG_NUMA
-	cpu_info->node_data = get_node_data_ptr();
-#endif
-
 	get_max_cacheline_size();
 
 	/*
 	 * We can't pass "local_cpu_data" to identify_cpu() because we haven't called
 	 * ia64_mmu_init() yet.  And we can't call ia64_mmu_init() first because it
 	 * depends on the data returned by identify_cpu().  We break the dependency by
-	 * accessing cpu_data() the old way, through identity mapped space.
+	 * accessing cpu_data() through the canonical per-CPU address.
 	 */
+	cpu_info = cpu_data + ((char *) &__ia64_per_cpu_var(cpu_info) - __per_cpu_start);
+#ifdef CONFIG_NUMA
+	cpu_info->node_data = get_node_data_ptr();
+#endif
 	identify_cpu(cpu_info);
 
 #ifdef CONFIG_MCKINLEY
diff -Nru a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
--- a/arch/ia64/kernel/smp.c	Sat Jul 19 12:54:30 2003
+++ b/arch/ia64/kernel/smp.c	Sat Jul 19 12:54:30 2003
@@ -72,7 +72,7 @@
 #define IPI_CPU_STOP		1
 
 /* This needs to be cacheline aligned because it is written to by *other* CPUs.  */
-static DEFINE_PER_CPU(__u64, ipi_operation) ____cacheline_aligned;
+static DEFINE_PER_CPU(u64, ipi_operation) ____cacheline_aligned;
 
 static void
 stop_this_cpu (void)
@@ -91,7 +91,7 @@
 handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
 {
 	int this_cpu = get_cpu();
-	unsigned long *pending_ipis = &__get_cpu_var(ipi_operation);
+	unsigned long *pending_ipis = &__ia64_per_cpu_var(ipi_operation);
 	unsigned long ops;
 
 	/* Count this now; we may make a call that never returns. */
diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
--- a/arch/ia64/kernel/time.c	Sat Jul 19 12:54:23 2003
+++ b/arch/ia64/kernel/time.c	Sat Jul 19 12:54:23 2003
@@ -83,12 +83,11 @@
 itc_get_offset (void)
 {
 	unsigned long elapsed_cycles, lost = jiffies - wall_jiffies;
-	unsigned long now, last_tick;
+	unsigned long now = ia64_get_itc(), last_tick;
 
 	last_tick = (cpu_data(TIME_KEEPER_ID)->itm_next
 		     - (lost + 1)*cpu_data(TIME_KEEPER_ID)->itm_delta);
 
-	now = ia64_get_itc();
 	if (unlikely((long) (now - last_tick) < 0)) {
 		printk(KERN_ERR "CPU %d: now < last_tick (now=0x%lx,last_tick=0x%lx)!\n",
 		       smp_processor_id(), now, last_tick);
diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
--- a/arch/ia64/pci/pci.c	Sat Jul 19 12:54:25 2003
+++ b/arch/ia64/pci/pci.c	Sat Jul 19 12:54:25 2003
@@ -124,7 +124,7 @@
 
 /* Called by ACPI when it finds a new root bus.  */
 
-static struct pci_controller *
+static struct pci_controller * __devinit
 alloc_pci_controller (int seg)
 {
 	struct pci_controller *controller;
@@ -138,7 +138,7 @@
 	return controller;
 }
 
-static int
+static int __devinit
 alloc_resource (char *name, struct resource *root, unsigned long start, unsigned long end, unsigned long flags)
 {
 	struct resource *res;
@@ -159,7 +159,7 @@
 	return 0;
 }
 
-static u64
+static u64 __devinit
 add_io_space (struct acpi_resource_address64 *addr)
 {
 	u64 offset;
@@ -190,7 +190,7 @@
 	return IO_SPACE_BASE(i);
 }
 
-static acpi_status
+static acpi_status __devinit
 count_window (struct acpi_resource *resource, void *data)
 {
 	unsigned int *windows = (unsigned int *) data;
@@ -211,7 +211,7 @@
 	char *name;
 };
 
-static acpi_status
+static acpi_status __devinit
 add_window (struct acpi_resource *res, void *data)
 {
 	struct pci_root_info *info = (struct pci_root_info *) data;
@@ -252,7 +252,7 @@
 	return AE_OK;
 }
 
-struct pci_bus *
+struct pci_bus * __devinit
 pci_acpi_scan_root (struct acpi_device *device, int domain, int bus)
 {
 	struct pci_root_info info;
diff -Nru a/arch/ia64/scripts/check-model.c b/arch/ia64/scripts/check-model.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/scripts/check-model.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1 @@
+int __attribute__ ((__model__ (__small__))) x;
diff -Nru a/arch/ia64/scripts/toolchain-flags b/arch/ia64/scripts/toolchain-flags
--- a/arch/ia64/scripts/toolchain-flags	Sat Jul 19 12:54:29 2003
+++ b/arch/ia64/scripts/toolchain-flags	Sat Jul 19 12:54:29 2003
@@ -2,6 +2,7 @@
 #
 # Check whether linker can handle cross-segment @segrel():
 #
+CPPFLAGS=""
 CC=$1
 OBJDUMP=$2
 dir=$(dirname $0)
@@ -11,10 +12,17 @@
 res=$($OBJDUMP --full --section .rodata $out | fgrep 000 | cut -f3 -d' ')
 rm -f $out
 if [ $res != 00000a00 ]; then
-    echo " -DHAVE_BUGGY_SEGREL"
+    CPPFLAGS="$CPPFLAGS -DHAVE_BUGGY_SEGREL"
     cat >&2 <<EOF
 warning: your linker cannot handle cross-segment segment-relative relocations.
          please upgrade to a newer version (it is safe to use this linker, but
          the kernel will be bigger than strictly necessary).
 EOF
 fi
+
+if ! $CC -c $dir/check-model.c -o $out | grep -q 'attribute directive ignored'
+then
+    CPPFLAGS="$CPPFLAGS -DHAVE_MODEL_SMALL_ATTRIBUTE"
+fi
+rm -f $out
+echo $CPPFLAGS
diff -Nru a/arch/m68k/apollo/dn_ints.c b/arch/m68k/apollo/dn_ints.c
--- a/arch/m68k/apollo/dn_ints.c	Sat Jul 19 12:54:26 2003
+++ b/arch/m68k/apollo/dn_ints.c	Sat Jul 19 12:54:26 2003
@@ -46,7 +46,7 @@
 int dn_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) {
 
   if((irq<0) || (irq>15)) {
-    printk("Trying to request illegal IRQ\n");
+    printk("Trying to request invalid IRQ\n");
     return -ENXIO;
   }
 
@@ -72,7 +72,7 @@
 void dn_free_irq(unsigned int irq, void *dev_id) {
 
   if((irq<0) || (irq>15)) {
-    printk("Trying to free illegal IRQ\n");
+    printk("Trying to free invalid IRQ\n");
     return ;
   }
 
diff -Nru a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
--- a/arch/m68k/atari/stram.c	Sat Jul 19 12:54:26 2003
+++ b/arch/m68k/atari/stram.c	Sat Jul 19 12:54:26 2003
@@ -37,7 +37,6 @@
 #define MAJOR_NR    Z2RAM_MAJOR
 #define do_z2_request do_stram_request
 #define DEVICE_NR(device) (minor(device))
-#include <linux/blk.h>
 #endif
 
 #undef DEBUG
diff -Nru a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
--- a/arch/m68k/mm/init.c	Sat Jul 19 12:54:27 2003
+++ b/arch/m68k/mm/init.c	Sat Jul 19 12:54:27 2003
@@ -17,9 +17,6 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
-#ifdef CONFIG_BLK_DEV_RAM
-#include <linux/blk.h>
-#endif
 
 #include <asm/setup.h>
 #include <asm/uaccess.h>
diff -Nru a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
--- a/arch/m68k/mm/motorola.c	Sat Jul 19 12:54:25 2003
+++ b/arch/m68k/mm/motorola.c	Sat Jul 19 12:54:25 2003
@@ -18,9 +18,6 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
-#ifdef CONFIG_BLK_DEV_RAM
-#include <linux/blk.h>
-#endif
 
 #include <asm/setup.h>
 #include <asm/uaccess.h>
diff -Nru a/arch/m68k/mm/sun3mmu.c b/arch/m68k/mm/sun3mmu.c
--- a/arch/m68k/mm/sun3mmu.c	Sat Jul 19 12:54:24 2003
+++ b/arch/m68k/mm/sun3mmu.c	Sat Jul 19 12:54:24 2003
@@ -16,9 +16,6 @@
 #include <linux/string.h>
 #include <linux/types.h>
 #include <linux/init.h>
-#ifdef CONFIG_BLK_DEV_RAM
-#include <linux/blk.h>
-#endif
 #include <linux/bootmem.h>
 
 #include <asm/setup.h>
diff -Nru a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
--- a/arch/m68k/q40/q40ints.c	Sat Jul 19 12:54:27 2003
+++ b/arch/m68k/q40/q40ints.c	Sat Jul 19 12:54:27 2003
@@ -171,7 +171,7 @@
 	  {
 	  case 1: case 2: case 8: case 9:
 	  case 12: case 13:
-	    printk("%s: ISA IRQ %d from %x illegal\n", __FUNCTION__, irq, (unsigned)dev_id);
+	    printk("%s: ISA IRQ %d from %x invalid\n", __FUNCTION__, irq, (unsigned)dev_id);
 	    return;
 	  case 11: irq=10;
 	  default:
diff -Nru a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
--- a/arch/m68knommu/kernel/setup.c	Sat Jul 19 12:54:26 2003
+++ b/arch/m68knommu/kernel/setup.c	Sat Jul 19 12:54:26 2003
@@ -37,7 +37,6 @@
 #include <asm/machdep.h>
 
 #ifdef CONFIG_BLK_DEV_INITRD
-#include <linux/blk.h>
 #include <asm/pgtable.h>
 #endif
 
diff -Nru a/arch/m68knommu/mm/init.c b/arch/m68knommu/mm/init.c
--- a/arch/m68knommu/mm/init.c	Sat Jul 19 12:54:26 2003
+++ b/arch/m68knommu/mm/init.c	Sat Jul 19 12:54:26 2003
@@ -27,9 +27,6 @@
 #include <linux/mm.h>
 #include <linux/swap.h>
 #include <linux/init.h>
-#ifdef CONFIG_BLK_DEV_RAM
-#include <linux/blk.h>
-#endif
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
 #include <linux/bootmem.h>
diff -Nru a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
--- a/arch/mips/mm/fault.c	Sat Jul 19 12:54:24 2003
+++ b/arch/mips/mm/fault.c	Sat Jul 19 12:54:24 2003
@@ -162,7 +162,7 @@
 		tsk->thread.cp0_badvaddr = address;
 		tsk->thread.error_code = write;
 #if 0
-		printk("do_page_fault() #2: sending SIGSEGV to %s for illegal %s\n"
+		printk("do_page_fault() #2: sending SIGSEGV to %s for invalid %s\n"
 		       "%08lx (epc == %08lx, ra == %08lx)\n",
 		       tsk->comm,
 		       write ? "write access to" : "read access from",
diff -Nru a/arch/mips/mm/init.c b/arch/mips/mm/init.c
--- a/arch/mips/mm/init.c	Sat Jul 19 12:54:27 2003
+++ b/arch/mips/mm/init.c	Sat Jul 19 12:54:27 2003
@@ -24,7 +24,7 @@
 #include <linux/bootmem.h>
 #include <linux/highmem.h>
 #include <linux/swap.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 
 #include <asm/bootinfo.h>
 #include <asm/cacheflush.h>
diff -Nru a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c
--- a/arch/mips/momentum/ocelot_c/setup.c	Sat Jul 19 12:54:23 2003
+++ b/arch/mips/momentum/ocelot_c/setup.c	Sat Jul 19 12:54:23 2003
@@ -63,7 +63,7 @@
 #include <asm/mc146818rtc.h>
 #include <linux/version.h>
 #include <linux/bootmem.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <asm/mv64340.h>
 #include "ocelot_c_fpga.h"
 
diff -Nru a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c
--- a/arch/mips/momentum/ocelot_g/setup.c	Sat Jul 19 12:54:24 2003
+++ b/arch/mips/momentum/ocelot_g/setup.c	Sat Jul 19 12:54:24 2003
@@ -64,7 +64,7 @@
 #include <asm/mc146818rtc.h>
 #include <linux/version.h>
 #include <linux/bootmem.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include "gt64240.h"
 #include "ocelot_pld.h"
 
diff -Nru a/arch/mips/ramdisk/Makefile b/arch/mips/ramdisk/Makefile
--- a/arch/mips/ramdisk/Makefile	Sat Jul 19 12:54:26 2003
+++ b/arch/mips/ramdisk/Makefile	Sat Jul 19 12:54:26 2003
@@ -2,7 +2,7 @@
 # Makefile for a ramdisk image
 #
 
-O_FORMAT = $(shell $(OBJDUMP) -i | head -2 | grep elf32)
+O_FORMAT = $(shell $(OBJDUMP) -i | head -n 2 | grep elf32)
 img = $(CONFIG_EMBEDDED_RAMDISK_IMAGE)
 ramdisk.o: $(subst ",,$(img)) ld.script
 	echo "O_FORMAT:  " $(O_FORMAT)
diff -Nru a/arch/mips/sibyte/cfe/setup.c b/arch/mips/sibyte/cfe/setup.c
--- a/arch/mips/sibyte/cfe/setup.c	Sat Jul 19 12:54:23 2003
+++ b/arch/mips/sibyte/cfe/setup.c	Sat Jul 19 12:54:23 2003
@@ -20,7 +20,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/bootmem.h>
 #include <linux/smp.h>
 
diff -Nru a/arch/mips/sibyte/sb1250/prom.c b/arch/mips/sibyte/sb1250/prom.c
--- a/arch/mips/sibyte/sb1250/prom.c	Sat Jul 19 12:54:26 2003
+++ b/arch/mips/sibyte/sb1250/prom.c	Sat Jul 19 12:54:26 2003
@@ -20,7 +20,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/bootmem.h>
 #include <linux/smp.h>
 
diff -Nru a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
--- a/arch/mips/sibyte/swarm/setup.c	Sat Jul 19 12:54:25 2003
+++ b/arch/mips/sibyte/swarm/setup.c	Sat Jul 19 12:54:25 2003
@@ -23,7 +23,7 @@
 #include <linux/spinlock.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/init.h>
 #include <linux/ide.h>
 #include <linux/console.h>
diff -Nru a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c	Sat Jul 19 12:54:24 2003
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c	Sat Jul 19 12:54:24 2003
@@ -134,7 +134,7 @@
 #include <asm/time.h>
 #include <linux/version.h>
 #include <linux/bootmem.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #ifdef CONFIG_RTC_DS1742
 #include <asm/rtc_ds1742.h>
 #endif
diff -Nru a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c	Sat Jul 19 12:54:25 2003
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c	Sat Jul 19 12:54:25 2003
@@ -62,7 +62,7 @@
 #include <asm/time.h>
 #include <linux/version.h>
 #include <linux/bootmem.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/console.h>
 #ifdef CONFIG_RTC_DS1742
 #include <asm/rtc_ds1742.h>
diff -Nru a/arch/mips/vr41xx/tanbac-tb0229/setup.c b/arch/mips/vr41xx/tanbac-tb0229/setup.c
--- a/arch/mips/vr41xx/tanbac-tb0229/setup.c	Sat Jul 19 12:54:25 2003
+++ b/arch/mips/vr41xx/tanbac-tb0229/setup.c	Sat Jul 19 12:54:25 2003
@@ -18,7 +18,7 @@
  *  option) any later version.
  */
 #include <linux/config.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/console.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
diff -Nru a/arch/mips64/kernel/setup.c b/arch/mips64/kernel/setup.c
--- a/arch/mips64/kernel/setup.c	Sat Jul 19 12:54:21 2003
+++ b/arch/mips64/kernel/setup.c	Sat Jul 19 12:54:21 2003
@@ -28,9 +28,6 @@
 #include <linux/a.out.h>
 #include <linux/tty.h>
 #include <linux/bootmem.h>
-#ifdef CONFIG_BLK_DEV_RAM
-#include <linux/blk.h>
-#endif
 #include <linux/major.h>
 #include <linux/kdev_t.h>
 #include <linux/root_dev.h>
diff -Nru a/arch/parisc/kernel/ioctl32.c b/arch/parisc/kernel/ioctl32.c
--- a/arch/parisc/kernel/ioctl32.c	Sat Jul 19 12:54:21 2003
+++ b/arch/parisc/kernel/ioctl32.c	Sat Jul 19 12:54:21 2003
@@ -48,7 +48,6 @@
 #include <linux/raw.h>
 #include <linux/smb_fs.h>
 #include <linux/blkpg.h>
-#include <linux/blk.h>
 #include <linux/elevator.h>
 #include <linux/rtc.h>
 #include <linux/pci.h>
diff -Nru a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
--- a/arch/ppc/kernel/irq.c	Sat Jul 19 12:54:27 2003
+++ b/arch/ppc/kernel/irq.c	Sat Jul 19 12:54:27 2003
@@ -420,10 +420,9 @@
 {
 	int status;
 	struct irqaction *action;
-	int cpu = smp_processor_id();
 	irq_desc_t *desc = irq_desc + irq;
 
-	kstat_cpu(cpu).irqs[irq]++;
+	kstat_this_cpu.irqs[irq]++;
 	spin_lock(&desc->lock);
 	ack_irq(irq);	
 	/*
diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
--- a/arch/ppc/kernel/misc.S	Sat Jul 19 12:54:28 2003
+++ b/arch/ppc/kernel/misc.S	Sat Jul 19 12:54:28 2003
@@ -1375,3 +1375,8 @@
 	.long sys_clock_gettime
 	.long sys_clock_getres
 	.long sys_clock_nanosleep
+	.long sys_ni_syscall	/* reserved for swapcontext */
+	.long sys_tgkill	/* 250 */
+	.long sys_utimes
+	.long sys_statfs64
+	.long sys_fstatfs64
diff -Nru a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c
--- a/arch/ppc/kernel/syscalls.c	Sat Jul 19 12:54:29 2003
+++ b/arch/ppc/kernel/syscalls.c	Sat Jul 19 12:54:29 2003
@@ -20,7 +20,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -59,10 +58,15 @@
 	version = call >> 16; /* hack for backward compatibility */
 	call &= 0xffff;
 
-	ret = -EINVAL;
+	ret = -ENOSYS;
 	switch (call) {
 	case SEMOP:
-		ret = sys_semop (first, (struct sembuf __user *)ptr, second);
+		ret = sys_semtimedop (first, (struct sembuf __user *)ptr,
+				      second, NULL);
+		break;
+	case SEMTIMEDOP:
+		ret = sys_semtimedop (first, (struct sembuf __user *)ptr,
+				      second, (const struct timespec *) fifth);
 		break;
 	case SEMGET:
 		ret = sys_semget (first, second, third);
@@ -258,6 +262,4 @@
 	return error;
 }
 
-cond_syscall(sys_pciconfig_read);
-cond_syscall(sys_pciconfig_write);
 cond_syscall(sys_pciconfig_iobase);
diff -Nru a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
--- a/arch/ppc/kernel/time.c	Sat Jul 19 12:54:26 2003
+++ b/arch/ppc/kernel/time.c	Sat Jul 19 12:54:26 2003
@@ -244,7 +244,7 @@
 	time_t wtm_sec, new_sec = tv->tv_sec;
 	long wtm_nsec, new_nsec = tv->tv_nsec;
 	unsigned long flags;
-	int tb_delta, new_nsec, new_sec;
+	int tb_delta;
 
 	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
 		return -EINVAL;
diff -Nru a/arch/ppc/mm/mem_pieces.c b/arch/ppc/mm/mem_pieces.c
--- a/arch/ppc/mm/mem_pieces.c	Sat Jul 19 12:54:21 2003
+++ b/arch/ppc/mm/mem_pieces.c	Sat Jul 19 12:54:21 2003
@@ -17,7 +17,6 @@
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
-#include <linux/blk.h>
 #include <linux/init.h>
 
 #include "mem_pieces.h"
diff -Nru a/arch/ppc/platforms/4xx/beech.c b/arch/ppc/platforms/4xx/beech.c
--- a/arch/ppc/platforms/4xx/beech.c	Sat Jul 19 12:54:25 2003
+++ b/arch/ppc/platforms/4xx/beech.c	Sat Jul 19 12:54:25 2003
@@ -25,7 +25,6 @@
  *
  */
 
-#include <linux/blk.h>
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
diff -Nru a/arch/ppc/platforms/4xx/sycamore.c b/arch/ppc/platforms/4xx/sycamore.c
--- a/arch/ppc/platforms/4xx/sycamore.c	Sat Jul 19 12:54:25 2003
+++ b/arch/ppc/platforms/4xx/sycamore.c	Sat Jul 19 12:54:25 2003
@@ -17,7 +17,6 @@
 #include <linux/threads.h>
 #include <linux/param.h>
 #include <linux/string.h>
-#include <linux/blk.h>
 #include <linux/pci.h>
 #include <linux/rtc.h>
 
diff -Nru a/arch/ppc/platforms/4xx/walnut.c b/arch/ppc/platforms/4xx/walnut.c
--- a/arch/ppc/platforms/4xx/walnut.c	Sat Jul 19 12:54:25 2003
+++ b/arch/ppc/platforms/4xx/walnut.c	Sat Jul 19 12:54:25 2003
@@ -19,7 +19,6 @@
 #include <linux/threads.h>
 #include <linux/param.h>
 #include <linux/string.h>
-#include <linux/blk.h>
 #include <linux/pci.h>
 #include <linux/rtc.h>
 
diff -Nru a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c
--- a/arch/ppc/platforms/pmac_cpufreq.c	Sat Jul 19 12:54:25 2003
+++ b/arch/ppc/platforms/pmac_cpufreq.c	Sat Jul 19 12:54:25 2003
@@ -176,7 +176,7 @@
 	
 	freqs.old = cur_freq;
 	freqs.new = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
-	freqs.cpu = CPUFREQ_ALL_CPUS;
+	freqs.cpu = smp_processor_id();
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 	if (cpufreq_uses_pmu)
diff -Nru a/arch/ppc/platforms/residual.c b/arch/ppc/platforms/residual.c
--- a/arch/ppc/platforms/residual.c	Sat Jul 19 12:54:23 2003
+++ b/arch/ppc/platforms/residual.c	Sat Jul 19 12:54:23 2003
@@ -36,7 +36,6 @@
 #include <linux/interrupt.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
-#include <linux/blk.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <linux/ide.h>
diff -Nru a/arch/ppc64/boot/Makefile b/arch/ppc64/boot/Makefile
--- a/arch/ppc64/boot/Makefile	Sat Jul 19 12:54:27 2003
+++ b/arch/ppc64/boot/Makefile	Sat Jul 19 12:54:27 2003
@@ -118,7 +118,7 @@
 	ls -l vmlinux | \
 	awk '{printf "/* generated -- do not edit! */\n" \
 		"unsigned long vmlinux_filesize = %d;\n", $$5}' > $(obj)/imagesize.c
-	$(CROSS_COMPILE)nm -n vmlinux | tail -1 | \
+	$(CROSS_COMPILE)nm -n vmlinux | tail -n 1 | \
 	awk '{printf "unsigned long vmlinux_memsize = 0x%s;\n", substr($$1,8)}' \
 		>> $(obj)/imagesize.c
 
diff -Nru a/arch/ppc64/kernel/XmPciLpEvent.c b/arch/ppc64/kernel/XmPciLpEvent.c
--- a/arch/ppc64/kernel/XmPciLpEvent.c	Sat Jul 19 12:54:25 2003
+++ b/arch/ppc64/kernel/XmPciLpEvent.c	Sat Jul 19 12:54:25 2003
@@ -12,7 +12,6 @@
 #include <linux/param.h>
 #include <linux/string.h>
 #include <linux/bootmem.h>
-#include <linux/blk.h>
 #include <linux/ide.h>
 
 #include <asm/iSeries/HvTypes.h>
diff -Nru a/arch/ppc64/kernel/iSeries_irq.c b/arch/ppc64/kernel/iSeries_irq.c
--- a/arch/ppc64/kernel/iSeries_irq.c	Sat Jul 19 12:54:26 2003
+++ b/arch/ppc64/kernel/iSeries_irq.c	Sat Jul 19 12:54:26 2003
@@ -29,7 +29,6 @@
 #include <linux/param.h>
 #include <linux/string.h>
 #include <linux/bootmem.h>
-#include <linux/blk.h>
 #include <linux/ide.h>
 
 #include <linux/irq.h>
diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
--- a/arch/ppc64/kernel/prom.c	Sat Jul 19 12:54:26 2003
+++ b/arch/ppc64/kernel/prom.c	Sat Jul 19 12:54:26 2003
@@ -27,7 +27,6 @@
 #include <linux/version.h>
 #include <linux/threads.h>
 #include <linux/spinlock.h>
-#include <linux/blk.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <asm/prom.h>
diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
--- a/arch/ppc64/mm/init.c	Sat Jul 19 12:54:25 2003
+++ b/arch/ppc64/mm/init.c	Sat Jul 19 12:54:25 2003
@@ -37,9 +37,6 @@
 #include <linux/bootmem.h>
 #include <linux/highmem.h>
 #include <linux/proc_fs.h>
-#ifdef CONFIG_BLK_DEV_INITRD
-#include <linux/blk.h>		/* for initrd_* */
-#endif
 
 #include <asm/pgalloc.h>
 #include <asm/page.h>
diff -Nru a/arch/s390/defconfig b/arch/s390/defconfig
--- a/arch/s390/defconfig	Sat Jul 19 12:54:27 2003
+++ b/arch/s390/defconfig	Sat Jul 19 12:54:27 2003
@@ -20,6 +20,7 @@
 CONFIG_SYSCTL=y
 CONFIG_LOG_BUF_SHIFT=17
 # CONFIG_EMBEDDED is not set
+# CONFIG_KALLSYMS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 
@@ -169,7 +170,7 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
-CONFIG_IPV6=m
+CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
@@ -180,7 +181,7 @@
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=m
+CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
@@ -383,7 +384,6 @@
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_SLAB is not set
-# CONFIG_KALLSYMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 
 #
diff -Nru a/arch/s390/kernel/compat_ioctl.c b/arch/s390/kernel/compat_ioctl.c
--- a/arch/s390/kernel/compat_ioctl.c	Sat Jul 19 12:54:26 2003
+++ b/arch/s390/kernel/compat_ioctl.c	Sat Jul 19 12:54:26 2003
@@ -23,7 +23,6 @@
 #include <asm/types.h>
 #include <asm/uaccess.h>
 
-#include <linux/blk.h>
 #include <linux/blkpg.h>
 #include <linux/cdrom.h>
 #include <linux/dm-ioctl.h>
diff -Nru a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
--- a/arch/s390/kernel/compat_linux.c	Sat Jul 19 12:54:27 2003
+++ b/arch/s390/kernel/compat_linux.c	Sat Jul 19 12:54:27 2003
@@ -250,14 +250,14 @@
 static inline long get_tv32(struct timeval *o, struct compat_timeval *i)
 {
 	return (!access_ok(VERIFY_READ, tv32, sizeof(*tv32)) ||
-		(__get_user(o->tv_sec, &i->tv_sec) |
+		(__get_user(o->tv_sec, &i->tv_sec) ||
 		 __get_user(o->tv_usec, &i->tv_usec)));
 }
 
 static inline long put_tv32(struct compat_timeval *o, struct timeval *i)
 {
 	return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
-		(__put_user(i->tv_sec, &o->tv_sec) |
+		(__put_user(i->tv_sec, &o->tv_sec) ||
 		 __put_user(i->tv_usec, &o->tv_usec)));
 }
 
diff -Nru a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
--- a/arch/s390/kernel/entry.S	Sat Jul 19 12:54:23 2003
+++ b/arch/s390/kernel/entry.S	Sat Jul 19 12:54:23 2003
@@ -606,6 +606,8 @@
 	SAVE_ALL_BASE
         SAVE_ALL __LC_EXT_OLD_PSW,0
         GET_THREAD_INFO                # load pointer to task_struct to R9
+	l	%r1,BASED(.Ldo_extint)
+	basr	%r14,%r1
 	lh	%r6,__LC_EXT_INT_CODE  # get interruption code
 	lr	%r1,%r6		       # calculate index = code & 0xff
 	n	%r1,BASED(.Lc0xff)
@@ -694,6 +696,7 @@
  */
 .Ls390_mcck:   .long  s390_do_machine_check
 .Ldo_IRQ:      .long  do_IRQ
+.Ldo_extint:   .long  do_extint
 .Ldo_signal:   .long  do_signal
 .Ldo_softirq:  .long  do_softirq
 .Lentry_base:  .long  entry_base
diff -Nru a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
--- a/arch/s390/kernel/entry64.S	Sat Jul 19 12:54:23 2003
+++ b/arch/s390/kernel/entry64.S	Sat Jul 19 12:54:23 2003
@@ -637,6 +637,7 @@
 ext_int_handler:
         SAVE_ALL __LC_EXT_OLD_PSW,0
         GET_THREAD_INFO                # load pointer to task_struct to R9
+	brasl   %r14,do_extint
 	llgh	%r6,__LC_EXT_INT_CODE  # get interruption code
 	lgr	%r1,%r6		       # calculate index = code & 0xff
 	nill	%r1,0xff
diff -Nru a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c
--- a/arch/s390/kernel/s390_ext.c	Sat Jul 19 12:54:25 2003
+++ b/arch/s390/kernel/s390_ext.c	Sat Jul 19 12:54:25 2003
@@ -11,8 +11,11 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
+#include <linux/kernel_stat.h>
+
 #include <asm/lowcore.h>
 #include <asm/s390_ext.h>
+#include <asm/irq.h>
 
 /*
  * Simple hash strategy: index = code & 0xff;
@@ -96,6 +99,11 @@
 	} else
 		ext_int_hash[index] = p->next;
 	return 0;
+}
+
+void do_extint(void)
+{
+	kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
 }
 
 EXPORT_SYMBOL(register_external_interrupt);
diff -Nru a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
--- a/arch/s390/kernel/setup.c	Sat Jul 19 12:54:22 2003
+++ b/arch/s390/kernel/setup.c	Sat Jul 19 12:54:22 2003
@@ -34,12 +34,15 @@
 #include <linux/root_dev.h>
 #include <linux/console.h>
 #include <linux/seq_file.h>
+#include <linux/kernel_stat.h>
+
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/smp.h>
 #include <asm/mmu_context.h>
 #include <asm/cpcmd.h>
 #include <asm/lowcore.h>
+#include <asm/irq.h>
 
 /*
  * Machine setup..
@@ -600,3 +603,40 @@
 	.stop	= c_stop,
 	.show	= show_cpuinfo,
 };
+
+/*
+ * show_interrupts is needed by /proc/interrupts.
+ */
+
+static const char *intrclass_names[] = {
+	"EXT",
+	"I/O",
+};
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+        int i, j;
+	
+        seq_puts(p, "           ");
+	
+        for (j=0; j<NR_CPUS; j++)
+                if (cpu_online(j))
+                        seq_printf(p, "CPU%d       ",j);
+	
+        seq_putc(p, '\n');
+	
+        for (i = 0 ; i < NR_IRQS ; i++) {
+		seq_printf(p, "%s: ", intrclass_names[i]);
+#ifndef CONFIG_SMP
+		seq_printf(p, "%10u ", kstat_irqs(i));
+#else
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+#endif
+                seq_putc(p, '\n');
+		
+        }
+	
+        return 0;
+}
diff -Nru a/arch/s390/mm/init.c b/arch/s390/mm/init.c
--- a/arch/s390/mm/init.c	Sat Jul 19 12:54:26 2003
+++ b/arch/s390/mm/init.c	Sat Jul 19 12:54:26 2003
@@ -22,9 +22,6 @@
 #include <linux/swap.h>
 #include <linux/smp.h>
 #include <linux/init.h>
-#ifdef CONFIG_BLK_DEV_INITRD
-#include <linux/blk.h>
-#endif
 #include <linux/pagemap.h>
 #include <linux/bootmem.h>
 
diff -Nru a/arch/sh/mm/init.c b/arch/sh/mm/init.c
--- a/arch/sh/mm/init.c	Sat Jul 19 12:54:27 2003
+++ b/arch/sh/mm/init.c	Sat Jul 19 12:54:27 2003
@@ -22,9 +22,6 @@
 #include <linux/swap.h>
 #include <linux/smp.h>
 #include <linux/init.h>
-#ifdef CONFIG_BLK_DEV_INITRD
-#include <linux/blk.h>
-#endif
 #include <linux/highmem.h>
 #include <linux/bootmem.h>
 
diff -Nru a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
--- a/arch/sparc/kernel/process.c	Sat Jul 19 12:54:23 2003
+++ b/arch/sparc/kernel/process.c	Sat Jul 19 12:54:23 2003
@@ -590,16 +590,20 @@
 		put_psr(get_psr() | PSR_EF);
 		fpsave(&current->thread.float_regs[0], &current->thread.fsr,
 		       &current->thread.fpqueue[0], &current->thread.fpqdepth);
-		regs->psr &= ~(PSR_EF);
-		current->flags &= ~(PF_USEDFPU);
+		if (regs != NULL) {
+			regs->psr &= ~(PSR_EF);
+			current->flags &= ~(PF_USEDFPU);
+		}
 	}
 #else
 	if (current == last_task_used_math) {
 		put_psr(get_psr() | PSR_EF);
 		fpsave(&current->thread.float_regs[0], &current->thread.fsr,
 		       &current->thread.fpqueue[0], &current->thread.fpqdepth);
-		last_task_used_math = 0;
-		regs->psr &= ~(PSR_EF);
+		if (regs != NULL) {
+			regs->psr &= ~(PSR_EF);
+			last_task_used_math = 0;
+		}
 	}
 #endif
 	memcpy(&fpregs->pr_fr.pr_regs[0],
diff -Nru a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
--- a/arch/sparc/kernel/setup.c	Sat Jul 19 12:54:21 2003
+++ b/arch/sparc/kernel/setup.c	Sat Jul 19 12:54:21 2003
@@ -25,7 +25,6 @@
 #include <linux/kdev_t.h>
 #include <linux/major.h>
 #include <linux/string.h>
-#include <linux/blk.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/console.h>
diff -Nru a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
--- a/arch/sparc/mm/srmmu.c	Sat Jul 19 12:54:25 2003
+++ b/arch/sparc/mm/srmmu.c	Sat Jul 19 12:54:25 2003
@@ -15,7 +15,6 @@
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
-#include <linux/blk.h>
 #include <linux/spinlock.h>
 #include <linux/bootmem.h>
 #include <linux/fs.h>
diff -Nru a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
--- a/arch/sparc64/kernel/head.S	Sat Jul 19 12:54:24 2003
+++ b/arch/sparc64/kernel/head.S	Sat Jul 19 12:54:24 2003
@@ -66,7 +66,7 @@
 sparc_ramdisk_size:
         .word   0
         .xword  reboot_command
-	.xword	bootstr_len
+	.xword	bootstr_info
 	.word	_end
 
 	/* We must be careful, 32-bit OpenBOOT will get confused if it
@@ -740,8 +740,9 @@
 
 	.data
 	.align	8
-	.globl	prom_tba
+	.globl	prom_tba, tlb_type
 prom_tba:	.xword	0
+tlb_type:	.word	0	/* Must NOT end up in BSS */
 	.section	".fixup",#alloc,#execinstr
 	.globl	__ret_efault
 __ret_efault:
diff -Nru a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
--- a/arch/sparc64/kernel/pci.c	Sat Jul 19 12:54:21 2003
+++ b/arch/sparc64/kernel/pci.c	Sat Jul 19 12:54:21 2003
@@ -804,25 +804,20 @@
 
 /* Return the domain nuber for this pci bus */
 
-int pci_domain_nr(struct pci_bus *bus)
+int pci_domain_nr(struct pci_bus *pbus)
 {
-	struct pcidev_cookie *cookie = bus->sysdata;
+	struct pci_pbm_info *pbm = pbus->sysdata;
 	int ret;
 
-	if (cookie != NULL) {
-		struct pci_pbm_info *pbm = cookie->pbm;
-		if (pbm == NULL || pbm->parent == NULL) {
-			ret = -ENXIO;
-		} else {
-			struct pci_controller_info *p = pbm->parent;
-
-			ret = p->index;
-			if (p->pbms_same_domain == 0)
-				ret = ((ret << 1) +
-				       ((pbm == &pbm->parent->pbm_B) ? 1 : 0));
-		}
-	} else {
+	if (pbm == NULL || pbm->parent == NULL) {
 		ret = -ENXIO;
+	} else {
+		struct pci_controller_info *p = pbm->parent;
+
+		ret = p->index;
+		if (p->pbms_same_domain == 0)
+			ret = ((ret << 1) +
+			       ((pbm == &pbm->parent->pbm_B) ? 1 : 0));
 	}
 
 	return ret;
diff -Nru a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
--- a/arch/sparc64/kernel/setup.c	Sat Jul 19 12:54:24 2003
+++ b/arch/sparc64/kernel/setup.c	Sat Jul 19 12:54:24 2003
@@ -24,7 +24,6 @@
 #include <linux/kdev_t.h>
 #include <linux/major.h>
 #include <linux/string.h>
-#include <linux/blk.h>
 #include <linux/init.h>
 #include <linux/inet.h>
 #include <linux/console.h>
diff -Nru a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
--- a/arch/sparc64/kernel/sparc64_ksyms.c	Sat Jul 19 12:54:27 2003
+++ b/arch/sparc64/kernel/sparc64_ksyms.c	Sat Jul 19 12:54:27 2003
@@ -176,6 +176,8 @@
 /* Atomic counter implementation. */
 EXPORT_SYMBOL(__atomic_add);
 EXPORT_SYMBOL(__atomic_sub);
+EXPORT_SYMBOL(__atomic64_add);
+EXPORT_SYMBOL(__atomic64_sub);
 #ifdef CONFIG_SMP
 EXPORT_SYMBOL(atomic_dec_and_lock);
 #endif
diff -Nru a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
--- a/arch/sparc64/kernel/time.c	Sat Jul 19 12:54:25 2003
+++ b/arch/sparc64/kernel/time.c	Sat Jul 19 12:54:25 2003
@@ -41,6 +41,7 @@
 #include <asm/isa.h>
 #include <asm/starfire.h>
 #include <asm/smp.h>
+#include <asm/sections.h>
 
 spinlock_t mostek_lock = SPIN_LOCK_UNLOCKED;
 spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
@@ -449,7 +450,6 @@
 		return;
 
 	{
-		extern int _stext;
 		extern int rwlock_impl_begin, rwlock_impl_end;
 		extern int atomic_impl_begin, atomic_impl_end;
 		extern int __memcpy_begin, __memcpy_end;
@@ -468,7 +468,7 @@
 		     pc < (unsigned long) &__bitops_end))
 			pc = o7;
 
-		pc -= (unsigned long) &_stext;
+		pc -= (unsigned long) _stext;
 		pc >>= prof_shift;
 
 		if(pc >= prof_len)
diff -Nru a/arch/sparc64/lib/atomic.S b/arch/sparc64/lib/atomic.S
--- a/arch/sparc64/lib/atomic.S	Sat Jul 19 12:54:27 2003
+++ b/arch/sparc64/lib/atomic.S	Sat Jul 19 12:54:27 2003
@@ -33,4 +33,27 @@
 	 membar	#StoreLoad | #StoreStore
 	retl
 	 sub	%g7, %o0, %o0
+
+	.globl	__atomic64_add
+__atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
+	ldx	[%o1], %g5
+	add	%g5, %o0, %g7
+	casx	[%o1], %g5, %g7
+	cmp	%g5, %g7
+	bne,pn	%xcc, __atomic64_add
+	 membar	#StoreLoad | #StoreStore
+	retl
+	 add	%g7, %o0, %o0
+
+	.globl	__atomic64_sub
+__atomic64_sub: /* %o0 = increment, %o1 = atomic_ptr */
+	ldx	[%o1], %g5
+	sub	%g5, %o0, %g7
+	casx	[%o1], %g5, %g7
+	cmp	%g5, %g7
+	bne,pn	%xcc, __atomic64_sub
+	 membar	#StoreLoad | #StoreStore
+	retl
+	 sub	%g7, %o0, %o0
+
 atomic_impl_end:
diff -Nru a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
--- a/arch/sparc64/mm/fault.c	Sat Jul 19 12:54:29 2003
+++ b/arch/sparc64/mm/fault.c	Sat Jul 19 12:54:29 2003
@@ -26,6 +26,7 @@
 #include <asm/uaccess.h>
 #include <asm/asi.h>
 #include <asm/lsu.h>
+#include <asm/sections.h>
 
 #define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0]))
 
@@ -320,10 +321,9 @@
 
 	if (regs->tstate & TSTATE_PRIV) {
 		unsigned long tpc = regs->tpc;
-		extern unsigned int _etext;
 
 		/* Sanity check the PC. */
-		if ((tpc >= KERNBASE && tpc < (unsigned long) &_etext) ||
+		if ((tpc >= KERNBASE && tpc < (unsigned long) _etext) ||
 		    (tpc >= MODULES_VADDR && tpc < MODULES_END)) {
 			/* Valid, no problems... */
 		} else {
diff -Nru a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
--- a/arch/sparc64/mm/init.c	Sat Jul 19 12:54:24 2003
+++ b/arch/sparc64/mm/init.c	Sat Jul 19 12:54:24 2003
@@ -35,6 +35,7 @@
 #include <asm/starfire.h>
 #include <asm/tlb.h>
 #include <asm/spitfire.h>
+#include <asm/sections.h>
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
@@ -48,16 +49,14 @@
 unsigned long phys_base;
 unsigned long pfn_base;
 
-enum ultra_tlb_layout tlb_type = spitfire;
-
 /* get_new_mmu_context() uses "cache + 1".  */
 spinlock_t ctx_alloc_lock = SPIN_LOCK_UNLOCKED;
 unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1;
 #define CTX_BMAP_SLOTS (1UL << (CTX_VERSION_SHIFT - 6))
 unsigned long mmu_context_bmap[CTX_BMAP_SLOTS];
 
-/* References to section boundaries */
-extern char __init_begin, __init_end, _start, _end, etext, edata;
+/* References to special section boundaries */
+extern char  _start[], _end[];
 
 /* Initial ramdisk setup */
 extern unsigned int sparc_ramdisk_image;
@@ -1333,7 +1332,7 @@
 	 * image.  The kernel is hard mapped below PAGE_OFFSET in a
 	 * 4MB locked TLB translation.
 	 */
-	start_pfn  = PAGE_ALIGN((unsigned long) &_end) -
+	start_pfn  = PAGE_ALIGN((unsigned long) _end) -
 		((unsigned long) KERNBASE);
 
 	/* Adjust up to the physical address where the kernel begins. */
@@ -1349,7 +1348,7 @@
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* Now have to check initial ramdisk, so that bootmap does not overwrite it */
 	if (sparc_ramdisk_image) {
-		if (sparc_ramdisk_image >= (unsigned long)&_end - 2 * PAGE_SIZE)
+		if (sparc_ramdisk_image >= (unsigned long)_end - 2 * PAGE_SIZE)
 			sparc_ramdisk_image -= KERNBASE;
 		initrd_start = sparc_ramdisk_image + phys_base;
 		initrd_end = initrd_start + sparc_ramdisk_size;
@@ -1426,7 +1425,7 @@
 
 	set_bit(0, mmu_context_bmap);
 
-	real_end = (unsigned long)&_end;
+	real_end = (unsigned long)_end;
 	if ((real_end > ((unsigned long)KERNBASE + 0x400000)))
 		bigkernel = 1;
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -1718,7 +1717,7 @@
 	memset(sparc64_valid_addr_bitmap, 0, i << 3);
 
 	addr = PAGE_OFFSET + phys_base;
-	last = PAGE_ALIGN((unsigned long)&_end) -
+	last = PAGE_ALIGN((unsigned long)_end) -
 		((unsigned long) KERNBASE);
 	last += PAGE_OFFSET + phys_base;
 	while (addr < last) {
@@ -1745,11 +1744,11 @@
 	SetPageReserved(mem_map_zero);
 	clear_page(page_address(mem_map_zero));
 
-	codepages = (((unsigned long) &etext) - ((unsigned long)&_start));
+	codepages = (((unsigned long) _etext) - ((unsigned long) _start));
 	codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT;
-	datapages = (((unsigned long) &edata) - ((unsigned long)&etext));
+	datapages = (((unsigned long) _edata) - ((unsigned long) _etext));
 	datapages = PAGE_ALIGN(datapages) >> PAGE_SHIFT;
-	initpages = (((unsigned long) &__init_end) - ((unsigned long) &__init_begin));
+	initpages = (((unsigned long) __init_end) - ((unsigned long) __init_begin));
 	initpages = PAGE_ALIGN(initpages) >> PAGE_SHIFT;
 
 #ifndef CONFIG_SMP
@@ -1812,8 +1811,8 @@
 	/*
 	 * The init section is aligned to 8k in vmlinux.lds. Page align for >8k pagesizes.
 	 */
-	addr = PAGE_ALIGN((unsigned long)(&__init_begin));
-	initend = (unsigned long)(&__init_end) & PAGE_MASK;
+	addr = PAGE_ALIGN((unsigned long)(__init_begin));
+	initend = (unsigned long)(__init_end) & PAGE_MASK;
 	for (; addr < initend; addr += PAGE_SIZE) {
 		unsigned long page;
 		struct page *p;
diff -Nru a/arch/sparc64/prom/bootstr.c b/arch/sparc64/prom/bootstr.c
--- a/arch/sparc64/prom/bootstr.c	Sat Jul 19 12:54:23 2003
+++ b/arch/sparc64/prom/bootstr.c	Sat Jul 19 12:54:23 2003
@@ -15,16 +15,22 @@
  */
 
 #define BARG_LEN  256
-int bootstr_len = BARG_LEN;
-static int bootstr_valid = 0;
-static char bootstr_buf[BARG_LEN] = { 0 };
+struct {
+	int bootstr_len;
+	int bootstr_valid;
+	char bootstr_buf[BARG_LEN];
+} bootstr_info = {
+	.bootstr_len = BARG_LEN,
+};
 
 char * __init
 prom_getbootargs(void)
 {
 	/* This check saves us from a panic when bootfd patches args. */
-	if (bootstr_valid) return bootstr_buf;
-	prom_getstring(prom_chosen_node, "bootargs", bootstr_buf, BARG_LEN);
-	bootstr_valid = 1;
-	return bootstr_buf;
+	if (bootstr_info.bootstr_valid)
+		return bootstr_info.bootstr_buf;
+	prom_getstring(prom_chosen_node, "bootargs",
+		       bootstr_info.bootstr_buf, BARG_LEN);
+	bootstr_info.bootstr_valid = 1;
+	return bootstr_info.bootstr_buf;
 }
diff -Nru a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
--- a/arch/um/drivers/ubd_kern.c	Sat Jul 19 12:54:25 2003
+++ b/arch/um/drivers/ubd_kern.c	Sat Jul 19 12:54:25 2003
@@ -15,7 +15,6 @@
 
 #include "linux/config.h"
 #include "linux/module.h"
-#include "linux/blk.h"
 #include "linux/blkdev.h"
 #include "linux/hdreg.h"
 #include "linux/init.h"
diff -Nru a/arch/v850/Kconfig b/arch/v850/Kconfig
--- a/arch/v850/Kconfig	Sat Jul 19 12:54:25 2003
+++ b/arch/v850/Kconfig	Sat Jul 19 12:54:25 2003
@@ -48,20 +48,24 @@
    choice
 	  prompt "Platform"
 	  default GDB
+      config V850E_SIM
+      	     bool "GDB"
       config RTE_CB_MA1
       	     bool "RTE-V850E/MA1-CB"
       config RTE_CB_NB85E
       	     bool "RTE-V850E/NB85E-CB"
-      config V850E_SIM
-      	     bool "GDB"
+      config RTE_CB_ME2
+      	     bool "RTE-V850E/ME2-CB"
+      config V850E_AS85EP1
+      	     bool "AS85EP1"
       config V850E2_SIM85E2C
       	     bool "sim85e2c"
+      config V850E2_SIM85E2S
+      	     bool "sim85e2s"
       config V850E2_FPGA85E2C
       	     bool "NA85E2C-FPGA"
       config V850E2_ANNA
       	     bool "Anna"
-      config V850E_AS85EP1
-      	     bool "AS85EP1"
    endchoice
 
 
@@ -78,41 +82,32 @@
    	  bool
 	  depends RTE_CB_MA1
 	  default y
-   # Similarly for the RTE-V850E/MA1-CB - V850E/TEG
+   # Similarly for the RTE-V850E/NB85E-CB - V850E/TEG
    config V850E_TEG
    	  bool
 	  depends RTE_CB_NB85E
 	  default y
-
-   # NB85E processor core
-   config V850E_NB85E
+   # ... and the RTE-V850E/ME2-CB - V850E/ME2
+   config V850E_ME2
    	  bool
-	  depends V850E_MA1 || V850E_TEG
+	  depends RTE_CB_ME2
 	  default y
 
-   config V850E_MA1_HIGHRES_TIMER
-   	  bool "High resolution timer support"
-  	  depends V850E_MA1
-
 
-   #### V850E2 processor-specific config
+   #### sim85e2-specific config
 
-   # V850E2 processors
-   config V850E2
+   config V850E2_SIM85E2
    	  bool
-	  depends V850E2_SIM85E2C || V850E2_FPGA85E2C || V850E2_ANNA
+	  depends V850E2_SIM85E2C || V850E2_SIM85E2S
 	  default y
 
-   # Processors based on the NA85E2A core
-   config V850E2_NA85E2A
-   	  bool
-	  depends V850E2_ANNA
-	  default y
 
-   # Processors based on the NA85E2C core
-   config V850E2_NA85E2C
+   #### V850E2 processor-specific config
+
+   # V850E2 processors
+   config V850E2
    	  bool
-	  depends V850E2_SIM85E2C || V850E2_FPGA85E2C
+	  depends V850E2_SIM85E2 || V850E2_FPGA85E2C || V850E2_ANNA
 	  default y
 
 
@@ -121,7 +116,7 @@
    # Boards in the RTE-x-CB series
    config RTE_CB
    	  bool
-	  depends RTE_CB_MA1 || RTE_CB_NB85E
+	  depends RTE_CB_MA1 || RTE_CB_NB85E || RTE_CB_ME2
 	  default y
 
    config RTE_CB_MULTI
@@ -129,7 +124,7 @@
 	  # RTE_CB_NB85E can either have multi ROM support or not, but
 	  # other platforms (currently only RTE_CB_MA1) require it.
 	  prompt "Multi monitor ROM support" if RTE_CB_NB85E
-	  depends RTE_CB
+	  depends RTE_CB_MA1 || RTE_CB_NB85E
 	  default y
 
    config RTE_CB_MULTI_DBTRAP
@@ -156,14 +151,42 @@
    # The only PCI bus we support is on the RTE-MOTHER-A board
    config PCI
    	  bool
-	  default y if RTE_MB_A_PCI
+	  default RTE_MB_A_PCI
+
+
+   #### Some feature-specific configs
+
+   # Everything except for the GDB simulator uses the same interrupt controller
+   config V850E_INTC
+   	  bool
+	  default !V850E_SIM
+
+   # Everything except for the various simulators uses the "Timer D" unit
+   config V850E_TIMER_D
+   	  bool
+	  default !V850E_SIM && !V850E2_SIM85E2
+
+   # Cache control used on some v850e1 processors
+   config V850E_CACHE
+          bool
+	  default V850E_TEG || V850E_ME2
+
+   # Cache control used on v850e2 processors; I think this should
+   # actually apply to more, but currently only the SIM85E2S uses it
+   config V850E2_CACHE
+   	  bool
+	  default V850E2_SIM85E2S
+
+   config NO_CACHE
+   	  bool
+	  default !V850E_CACHE && !V850E2_CACHE
 
 
    #### Misc config
 
    config ROM_KERNEL
    	  bool "Kernel in ROM"
-	  depends V850E2_ANNA || (RTE_CB && !RTE_CB_MULTI)
+	  depends V850E2_ANNA || V850E_AS85EP1 || RTE_CB_ME2
 
    # Some platforms pre-zero memory, in which case the kernel doesn't need to
    config ZERO_BSS
@@ -177,9 +200,12 @@
    	  int
 	  default 8 if V850E2_SIM85E2C || V850E2_FPGA85E2C
 
+   config V850E_HIGHRES_TIMER
+   	  bool "High resolution timer support"
+	  depends V850E_TIMER_D
    config TIME_BOOTUP
    	  bool "Time bootup"
-	  depends V850E_MA1_HIGHRES_TIMER
+	  depends V850E_HIGHRES_TIMER
 
    config RESET_GUARD
    	  bool "Reset Guard"
@@ -241,6 +267,7 @@
 	default y
 
 config KCORE_ELF
+	bool
 	default y
 
 source "fs/Kconfig.binfmt"
diff -Nru a/arch/v850/kernel/Makefile b/arch/v850/kernel/Makefile
--- a/arch/v850/kernel/Makefile	Sat Jul 19 12:54:30 2003
+++ b/arch/v850/kernel/Makefile	Sat Jul 19 12:54:30 2003
@@ -15,24 +15,26 @@
 	 signal.o irq.o mach.o ptrace.o bug.o
 obj-$(CONFIG_MODULES)		+= module.o v850_ksyms.o
 # chip-specific code
-obj-$(CONFIG_V850E_NB85E)	+= nb85e_intc.o
-obj-$(CONFIG_V850E_MA1)		+= ma.o nb85e_utils.o nb85e_timer_d.o
-obj-$(CONFIG_V850E_TEG)		+= teg.o nb85e_utils.o nb85e_cache.o \
-				   nb85e_timer_d.o
-obj-$(CONFIG_V850E2_ANNA)	+= anna.o nb85e_intc.o nb85e_utils.o \
-				   nb85e_timer_d.o
-obj-$(CONFIG_V850E_AS85EP1)	+= as85ep1.o nb85e_intc.o nb85e_utils.o \
-				   nb85e_timer_d.o
+obj-$(CONFIG_V850E_MA1)		+= ma.o
+obj-$(CONFIG_V850E_ME2)		+= me2.o
+obj-$(CONFIG_V850E_TEG)		+= teg.o
+obj-$(CONFIG_V850E_AS85EP1)	+= as85ep1.o
+obj-$(CONFIG_V850E2_ANNA)	+= anna.o
 # platform-specific code
 obj-$(CONFIG_V850E_SIM)		+= sim.o simcons.o
-obj-$(CONFIG_V850E2_SIM85E2C)	+= sim85e2c.o nb85e_intc.o memcons.o
-obj-$(CONFIG_V850E2_FPGA85E2C)	+= fpga85e2c.o nb85e_intc.o memcons.o
+obj-$(CONFIG_V850E2_SIM85E2)	+= sim85e2.o memcons.o
+obj-$(CONFIG_V850E2_FPGA85E2C)	+= fpga85e2c.o memcons.o
 obj-$(CONFIG_RTE_CB)		+= rte_cb.o rte_cb_leds.o
 obj-$(CONFIG_RTE_CB_MA1)	+= rte_ma1_cb.o
+obj-$(CONFIG_RTE_CB_ME2)	+= rte_me2_cb.o
 obj-$(CONFIG_RTE_CB_NB85E)	+= rte_nb85e_cb.o
 obj-$(CONFIG_RTE_CB_MULTI)	+= rte_cb_multi.o
 obj-$(CONFIG_RTE_MB_A_PCI)	+= rte_mb_a_pci.o
 obj-$(CONFIG_RTE_GBUS_INT)	+= gbus_int.o
 # feature-specific code
-obj-$(CONFIG_V850E_MA1_HIGHRES_TIMER)	+= highres_timer.o
+obj-$(CONFIG_V850E_INTC)	+= v850e_intc.o
+obj-$(CONFIG_V850E_TIMER_D)	+= v850e_timer_d.o v850e_utils.o
+obj-$(CONFIG_V850E_CACHE)	+= v850e_cache.o
+obj-$(CONFIG_V850E2_CACHE)	+= v850e2_cache.o
+obj-$(CONFIG_V850E_HIGHRES_TIMER) += highres_timer.o
 obj-$(CONFIG_PROC_FS)		+= procfs.o
diff -Nru a/arch/v850/kernel/anna.c b/arch/v850/kernel/anna.c
--- a/arch/v850/kernel/anna.c	Sat Jul 19 12:54:25 2003
+++ b/arch/v850/kernel/anna.c	Sat Jul 19 12:54:25 2003
@@ -1,8 +1,8 @@
 /*
  * arch/v850/kernel/anna.c -- Anna V850E2 evaluation chip/board
  *
- *  Copyright (C) 2002  NEC Corporation
- *  Copyright (C) 2002  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2002,03  NEC Electronics Corporation
+ *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -21,8 +21,8 @@
 #include <asm/machdep.h>
 #include <asm/atomic.h>
 #include <asm/page.h>
-#include <asm/nb85e_timer_d.h>
-#include <asm/nb85e_uart.h>
+#include <asm/v850e_timer_d.h>
+#include <asm/v850e_uart.h>
 
 #include "mach.h"
 
@@ -41,32 +41,34 @@
 
 void __init mach_early_init (void)
 {
-	ANNA_ILBEN  = 0;
-	ANNA_CSC(0) = 0x402F;
-	ANNA_CSC(1) = 0x4000;
-	ANNA_BPC    = 0;
-	ANNA_BSC    = 0xAAAA;
-	ANNA_BEC    = 0;
-	ANNA_BHC    = 0xFFFF;	/* icache all memory, dcache all */
-	ANNA_BCT(0) = 0xB088;
-	ANNA_BCT(1) = 0x0008;
-	ANNA_DWC(0) = 0x0027;
-	ANNA_DWC(1) = 0;
-	ANNA_BCC    = 0x0006;
-	ANNA_ASC    = 0;
-	ANNA_LBS    = 0x0089;
-	ANNA_SCR3   = 0x21A9;
-	ANNA_RFS3   = 0x8121;
+	ANNA_ILBEN    = 0;
 
-	nb85e_intc_disable_irqs ();
+	V850E2_CSC(0) = 0x402F;
+	V850E2_CSC(1) = 0x4000;
+	V850E2_BPC    = 0;
+	V850E2_BSC    = 0xAAAA;
+	V850E2_BEC    = 0;
+
+#if 0
+	V850E2_BHC    = 0xFFFF;	/* icache all memory, dcache all */
+#else
+	V850E2_BHC    = 0;	/* cache no memory */
+#endif
+	V850E2_BCT(0) = 0xB088;
+	V850E2_BCT(1) = 0x0008;
+	V850E2_DWC(0) = 0x0027;
+	V850E2_DWC(1) = 0;
+	V850E2_BCC    = 0x0006;
+	V850E2_ASC    = 0;
+	V850E2_LBS    = 0x0089;
+	V850E2_SCR(3) = 0x21A9;
+	V850E2_RFS(3) = 0x8121;
+
+	v850e_intc_disable_irqs ();
 }
 
 void __init mach_setup (char **cmdline)
 {
-#ifdef CONFIG_V850E_NB85E_UART_CONSOLE
-	nb85e_uart_cons_init (1);
-#endif
-
 	ANNA_PORT_PM (LEDS_PORT) = 0;	/* Make all LED pins output pins.  */
 	mach_tick = anna_led_tick;
 }
@@ -95,12 +97,12 @@
 void __init mach_sched_init (struct irqaction *timer_action)
 {
 	/* Start hardware timer.  */
-	nb85e_timer_d_configure (0, HZ);
+	v850e_timer_d_configure (0, HZ);
 	/* Install timer interrupt handler.  */
 	setup_irq (IRQ_INTCMD(0), timer_action);
 }
 
-static struct nb85e_intc_irq_init irq_inits[] = {
+static struct v850e_intc_irq_init irq_inits[] = {
 	{ "IRQ", 0, 		NUM_MACH_IRQS,	1, 7 },
 	{ "PIN", IRQ_INTP(0),   IRQ_INTP_NUM,   1, 4 },
 	{ "CCC", IRQ_INTCCC(0),	IRQ_INTCCC_NUM, 1, 5 },
@@ -118,7 +120,7 @@
 
 void __init mach_init_irqs (void)
 {
-	nb85e_intc_init_irq_types (irq_inits, hw_itypes);
+	v850e_intc_init_irq_types (irq_inits, hw_itypes);
 }
 
 void machine_restart (char *__unused)
diff -Nru a/arch/v850/kernel/as85ep1.c b/arch/v850/kernel/as85ep1.c
--- a/arch/v850/kernel/as85ep1.c	Sat Jul 19 12:54:29 2003
+++ b/arch/v850/kernel/as85ep1.c	Sat Jul 19 12:54:29 2003
@@ -1,8 +1,8 @@
 /*
  * arch/v850/kernel/as85ep1.c -- AS85EP1 V850E evaluation chip/board
  *
- *  Copyright (C) 2002  NEC Corporation
- *  Copyright (C) 2002  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2002,03  NEC Electronics Corporation
+ *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -21,8 +21,8 @@
 #include <asm/machdep.h>
 #include <asm/atomic.h>
 #include <asm/page.h>
-#include <asm/nb85e_timer_d.h>
-#include <asm/nb85e_uart.h>
+#include <asm/v850e_timer_d.h>
+#include <asm/v850e_uart.h>
 
 #include "mach.h"
 
@@ -90,20 +90,14 @@
 	AS85EP1_IRAMM = 0x0;	/* $BFbB"L?Na(BRAM$B$O!V(Bread-mode$B!W$K$J$j$^$9(B */
 #endif /* !CONFIG_ROM_KERNEL */
 
-	nb85e_intc_disable_irqs ();
+	v850e_intc_disable_irqs ();
 }
 
 void __init mach_setup (char **cmdline)
 {
-#ifdef CONFIG_V850E_NB85E_UART_CONSOLE
-	nb85e_uart_cons_init (1);
-#endif
-
 	AS85EP1_PORT_PMC (LEDS_PORT) = 0; /* Make the LEDs port an I/O port. */
 	AS85EP1_PORT_PM (LEDS_PORT) = 0; /* Make all the bits output pins.  */
 	mach_tick = as85ep1_led_tick;
-
-	ROOT_DEV = MKDEV (BLKMEM_MAJOR, 0);
 }
 
 void __init mach_get_physical_ram (unsigned long *ram_start,
@@ -137,21 +131,21 @@
 				 root_fs_image_end - root_fs_image_start);
 }
 
-void mach_gettimeofday (struct timeval *tv)
+void mach_gettimeofday (struct timespec *tv)
 {
 	tv->tv_sec = 0;
-	tv->tv_usec = 0;
+	tv->tv_nsec = 0;
 }
 
 void __init mach_sched_init (struct irqaction *timer_action)
 {
 	/* Start hardware timer.  */
-	nb85e_timer_d_configure (0, HZ);
+	v850e_timer_d_configure (0, HZ);
 	/* Install timer interrupt handler.  */
 	setup_irq (IRQ_INTCMD(0), timer_action);
 }
 
-static struct nb85e_intc_irq_init irq_inits[] = {
+static struct v850e_intc_irq_init irq_inits[] = {
 	{ "IRQ", 0, 		NUM_MACH_IRQS,	1, 7 },
 	{ "CCC", IRQ_INTCCC(0),	IRQ_INTCCC_NUM, 1, 5 },
 	{ "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM,	1, 5 },
@@ -166,7 +160,7 @@
 
 void __init mach_init_irqs (void)
 {
-	nb85e_intc_init_irq_types (irq_inits, hw_itypes);
+	v850e_intc_init_irq_types (irq_inits, hw_itypes);
 }
 
 void machine_restart (char *__unused)
diff -Nru a/arch/v850/kernel/fpga85e2c.c b/arch/v850/kernel/fpga85e2c.c
--- a/arch/v850/kernel/fpga85e2c.c	Sat Jul 19 12:54:28 2003
+++ b/arch/v850/kernel/fpga85e2c.c	Sat Jul 19 12:54:28 2003
@@ -2,8 +2,8 @@
  * arch/v850/kernel/fpga85e2c.h -- Machine-dependent defs for
  *	FPGA implementation of V850E2/NA85E2C
  *
- *  Copyright (C) 2002  NEC Corporation
- *  Copyright (C) 2002  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2002,03  NEC Electronics Corporation
+ *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -46,7 +46,7 @@
 
 	/* Set bus sizes: CS0 32-bit, CS1 16-bit, CS7 8-bit,
 	   everything else 32-bit.  */
-	BSC = 0x2AA6;
+	V850E2_BSC = 0x2AA6;
 	for (i = 2; i <= 6; i++)
 		CSDEV(i) = 0;	/* 32 bit */
 
@@ -134,7 +134,7 @@
 
 /* Interrupts */
 
-struct nb85e_intc_irq_init irq_inits[] = {
+struct v850e_intc_irq_init irq_inits[] = {
 	{ "IRQ", 0, 		NUM_MACH_IRQS,	1, 7 },
 	{ "RPU", IRQ_RPU(0),	IRQ_RPU_NUM,	1, 6 },
 	{ 0 }
@@ -146,7 +146,7 @@
 /* Initialize interrupts.  */
 void __init mach_init_irqs (void)
 {
-	nb85e_intc_init_irq_types (irq_inits, hw_itypes);
+	v850e_intc_init_irq_types (irq_inits, hw_itypes);
 }
 
 
diff -Nru a/arch/v850/kernel/gbus_int.c b/arch/v850/kernel/gbus_int.c
--- a/arch/v850/kernel/gbus_int.c	Sat Jul 19 12:54:30 2003
+++ b/arch/v850/kernel/gbus_int.c	Sat Jul 19 12:54:30 2003
@@ -113,9 +113,7 @@
 		/* Only pay attention to enabled interrupts.  */
 		status &= enable;
 		if (status) {
-			unsigned base_irq
-				= IRQ_GBUS_INT (w * GBUS_INT_BITS_PER_WORD);
-			irq = base_irq;
+			irq = IRQ_GBUS_INT (w * GBUS_INT_BITS_PER_WORD);
 			do {
 				/* There's an active interrupt in word
 				   W, find out which one, and call its
@@ -247,7 +245,7 @@
 	/* First initialize the shared gint interrupts.  */
 	for (i = 0; i < NUM_USED_GINTS; i++) {
 		unsigned gint = used_gint[i].gint;
-		struct nb85e_intc_irq_init gint_irq_init[2];
+		struct v850e_intc_irq_init gint_irq_init[2];
 
 		/* We initialize one GINT interrupt at a time.  */
 		gint_irq_init[0].name = "GINT";
@@ -258,7 +256,7 @@
 
 		gint_irq_init[1].name = 0; /* Terminate the vector.  */
 
-		nb85e_intc_init_irq_types (gint_irq_init, gint_hw_itypes);
+		v850e_intc_init_irq_types (gint_irq_init, gint_hw_itypes);
 	}
 
 	/* Then the GBUS interrupts.  */
diff -Nru a/arch/v850/kernel/head.S b/arch/v850/kernel/head.S
--- a/arch/v850/kernel/head.S	Sat Jul 19 12:54:23 2003
+++ b/arch/v850/kernel/head.S	Sat Jul 19 12:54:23 2003
@@ -1,8 +1,8 @@
 /*
  * arch/v850/kernel/head.S -- Lowest-level startup code
  *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -115,7 +115,14 @@
 	jarl	CSYM(memset), lp
 #endif
 
-	// Start Linux kernel.
+	// What happens if the main kernel function returns (it shouldn't)
 	mov	hilo(CSYM(machine_halt)), lp
-	jr	CSYM(start_kernel)
+
+	// Start the linux kernel.  We use an indirect jump to get extra
+	// range, because on some platforms this initial startup code
+	// (and the associated platform-specific code in mach_early_init)
+	// are located far away from the main kernel, e.g. so that they
+	// can initialize RAM first and copy the kernel or something.
+	mov	hilo(CSYM(start_kernel)), r12
+	jmp	[r12]
 C_END(start)
diff -Nru a/arch/v850/kernel/highres_timer.c b/arch/v850/kernel/highres_timer.c
--- a/arch/v850/kernel/highres_timer.c	Sat Jul 19 12:54:30 2003
+++ b/arch/v850/kernel/highres_timer.c	Sat Jul 19 12:54:30 2003
@@ -1,8 +1,8 @@
 /*
  * arch/v850/kernel/highres_timer.c -- High resolution timing routines
  *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -12,7 +12,7 @@
  */
 
 #include <asm/system.h>
-#include <asm/nb85e_timer_d.h>
+#include <asm/v850e_timer_d.h>
 #include <asm/highres_timer.h>
 
 #define HIGHRES_TIMER_USEC_SHIFT   12
@@ -42,7 +42,7 @@
 
 void highres_timer_reset (void)
 {
-	NB85E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT) = 0;
+	V850E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT) = 0;
 	HIGHRES_TIMER_SLOW_TICKS = 0;
 }
 
@@ -51,12 +51,12 @@
 	u32 fast_tick_rate;
 
 	/* Start hardware timer.  */
-	nb85e_timer_d_configure (HIGHRES_TIMER_TIMER_D_UNIT,
+	v850e_timer_d_configure (HIGHRES_TIMER_TIMER_D_UNIT,
 				 HIGHRES_TIMER_SLOW_TICK_RATE);
 
 	fast_tick_rate =
-		(NB85E_TIMER_D_BASE_FREQ
-		 >> NB85E_TIMER_D_DIVLOG2 (HIGHRES_TIMER_TIMER_D_UNIT));
+		(V850E_TIMER_D_BASE_FREQ
+		 >> V850E_TIMER_D_DIVLOG2 (HIGHRES_TIMER_TIMER_D_UNIT));
 
 	/* The obvious way of calculating microseconds from fast ticks
 	   is to do:
@@ -77,16 +77,16 @@
 
 	/* Enable the interrupt (which is hardwired to this use), and
 	   give it the highest priority.  */
-	NB85E_INTC_IC (IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT)) = 0;
+	V850E_INTC_IC (IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT)) = 0;
 }
 
 void highres_timer_stop (void)
 {
 	/* Stop the timer.  */
-	NB85E_TIMER_D_TMCD (HIGHRES_TIMER_TIMER_D_UNIT) =
-		NB85E_TIMER_D_TMCD_CAE;
+	V850E_TIMER_D_TMCD (HIGHRES_TIMER_TIMER_D_UNIT) =
+		V850E_TIMER_D_TMCD_CAE;
 	/* Disable its interrupt, just in case.  */
-	nb85e_intc_disable_irq (IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT));
+	v850e_intc_disable_irq (IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT));
 }
 
 inline void highres_timer_read_ticks (u32 *slow_ticks, u32 *fast_ticks)
@@ -95,9 +95,9 @@
 	u32 fast_ticks_1, fast_ticks_2, _slow_ticks;
 
 	local_irq_save (flags);
-	fast_ticks_1 = NB85E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT);
+	fast_ticks_1 = V850E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT);
 	_slow_ticks = HIGHRES_TIMER_SLOW_TICKS;
-	fast_ticks_2 = NB85E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT);
+	fast_ticks_2 = V850E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT);
 	local_irq_restore (flags);
 
 	if (fast_ticks_2 < fast_ticks_1)
diff -Nru a/arch/v850/kernel/intv.S b/arch/v850/kernel/intv.S
--- a/arch/v850/kernel/intv.S	Sat Jul 19 12:54:25 2003
+++ b/arch/v850/kernel/intv.S	Sat Jul 19 12:54:25 2003
@@ -16,7 +16,7 @@
 #include <asm/machdep.h>
 #include <asm/entry.h>
 
-#ifdef CONFIG_V850E_MA1_HIGHRES_TIMER
+#ifdef CONFIG_V850E_HIGHRES_TIMER
 #include <asm/highres_timer.h>
 #endif
 
@@ -59,7 +59,7 @@
 	.section	.intv.mach, "ax"
 	.org	0x0
 
-#if defined (CONFIG_V850E_MA1_HIGHRES_TIMER) && defined (IRQ_INTCMD)
+#if defined (CONFIG_V850E_HIGHRES_TIMER) && defined (IRQ_INTCMD)
 
 	/* Interrupts before the highres timer interrupt.  */
 	.rept	IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT)
diff -Nru a/arch/v850/kernel/ma.c b/arch/v850/kernel/ma.c
--- a/arch/v850/kernel/ma.c	Sat Jul 19 12:54:23 2003
+++ b/arch/v850/kernel/ma.c	Sat Jul 19 12:54:23 2003
@@ -22,19 +22,19 @@
 #include <asm/atomic.h>
 #include <asm/page.h>
 #include <asm/machdep.h>
-#include <asm/nb85e_timer_d.h>
+#include <asm/v850e_timer_d.h>
 
 #include "mach.h"
 
 void __init mach_sched_init (struct irqaction *timer_action)
 {
 	/* Start hardware timer.  */
-	nb85e_timer_d_configure (0, HZ);
+	v850e_timer_d_configure (0, HZ);
 	/* Install timer interrupt handler.  */
 	setup_irq (IRQ_INTCMD(0), timer_action);
 }
 
-static struct nb85e_intc_irq_init irq_inits[] = {
+static struct v850e_intc_irq_init irq_inits[] = {
 	{ "IRQ", 0, 		NUM_MACH_IRQS,	1, 7 },
 	{ "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM,	1, 5 },
 	{ "DMA", IRQ_INTDMA(0), IRQ_INTDMA_NUM,	1, 2 },
@@ -51,7 +51,7 @@
 /* Initialize MA chip interrupts.  */
 void __init ma_init_irqs (void)
 {
-	nb85e_intc_init_irq_types (irq_inits, hw_itypes);
+	v850e_intc_init_irq_types (irq_inits, hw_itypes);
 }
 
 /* Called before configuring an on-chip UART.  */
diff -Nru a/arch/v850/kernel/me2.c b/arch/v850/kernel/me2.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/v850/kernel/me2.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,74 @@
+/*
+ * arch/v850/kernel/me2.c -- V850E/ME2 chip-specific support
+ *
+ *  Copyright (C) 2003  NEC Corporation
+ *  Copyright (C) 2003  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+
+#include <asm/atomic.h>
+#include <asm/page.h>
+#include <asm/machdep.h>
+#include <asm/v850e_timer_d.h>
+
+#include "mach.h"
+
+void __init mach_sched_init (struct irqaction *timer_action)
+{
+	/* Start hardware timer.  */
+	v850e_timer_d_configure (0, HZ);
+	/* Install timer interrupt handler.  */
+	setup_irq (IRQ_INTCMD(0), timer_action);
+}
+
+static struct v850e_intc_irq_init irq_inits[] = {
+	{ "IRQ",    0,                NUM_CPU_IRQS,      1, 7 },
+	{ "INTP",   IRQ_INTP(0),      IRQ_INTP_NUM,      1, 5 },
+	{ "CMD",    IRQ_INTCMD(0),    IRQ_INTCMD_NUM,    1, 3 },
+	{ "UBTIRE", IRQ_INTUBTIRE(0), IRQ_INTUBTIRE_NUM, 5, 4 },
+	{ "UBTIR",  IRQ_INTUBTIR(0),  IRQ_INTUBTIR_NUM,  5, 4 },
+	{ "UBTIT",  IRQ_INTUBTIT(0),  IRQ_INTUBTIT_NUM,  5, 4 },
+	{ "UBTIF",  IRQ_INTUBTIF(0),  IRQ_INTUBTIF_NUM,  5, 4 },
+	{ "UBTITO", IRQ_INTUBTITO(0), IRQ_INTUBTITO_NUM, 5, 4 },
+	{ 0 }
+};
+#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1)
+
+static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS];
+
+/* Initialize V850E/ME2 chip interrupts.  */
+void __init me2_init_irqs (void)
+{
+	v850e_intc_init_irq_types (irq_inits, hw_itypes);
+}
+
+/* Called before configuring an on-chip UART.  */
+void me2_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud)
+{
+	if (chan == 0) {
+		/* Specify that the relevent pins on the chip should do
+		   serial I/O, not direct I/O.  */
+		ME2_PORT1_PMC |= 0xC;
+		/* Specify that we're using the UART, not the CSI device. */
+		ME2_PORT1_PFC |= 0xC;
+	} else if (chan == 1) {
+		/* Specify that the relevent pins on the chip should do
+		   serial I/O, not direct I/O.  */
+		ME2_PORT2_PMC |= 0x6;
+		/* Specify that we're using the UART, not the CSI device. */
+		ME2_PORT2_PFC |= 0x6;
+	}
+}
diff -Nru a/arch/v850/kernel/nb85e_cache.c b/arch/v850/kernel/nb85e_cache.c
--- a/arch/v850/kernel/nb85e_cache.c	Sat Jul 19 12:54:26 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,178 +0,0 @@
-/*
- * arch/v850/kernel/nb85e_cache.c -- Cache control for NB85E_CACHE212 and
- * 	NB85E_CACHE213 cache memories
- *
- *  Copyright (C) 2003  NEC Electronics Corporation
- *  Copyright (C) 2003  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <asm/entry.h>
-#include <asm/nb85e_cache.h>
-
-#define WAIT_UNTIL_CLEAR(value) while (value) {}
-
-/* Set caching params via the BHC and DCC registers.  */
-void nb85e_cache_enable (u16 bhc, u16 dcc)
-{
-	unsigned long *r0_ram = (unsigned long *)R0_RAM_ADDR;
-	register u16 bhc_val asm ("r6") = bhc;
-
-	/* Configure data-cache.  */
-	NB85E_CACHE_DCC = dcc;
-
-	/* Configure caching for various memory regions by writing the BHC
-	   register.  The documentation says that an instruction _cannot_
-	   enable/disable caching for the memory region in which the
-	   instruction itself exists; to work around this, we store
-	   appropriate instructions into the on-chip RAM area (which is never
-	   cached), and briefly jump there to do the work.  */
-	r0_ram[0] = 0xf0720760;	/* st.h r0, 0xfffff072[r0] */
-	r0_ram[1] = 0xf06a3760;	/* st.h r6, 0xfffff06a[r0] */
-	r0_ram[2] = 0x5640006b;	/* jmp [r11] */
-	asm ("mov hilo(1f), r11; jmp [%1]; 1:;"
-	     :: "r" (bhc_val), "r" (R0_RAM_ADDR) : "r11");
-}
-
-static void clear_icache (void)
-{
-	/* 1. Read the instruction cache control register (ICC) and confirm
-	      that bits 0 and 1 (TCLR0, TCLR1) are all cleared.  */
-	WAIT_UNTIL_CLEAR (NB85E_CACHE_ICC & 0x3);
-
-	/* 2. Read the ICC register and confirm that bit 12 (LOCK0) is
-  	      cleared.  Bit 13 of the ICC register is always cleared.  */
-	WAIT_UNTIL_CLEAR (NB85E_CACHE_ICC & 0x1000);
-
-	/* 3. Set the TCLR0 and TCLR1 bits of the ICC register as follows,
-	      when clearing way 0 and way 1 at the same time:
-	        (a) Set the TCLR0 and TCLR1 bits.
-		(b) Read the TCLR0 and TCLR1 bits to confirm that these bits
-		    are cleared.
-		(c) Perform (a) and (b) above again.  */
-	NB85E_CACHE_ICC |= 0x3;
-	WAIT_UNTIL_CLEAR (NB85E_CACHE_ICC & 0x3);
-	/* Do it again.  */
-	NB85E_CACHE_ICC |= 0x3;
-	WAIT_UNTIL_CLEAR (NB85E_CACHE_ICC & 0x3);
-}
-
-/* Flush or clear (or both) the data cache, depending on the value of FLAGS;
-   the procedure is the same for both, just the control bits used differ (and
-   both may be performed simultaneously).  */
-static void dcache_op (unsigned short flags)
-{
-	/* 1. Read the data cache control register (DCC) and confirm that bits
-	      0, 1, 4, and 5 (DC00, DC01, DC04, DC05) are all cleared.  */
-	WAIT_UNTIL_CLEAR (NB85E_CACHE_DCC & 0x33);
-
-	/* 2. Clear DCC register bit 12 (DC12), bit 13 (DC13), or both
-	      depending on the way for which tags are to be cleared.  */
-	NB85E_CACHE_DCC &= ~0xC000;
-
-	/* 3. Set DCC register bit 0 (DC00), bit 1 (DC01) or both depending on
-	      the way for which tags are to be cleared.
-	      ...
-	      Set DCC register bit 4 (DC04), bit 5 (DC05), or both depending
-	      on the way to be data flushed.  */
-	NB85E_CACHE_DCC |= flags;
-
-	/* 4. Read DCC register bit DC00, DC01 [DC04, DC05], or both depending
-	      on the way for which tags were cleared [flushed] and confirm
-	      that that bit is cleared.  */
-	WAIT_UNTIL_CLEAR (NB85E_CACHE_DCC & flags);
-}
-
-/* Flushes the contents of the dcache to memory.  */
-static inline void flush_dcache (void)
-{
-	/* We only need to do something if in write-back mode.  */
-	if (NB85E_CACHE_DCC & 0x0400)
-		dcache_op (0x30);
-}
-
-/* Flushes the contents of the dcache to memory, and then clears it.  */
-static inline void clear_dcache (void)
-{
-	/* We only need to do something if the dcache is enabled.  */
-	if (NB85E_CACHE_DCC & 0x0C00)
-		dcache_op (0x33);
-}
-
-/* Clears the dcache without flushing to memory first.  */
-static inline void clear_dcache_no_flush (void)
-{
-	/* We only need to do something if the dcache is enabled.  */
-	if (NB85E_CACHE_DCC & 0x0C00)
-		dcache_op (0x3);
-}
-
-static inline void cache_exec_after_store (void)
-{
-	flush_dcache ();
-	clear_icache ();
-}
-
-
-/* Exported functions.  */
-
-void inline nb85e_cache_flush_all (void)
-{
-	clear_icache ();
-	clear_dcache ();
-}
-
-void nb85e_cache_flush_mm (struct mm_struct *mm)
-{
-	/* nothing */
-}
-
-void nb85e_cache_flush_range (struct mm_struct *mm,
-			      unsigned long start, unsigned long end)
-{
-	/* nothing */
-}
-
-void nb85e_cache_flush_page (struct vm_area_struct *vma,
-			     unsigned long page_addr)
-{
-	/* nothing */
-}
-
-void nb85e_cache_flush_dcache_page (struct page *page)
-{
-	/* nothing */
-}
-
-void nb85e_cache_flush_icache (void)
-{
-	cache_exec_after_store ();
-}
-
-void nb85e_cache_flush_icache_range (unsigned long start, unsigned long end)
-{
-	cache_exec_after_store ();
-}
-
-void nb85e_cache_flush_icache_page (struct vm_area_struct *vma,
-				    struct page *page)
-{
-	cache_exec_after_store ();
-}
-
-void nb85e_cache_flush_icache_user_range (struct vm_area_struct *vma,
-					  struct page *page,
-					  unsigned long adr, int len)
-{
-	cache_exec_after_store ();
-}
-
-void nb85e_cache_flush_sigtramp (unsigned long addr)
-{
-	cache_exec_after_store ();
-}
diff -Nru a/arch/v850/kernel/nb85e_intc.c b/arch/v850/kernel/nb85e_intc.c
--- a/arch/v850/kernel/nb85e_intc.c	Sat Jul 19 12:54:24 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,104 +0,0 @@
-/*
- * arch/v850/kernel/nb85e_intc.c -- NB85E cpu core interrupt controller (INTC)
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/nb85e_intc.h>
-
-static void irq_nop (unsigned irq) { }
-
-static unsigned nb85e_intc_irq_startup (unsigned irq)
-{
-	nb85e_intc_clear_pending_irq (irq);
-	nb85e_intc_enable_irq (irq);
-	return 0;
-}
-
-static void nb85e_intc_end_irq (unsigned irq)
-{
-	unsigned long psw, temp;
-
-	/* Clear the highest-level bit in the In-service priority register
-	   (ISPR), to allow this interrupt (or another of the same or
-	   lesser priority) to happen again.
-
-	   The `reti' instruction normally does this automatically when the
-	   PSW bits EP and NP are zero, but we can't always rely on reti
-	   being used consistently to return after an interrupt (another
-	   process can be scheduled, for instance, which can delay the
-	   associated reti for a long time, or this process may be being
-	   single-stepped, which uses the `dbret' instruction to return
-	   from the kernel).
-
-	   We also set the PSW EP bit, which prevents reti from also
-	   trying to modify the ISPR itself.  */
-
-	/* Get PSW and disable interrupts.  */
-	asm volatile ("stsr psw, %0; di" : "=r" (psw));
-	/* We don't want to do anything for NMIs (they don't use the ISPR).  */
-	if (! (psw & 0xC0)) {
-		/* Transition to `trap' state, so that an eventual real
-		   reti instruction won't modify the ISPR.  */
-		psw |= 0x40;
-		/* Fake an interrupt return, which automatically clears the
-		   appropriate bit in the ISPR.  */
-		asm volatile ("mov hilo(1f), %0;"
-			      "ldsr %0, eipc; ldsr %1, eipsw;"
-			      "reti;"
-			      "1:"
-			      : "=&r" (temp) : "r" (psw));
-	}
-}
-
-/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
-   INITS (which is terminated by an entry with the name field == 0).  */
-void __init nb85e_intc_init_irq_types (struct nb85e_intc_irq_init *inits,
-				       struct hw_interrupt_type *hw_irq_types)
-{
-	struct nb85e_intc_irq_init *init;
-	for (init = inits; init->name; init++) {
-		unsigned i;
-		struct hw_interrupt_type *hwit = hw_irq_types++;
-
-		hwit->typename = init->name;
-
-		hwit->startup  = nb85e_intc_irq_startup;
-		hwit->shutdown = nb85e_intc_disable_irq;
-		hwit->enable   = nb85e_intc_enable_irq;
-		hwit->disable  = nb85e_intc_disable_irq;
-		hwit->ack      = irq_nop;
-		hwit->end      = nb85e_intc_end_irq;
-		
-		/* Initialize kernel IRQ infrastructure for this interrupt.  */
-		init_irq_handlers(init->base, init->num, init->interval, hwit);
-
-		/* Set the interrupt priorities.  */
-		for (i = 0; i < init->num; i++) {
-			unsigned irq = init->base + i * init->interval;
-
-			/* If the interrupt is currently enabled (all
-			   interrupts are initially disabled), then
-			   assume whoever enabled it has set things up
-			   properly, and avoid messing with it.  */
-			if (! nb85e_intc_irq_enabled (irq))
-				/* This write also (1) disables the
-				   interrupt, and (2) clears any pending
-				   interrupts.  */
-				NB85E_INTC_IC (irq)
-					= (NB85E_INTC_IC_PR (init->priority)
-					   | NB85E_INTC_IC_MK);
-		}
-	}
-}
diff -Nru a/arch/v850/kernel/nb85e_timer_d.c b/arch/v850/kernel/nb85e_timer_d.c
--- a/arch/v850/kernel/nb85e_timer_d.c	Sat Jul 19 12:54:25 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,54 +0,0 @@
-/*
- * include/asm-v850/nb85e_timer_d.c -- `Timer D' component often used
- *	with the NB85E cpu core
- *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-
-#include <asm/nb85e_utils.h>
-#include <asm/nb85e_timer_d.h>
-
-/* Start interval timer TIMER (0-3).  The timer will issue the
-   corresponding INTCMD interrupt RATE times per second.
-   This function does not enable the interrupt.  */
-void nb85e_timer_d_configure (unsigned timer, unsigned rate)
-{
-	unsigned divlog2, count;
-
-	/* Calculate params for timer.  */
-	if (! calc_counter_params (
-		    NB85E_TIMER_D_BASE_FREQ, rate,
-		    NB85E_TIMER_D_TMCD_CS_MIN, NB85E_TIMER_D_TMCD_CS_MAX, 16,
-		    &divlog2, &count))
-		printk (KERN_WARNING
-			"Cannot find interval timer %d setting suitable"
-			" for rate of %dHz.\n"
-			"Using rate of %dHz instead.\n",
-			timer, rate,
-			(NB85E_TIMER_D_BASE_FREQ >> divlog2) >> 16);
-
-	/* Do the actual hardware timer initialization:  */
-
-	/* Enable timer.  */
-	NB85E_TIMER_D_TMCD(timer) = NB85E_TIMER_D_TMCD_CAE;
-	/* Set clock divider.  */
-	NB85E_TIMER_D_TMCD(timer)
-		= NB85E_TIMER_D_TMCD_CAE
-		| NB85E_TIMER_D_TMCD_CS(divlog2);
-	/* Set timer compare register.  */
-	NB85E_TIMER_D_CMD(timer) = count;
-	/* Start counting.  */
-	NB85E_TIMER_D_TMCD(timer)
-		= NB85E_TIMER_D_TMCD_CAE
-		| NB85E_TIMER_D_TMCD_CS(divlog2)
-		| NB85E_TIMER_D_TMCD_CE;
-}
diff -Nru a/arch/v850/kernel/nb85e_utils.c b/arch/v850/kernel/nb85e_utils.c
--- a/arch/v850/kernel/nb85e_utils.c	Sat Jul 19 12:54:23 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,65 +0,0 @@
-/*
- * include/asm-v850/nb85e_utils.h -- Utility functions associated with
- *	the NB85E cpu core
- *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-/* Note: these functions are often associated with the N85E cpu core,
-   but not always, which is why they're not in `nb85e.c'.  */
-
-#include <asm/nb85e_utils.h>
-
-/* Calculate counter clock-divider and count values to attain the
-   desired frequency RATE from the base frequency BASE_FREQ.  The
-   counter is expected to have a clock-divider, which can divide the
-   system cpu clock by a power of two value from MIN_DIVLOG2 to
-   MAX_DIV_LOG2, and a word-size of COUNTER_SIZE bits (the counter
-   counts up and resets whenever it's equal to the compare register,
-   generating an interrupt or whatever when it does so).  The returned
-   values are: *DIVLOG2 -- log2 of the desired clock divider and *COUNT
-   -- the counter compare value to use.  Returns true if it was possible
-   to find a reasonable value, otherwise false (and the other return
-   values will be set to be as good as possible).  */
-int calc_counter_params (unsigned long base_freq,
-			 unsigned long rate,
-			 unsigned min_divlog2, unsigned max_divlog2,
-			 unsigned counter_size,
-			 unsigned *divlog2, unsigned *count)
-{
-	unsigned _divlog2;
-	int ok = 0;
-
-	/* Find the lowest clock divider setting that can represent RATE.  */
-	for (_divlog2 = min_divlog2; _divlog2 <= max_divlog2; _divlog2++) {
-		/* Minimum interrupt rate possible using this divider.  */
-		unsigned min_int_rate
-			= (base_freq >> _divlog2) >> counter_size;
-
-		if (min_int_rate <= rate) {
-			/* This setting is the highest resolution
-			   setting that's slow enough enough to attain
-			   RATE interrupts per second, so use it.  */
-			ok = 1;
-			break;
-		}
-	}
-
-	if (_divlog2 > max_divlog2)
-		/* Can't find correct setting.  */
-		_divlog2 = max_divlog2;
-
-	if (divlog2)
-		*divlog2 = _divlog2;
-	if (count)
-		*count = ((base_freq >> _divlog2) + rate/2) / rate;
-
-	return ok;
-}
diff -Nru a/arch/v850/kernel/rte_cb.c b/arch/v850/kernel/rte_cb.c
--- a/arch/v850/kernel/rte_cb.c	Sat Jul 19 12:54:22 2003
+++ b/arch/v850/kernel/rte_cb.c	Sat Jul 19 12:54:22 2003
@@ -17,7 +17,7 @@
 #include <linux/fs.h>
 
 #include <asm/machdep.h>
-#include <asm/nb85e_uart.h>
+#include <asm/v850e_uart.h>
 
 #include "mach.h"
 
@@ -34,7 +34,7 @@
 
 void __init rte_cb_early_init (void)
 {
-	nb85e_intc_disable_irqs ();
+	v850e_intc_disable_irqs ();
 
 #ifdef CONFIG_RTE_CB_MULTI
 	multi_init ();
@@ -43,6 +43,7 @@
 
 void __init mach_setup (char **cmdline)
 {
+#ifdef CONFIG_RTE_MB_A_PCI
 	/* Probe for Mother-A, and print a message if we find it.  */
 	*(volatile unsigned long *)MB_A_SRAM_ADDR = 0xDEADBEEF;
 	if (*(volatile unsigned long *)MB_A_SRAM_ADDR == 0xDEADBEEF) {
@@ -52,23 +53,11 @@
 				"          NEC SolutionGear/Midas lab"
 				" RTE-MOTHER-A motherboard\n");
 	}
-
-#if defined (CONFIG_V850E_NB85E_UART_CONSOLE) && !defined (CONFIG_TIME_BOOTUP)
-	nb85e_uart_cons_init (0);
-#endif
+#endif /* CONFIG_RTE_MB_A_PCI */
 
 	mach_tick = led_tick;
 }
 
-#ifdef CONFIG_TIME_BOOTUP
-void initial_boot_done (void)
-{
-#ifdef CONFIG_V850E_NB85E_UART_CONSOLE
-	nb85e_uart_cons_init (0);
-#endif
-}
-#endif
-
 void machine_restart (char *__unused)
 {
 #ifdef CONFIG_RESET_GUARD
@@ -193,6 +182,7 @@
 static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS];
 
 #endif /* CONFIG_RTE_GBUS_INT */
+
 
 void __init rte_cb_init_irqs (void)
 {
diff -Nru a/arch/v850/kernel/rte_ma1_cb.c b/arch/v850/kernel/rte_ma1_cb.c
--- a/arch/v850/kernel/rte_ma1_cb.c	Sat Jul 19 12:54:27 2003
+++ b/arch/v850/kernel/rte_ma1_cb.c	Sat Jul 19 12:54:27 2003
@@ -20,7 +20,7 @@
 #include <asm/page.h>
 #include <asm/ma1.h>
 #include <asm/rte_ma1_cb.h>
-#include <asm/nb85e_timer_c.h>
+#include <asm/v850e_timer_c.h>
 
 #include "mach.h"
 
@@ -89,14 +89,14 @@
 	rte_cb_init_irqs ();
 
 	/* Use falling-edge-sensitivity for interrupts .  */
-	NB85E_TIMER_C_SESC (0) &= ~0xC;
-	NB85E_TIMER_C_SESC (1) &= ~0xF;
+	V850E_TIMER_C_SESC (0) &= ~0xC;
+	V850E_TIMER_C_SESC (1) &= ~0xF;
 
 	/* INTP000-INTP011 are shared with `Timer C', so we have to set
 	   up Timer C to pass them through as raw interrupts.  */
 	for (tc = 0; tc < 2; tc++)
 		/* Turn on the timer.  */
-		NB85E_TIMER_C_TMCC0 (tc) |= NB85E_TIMER_C_TMCC0_CAE;
+		V850E_TIMER_C_TMCC0 (tc) |= V850E_TIMER_C_TMCC0_CAE;
 
 	/* Make sure the relevant port0/port1 pins are assigned
 	   interrupt duty.  We used INTP001-INTP011 (don't screw with
diff -Nru a/arch/v850/kernel/rte_me2_cb.c b/arch/v850/kernel/rte_me2_cb.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/v850/kernel/rte_me2_cb.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,308 @@
+/*
+ * arch/v850/kernel/rte_me2_cb.c -- Midas labs RTE-V850E/ME2-CB board
+ *
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+#include <linux/fs.h>
+#include <linux/major.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+
+#include <asm/atomic.h>
+#include <asm/page.h>
+#include <asm/me2.h>
+#include <asm/rte_me2_cb.h>
+#include <asm/machdep.h>
+#include <asm/v850e_intc.h>
+#include <asm/v850e_cache.h>
+#include <asm/irq.h>
+
+#include "mach.h"
+
+extern unsigned long *_intv_start;
+extern unsigned long *_intv_end;
+
+/* LED access routines.  */
+extern unsigned read_leds (int pos, char *buf, int len);
+extern unsigned write_leds (int pos, const char *buf, int len);
+
+
+/* SDRAM are almost contiguous (with a small hole in between;
+   see mach_reserve_bootmem for details), so just use both as one big area.  */
+#define RAM_START 	SDRAM_ADDR
+#define RAM_END		(SDRAM_ADDR + SDRAM_SIZE)
+
+
+void __init mach_get_physical_ram (unsigned long *ram_start,
+				   unsigned long *ram_len)
+{
+	*ram_start = RAM_START;
+	*ram_len = RAM_END - RAM_START;
+}
+
+void __init mach_reserve_bootmem ()
+{
+	extern char _root_fs_image_start, _root_fs_image_end;
+	u32 root_fs_image_start = (u32)&_root_fs_image_start;
+	u32 root_fs_image_end = (u32)&_root_fs_image_end;
+
+	/* Reserve the memory used by the root filesystem image if it's
+	   in RAM.  */
+	if (root_fs_image_start >= RAM_START && root_fs_image_start < RAM_END)
+		reserve_bootmem (root_fs_image_start,
+				 root_fs_image_end - root_fs_image_start);
+}
+
+void mach_gettimeofday (struct timespec *tv)
+{
+	tv->tv_sec = 0;
+	tv->tv_nsec = 0;
+}
+
+/* Called before configuring an on-chip UART.  */
+void rte_me2_cb_uart_pre_configure (unsigned chan,
+				    unsigned cflags, unsigned baud)
+{
+	/* The RTE-V850E/ME2-CB connects some general-purpose I/O
+	   pins on the CPU to the RTS/CTS lines of UARTB channel 0's
+	   serial connection.
+	   I/O pins P21 and P22 are RTS and CTS respectively.  */
+	if (chan == 0) {
+		/* Put P21 & P22 in I/O port mode.  */
+		ME2_PORT2_PMC &= ~0x6;
+		/* Make P21 and output, and P22 an input.  */
+		ME2_PORT2_PM = (ME2_PORT2_PM & ~0xC) | 0x4;
+	}
+
+	me2_uart_pre_configure (chan, cflags, baud);
+}
+
+void __init mach_init_irqs (void)
+{
+	/* Initialize interrupts.  */
+	me2_init_irqs ();
+	rte_me2_cb_init_irqs ();
+}
+
+#ifdef CONFIG_ROM_KERNEL
+/* Initialization for kernel in ROM.  */
+static inline rom_kernel_init (void)
+{
+	/* If the kernel is in ROM, we have to copy any initialized data
+	   from ROM into RAM.  */
+	extern unsigned long _data_load_start, _sdata, _edata;
+	register unsigned long *src = &_data_load_start;
+	register unsigned long *dst = &_sdata, *end = &_edata;
+
+	while (dst != end)
+		*dst++ = *src++;
+}
+#endif /* CONFIG_ROM_KERNEL */
+
+static void install_interrupt_vectors (void)
+{
+	unsigned long *p1, *p2;
+
+	ME2_IRAMM = 0x03; /* V850E/ME2 iRAM write mode */
+
+	/* vector copy to iRAM */
+	p1 = (unsigned long *)0; /* v85x vector start */
+	p2 = (unsigned long *)&_intv_start;
+	while (p2 < (unsigned long *)&_intv_end)
+		*p1++ = *p2++;
+
+	ME2_IRAMM = 0x00; /* V850E/ME2 iRAM read mode */
+}
+
+/* CompactFlash */
+
+static void cf_power_on (void)
+{
+	/* CF card detected? */
+	if (CB_CF_STS0 & 0x0030)
+		return;
+
+	CB_CF_REG0 = 0x0002; /* reest on */
+	mdelay (10);
+	CB_CF_REG0 = 0x0003; /* power on */
+	mdelay (10);
+	CB_CF_REG0 = 0x0001; /* reset off */
+	mdelay (10);
+}
+
+static void cf_power_off (void)
+{
+	CB_CF_REG0 = 0x0003; /* power on */
+	mdelay (10);
+	CB_CF_REG0 = 0x0002; /* reest on */
+	mdelay (10);
+}
+
+void __init mach_early_init (void)
+{
+	install_interrupt_vectors ();
+
+	/* CS1 SDRAM instruction cache enable */
+	v850e_cache_enable (0x04, 0x03, 0);
+
+	rte_cb_early_init ();
+
+	/* CompactFlash power on */
+	cf_power_on ();
+
+#if defined (CONFIG_ROM_KERNEL)
+	rom_kernel_init ();
+#endif
+}
+
+
+/* RTE-V850E/ME2-CB Programmable Interrupt Controller.  */
+
+static struct cb_pic_irq_init cb_pic_irq_inits[] = {
+	{ "CB_EXTTM0",       IRQ_CB_EXTTM0,       1, 1, 6 },
+	{ "CB_EXTSIO",       IRQ_CB_EXTSIO,       1, 1, 6 },
+	{ "CB_TOVER",        IRQ_CB_TOVER,        1, 1, 6 },
+	{ "CB_GINT0",        IRQ_CB_GINT0,        1, 1, 6 },
+	{ "CB_USB",          IRQ_CB_USB,          1, 1, 6 },
+	{ "CB_LANC",         IRQ_CB_LANC,         1, 1, 6 },
+	{ "CB_USB_VBUS_ON",  IRQ_CB_USB_VBUS_ON,  1, 1, 6 },
+	{ "CB_USB_VBUS_OFF", IRQ_CB_USB_VBUS_OFF, 1, 1, 6 },
+	{ "CB_EXTTM1",       IRQ_CB_EXTTM1,       1, 1, 6 },
+	{ "CB_EXTTM2",       IRQ_CB_EXTTM2,       1, 1, 6 },
+	{ 0 }
+};
+#define NUM_CB_PIC_IRQ_INITS  \
+   ((sizeof cb_pic_irq_inits / sizeof cb_pic_irq_inits[0]) - 1)
+
+static struct hw_interrupt_type cb_pic_hw_itypes[NUM_CB_PIC_IRQ_INITS];
+static unsigned char cb_pic_active_irqs = 0;
+
+void __init rte_me2_cb_init_irqs (void)
+{
+	cb_pic_init_irq_types (cb_pic_irq_inits, cb_pic_hw_itypes);
+
+	/* Initalize on board PIC1 (not PIC0) enable */
+	CB_PIC_INT0M  = 0x0000;
+	CB_PIC_INT1M  = 0x0000;
+	CB_PIC_INTR   = 0x0000;
+	CB_PIC_INTEN |= CB_PIC_INT1EN;
+
+	ME2_PORT2_PMC 	 |= 0x08;	/* INTP23/SCK1 mode */
+	ME2_PORT2_PFC 	 &= ~0x08;	/* INTP23 mode */
+	ME2_INTR(2) 	 &= ~0x08;	/* INTP23 falling-edge detect */
+	ME2_INTF(2) 	 &= ~0x08;	/*   " */
+
+	rte_cb_init_irqs ();	/* gbus &c */
+}
+
+
+/* Enable interrupt handling for interrupt IRQ.  */
+void cb_pic_enable_irq (unsigned irq)
+{
+	CB_PIC_INT1M |= 1 << (irq - CB_PIC_BASE_IRQ);
+}
+
+void cb_pic_disable_irq (unsigned irq)
+{
+	CB_PIC_INT1M &= ~(1 << (irq - CB_PIC_BASE_IRQ));
+}
+
+void cb_pic_shutdown_irq (unsigned irq)
+{
+	cb_pic_disable_irq (irq);
+
+	if (--cb_pic_active_irqs == 0)
+		free_irq (IRQ_CB_PIC, 0);
+
+	CB_PIC_INT1M &= ~(1 << (irq - CB_PIC_BASE_IRQ));
+}
+
+static void cb_pic_handle_irq (int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned status = CB_PIC_INTR;
+	unsigned enable = CB_PIC_INT1M;
+
+	/* Only pay attention to enabled interrupts.  */
+	status &= enable;
+
+	CB_PIC_INTEN &= ~CB_PIC_INT1EN;
+
+	if (status) {
+		unsigned mask = 1;
+
+		irq = CB_PIC_BASE_IRQ;
+		do {
+			/* There's an active interrupt, find out which one,
+			   and call its handler.  */
+			while (! (status & mask)) {
+				irq++;
+				mask <<= 1;
+			}
+			status &= ~mask;
+
+			CB_PIC_INTR = mask;
+
+			/* Recursively call handle_irq to handle it. */
+			handle_irq (irq, regs);
+		} while (status);
+	}
+
+	CB_PIC_INTEN |= CB_PIC_INT1EN;
+}
+
+
+static void irq_nop (unsigned irq) { }
+
+static unsigned cb_pic_startup_irq (unsigned irq)
+{
+	int rval;
+
+	if (cb_pic_active_irqs == 0) {
+		rval = request_irq (IRQ_CB_PIC, cb_pic_handle_irq,
+				    SA_INTERRUPT, "cb_pic_handler", 0);
+		if (rval != 0)
+			return rval;
+	}
+
+	cb_pic_active_irqs++;
+
+	cb_pic_enable_irq (irq);
+
+	return 0;
+}
+
+/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
+   INITS (which is terminated by an entry with the name field == 0).  */
+void __init cb_pic_init_irq_types (struct cb_pic_irq_init *inits,
+				   struct hw_interrupt_type *hw_irq_types)
+{
+	struct cb_pic_irq_init *init;
+	for (init = inits; init->name; init++) {
+		struct hw_interrupt_type *hwit = hw_irq_types++;
+
+		hwit->typename = init->name;
+
+		hwit->startup  = cb_pic_startup_irq;
+		hwit->shutdown = cb_pic_shutdown_irq;
+		hwit->enable   = cb_pic_enable_irq;
+		hwit->disable  = cb_pic_disable_irq;
+		hwit->ack      = irq_nop;
+		hwit->end      = irq_nop;
+
+		/* Initialize kernel IRQ infrastructure for this interrupt.  */
+		init_irq_handlers(init->base, init->num, init->interval, hwit);
+	}
+}
diff -Nru a/arch/v850/kernel/rte_nb85e_cb.c b/arch/v850/kernel/rte_nb85e_cb.c
--- a/arch/v850/kernel/rte_nb85e_cb.c	Sat Jul 19 12:54:29 2003
+++ b/arch/v850/kernel/rte_nb85e_cb.c	Sat Jul 19 12:54:29 2003
@@ -21,7 +21,7 @@
 
 #include <asm/atomic.h>
 #include <asm/page.h>
-#include <asm/nb85e.h>
+#include <asm/v850e.h>
 #include <asm/rte_nb85e_cb.h>
 
 #include "mach.h"
@@ -41,7 +41,7 @@
 
 	   Unfortunately, the dcache seems to be buggy, so we only use the
 	   icache for now.  */
-	nb85e_cache_enable (0x0040 /* BHC */, 0x0000 /* DCC */);
+	v850e_cache_enable (0x0040 /*BHC*/, 0x0003 /*ICC*/, 0x0000 /*DCC*/);
 
 	rte_cb_early_init ();
 }
diff -Nru a/arch/v850/kernel/sim85e2.c b/arch/v850/kernel/sim85e2.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/v850/kernel/sim85e2.c	Sat Jul 19 12:54:25 2003
@@ -0,0 +1,211 @@
+/*
+ * arch/v850/kernel/sim85e2.c -- Machine-specific stuff for
+ *	V850E2 RTL simulator
+ *
+ *  Copyright (C) 2002,03  NEC Electronics Corporation
+ *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+
+#include <asm/atomic.h>
+#include <asm/page.h>
+#include <asm/machdep.h>
+
+#include "mach.h"
+
+
+/* There are 4 possible areas we can use:
+
+     IRAM (1MB) is fast for instruction fetches, but slow for data
+     DRAM (1020KB) is fast for data, but slow for instructions
+     ERAM is cached, so should be fast for both insns and data
+     SDRAM is external DRAM, similar to ERAM
+*/
+
+#define INIT_MEMC_FOR_SDRAM
+#define USE_SDRAM_AREA
+#define KERNEL_IN_SDRAM_AREA
+
+#define DCACHE_MODE	V850E2_CACHE_BTSC_DCM_WT
+/*#define DCACHE_MODE	V850E2_CACHE_BTSC_DCM_WB_ALLOC*/
+
+#ifdef USE_SDRAM_AREA
+#define RAM_START 	SDRAM_ADDR
+#define RAM_END		(SDRAM_ADDR + SDRAM_SIZE)
+#else
+/* When we use DRAM, we need to account for the fact that the end of it is
+   used for R0_RAM.  */
+#define RAM_START	DRAM_ADDR
+#define RAM_END		R0_RAM_ADDR
+#endif
+
+
+extern void memcons_setup (void);
+
+
+#ifdef KERNEL_IN_SDRAM_AREA
+#define EARLY_INIT_SECTION_ATTR __attribute__ ((section (".early.text")))
+#else
+#define EARLY_INIT_SECTION_ATTR __init
+#endif
+
+void EARLY_INIT_SECTION_ATTR mach_early_init (void)
+{
+	extern int panic_timeout;
+
+	/* The sim85e2 simulator tracks `undefined' values, so to make
+	   debugging easier, we begin by zeroing out all otherwise
+	   undefined registers.  This is not strictly necessary.
+
+	   The registers we zero are:
+	       Every GPR except:
+	           stack-pointer (r3)
+		   task-pointer (r16)
+		   our return addr (r31)
+	       Every system register (SPR) that we know about except for
+	       the PSW (SPR 5), which we zero except for the
+	       disable-interrupts bit.
+	*/
+
+	/* GPRs */
+	asm volatile ("             mov r0, r1 ; mov r0, r2              ");
+	asm volatile ("mov r0, r4 ; mov r0, r5 ; mov r0, r6 ; mov r0, r7 ");
+	asm volatile ("mov r0, r8 ; mov r0, r9 ; mov r0, r10; mov r0, r11");
+	asm volatile ("mov r0, r12; mov r0, r13; mov r0, r14; mov r0, r15");
+	asm volatile ("             mov r0, r17; mov r0, r18; mov r0, r19");
+	asm volatile ("mov r0, r20; mov r0, r21; mov r0, r22; mov r0, r23");
+	asm volatile ("mov r0, r24; mov r0, r25; mov r0, r26; mov r0, r27");
+	asm volatile ("mov r0, r28; mov r0, r29; mov r0, r30");
+
+	/* SPRs */
+	asm volatile ("ldsr r0, 0;  ldsr r0, 1;  ldsr r0, 2;  ldsr r0, 3");
+	asm volatile ("ldsr r0, 4");
+	asm volatile ("addi 0x20, r0, r1; ldsr r1, 5"); /* PSW */
+	asm volatile ("ldsr r0, 16; ldsr r0, 17; ldsr r0, 18; ldsr r0, 19");
+	asm volatile ("ldsr r0, 20");
+
+
+#ifdef INIT_MEMC_FOR_SDRAM
+	/* Settings for SDRAM controller.  */
+	V850E2_VSWC   = 0x0042;
+	V850E2_BSC    = 0x9286;
+	V850E2_BCT(0) = 0xb000;	/* was: 0 */
+	V850E2_BCT(1) = 0x000b;
+	V850E2_ASC    = 0;
+	V850E2_LBS    = 0xa9aa;	/* was: 0xaaaa */
+	V850E2_LBC(0) = 0;
+	V850E2_LBC(1) = 0;	/* was: 0x3 */
+	V850E2_BCC    = 0;
+	V850E2_RFS(4) = 0x800a;	/* was: 0xf109 */
+	V850E2_SCR(4) = 0x2091;	/* was: 0x20a1 */
+	V850E2_RFS(3) = 0x800c;
+	V850E2_SCR(3) = 0x20a1;
+	V850E2_DWC(0) = 0;
+	V850E2_DWC(1) = 0;
+#endif
+
+#if 0
+#ifdef CONFIG_V850E2_SIM85E2S
+	/* Turn on the caches.  */
+	V850E2_CACHE_BTSC = V850E2_CACHE_BTSC_ICM | DCACHE_MODE;
+	V850E2_BHC  = 0x1010;
+#elif CONFIG_V850E2_SIM85E2C
+	V850E2_CACHE_BTSC |= (V850E2_CACHE_BTSC_ICM | V850E2_CACHE_BTSC_DCM0);
+	V850E2_BUSM_BHC = 0xFFFF;
+#endif
+#else
+	V850E2_BHC  = 0;
+#endif
+
+	/* Don't stop the simulator at `halt' instructions.  */
+	SIM85E2_NOTHAL = 1;
+
+	/* Ensure that the simulator halts on a panic, instead of going
+	   into an infinite loop inside the panic function.  */
+	panic_timeout = -1;
+}
+
+void __init mach_setup (char **cmdline)
+{
+	memcons_setup ();
+}
+
+void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len)
+{
+	*ram_start = RAM_START;
+	*ram_len = RAM_END - RAM_START;
+}
+
+void __init mach_reserve_bootmem ()
+{
+	extern char _root_fs_image_start, _root_fs_image_end;
+	u32 root_fs_image_start = (u32)&_root_fs_image_start;
+	u32 root_fs_image_end = (u32)&_root_fs_image_end;
+
+	/* Reserve the memory used by the root filesystem image if it's
+	   in RAM.  */
+	if (root_fs_image_end > root_fs_image_start
+	    && root_fs_image_start >= RAM_START
+	    && root_fs_image_start < RAM_END)
+		reserve_bootmem (root_fs_image_start,
+				 root_fs_image_end - root_fs_image_start);
+}
+
+void __init mach_sched_init (struct irqaction *timer_action)
+{
+	/* The simulator actually cycles through all interrupts
+	   periodically.  We just pay attention to IRQ0, which gives us
+	   1/64 the rate of the periodic interrupts.  */
+	setup_irq (0, timer_action);
+}
+
+void mach_gettimeofday (struct timespec *tv)
+{
+	tv->tv_sec = 0;
+	tv->tv_nsec = 0;
+}
+
+/* Interrupts */
+
+struct v850e_intc_irq_init irq_inits[] = {
+	{ "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
+	{ 0 }
+};
+struct hw_interrupt_type hw_itypes[1];
+
+/* Initialize interrupts.  */
+void __init mach_init_irqs (void)
+{
+	v850e_intc_init_irq_types (irq_inits, hw_itypes);
+}
+
+
+void machine_halt (void) __attribute__ ((noreturn));
+void machine_halt (void)
+{
+	SIM85E2_SIMFIN = 0;	/* Halt immediately.  */
+	for (;;) {}
+}
+
+void machine_restart (char *__unused)
+{
+	machine_halt ();
+}
+
+void machine_power_off (void)
+{
+	machine_halt ();
+}
diff -Nru a/arch/v850/kernel/sim85e2c.c b/arch/v850/kernel/sim85e2c.c
--- a/arch/v850/kernel/sim85e2c.c	Sat Jul 19 12:54:25 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,145 +0,0 @@
-/*
- * arch/v850/kernel/sim85e2c.c -- Machine-specific stuff for
- *	V850E2 RTL simulator
- *
- *  Copyright (C) 2002  NEC Corporation
- *  Copyright (C) 2002  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-
-#include <asm/atomic.h>
-#include <asm/page.h>
-#include <asm/machdep.h>
-
-#include "mach.h"
-
-extern void memcons_setup (void);
-
-
-void __init mach_early_init (void)
-{
-	extern int panic_timeout;
-
-	/* Don't stop the simulator at `halt' instructions.  */
-	NOTHAL = 1;
-
-	/* The sim85e2c simulator tracks `undefined' values, so to make
-	   debugging easier, we begin by zeroing out all otherwise
-	   undefined registers.  This is not strictly necessary.
-
-	   The registers we zero are:
-	       Every GPR except:
-	           stack-pointer (r3)
-		   task-pointer (r16)
-		   our return addr (r31)
-	       Every system register (SPR) that we know about except for
-	       the PSW (SPR 5), which we zero except for the
-	       disable-interrupts bit.
-	*/
-
-	/* GPRs */
-	asm volatile ("             mov r0, r1 ; mov r0, r2              ");
-	asm volatile ("mov r0, r4 ; mov r0, r5 ; mov r0, r6 ; mov r0, r7 ");
-	asm volatile ("mov r0, r8 ; mov r0, r9 ; mov r0, r10; mov r0, r11");
-	asm volatile ("mov r0, r12; mov r0, r13; mov r0, r14; mov r0, r15");
-	asm volatile ("             mov r0, r17; mov r0, r18; mov r0, r19");
-	asm volatile ("mov r0, r20; mov r0, r21; mov r0, r22; mov r0, r23");
-	asm volatile ("mov r0, r24; mov r0, r25; mov r0, r26; mov r0, r27");
-	asm volatile ("mov r0, r28; mov r0, r29; mov r0, r30");
-
-	/* SPRs */
-	asm volatile ("ldsr r0, 0;  ldsr r0, 1;  ldsr r0, 2;  ldsr r0, 3");
-	asm volatile ("ldsr r0, 4");
-	asm volatile ("addi 0x20, r0, r1; ldsr r1, 5"); /* PSW */
-	asm volatile ("ldsr r0, 16; ldsr r0, 17; ldsr r0, 18; ldsr r0, 19");
-	asm volatile ("ldsr r0, 20");
-
-	/* Turn on the caches.  */
-	NA85E2C_CACHE_BTSC
-		|= (NA85E2C_CACHE_BTSC_ICM | NA85E2C_CACHE_BTSC_DCM0);
-	NA85E2C_BUSM_BHC = 0xFFFF;
-
-	/* Ensure that the simulator halts on a panic, instead of going
-	   into an infinite loop inside the panic function.  */
-	panic_timeout = -1;
-}
-
-void __init mach_setup (char **cmdline)
-{
-	memcons_setup ();
-}
-
-void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len)
-{
-	/* There are 3 possible areas we can use:
-	     IRAM (1MB) is fast for instruction fetches, but slow for data
-	     DRAM (1020KB) is fast for data, but slow for instructions
-	     ERAM is cached, so should be fast for both insns and data,
-	          _but_ currently only supports write-through caching, so
-		  writes are slow.
-	   Since there's really no area that's good for general kernel
-	   use, we use DRAM -- it won't be good for user programs
-	   (which will be loaded into kernel allocated memory), but
-	   currently we're more concerned with testing the kernel.  */
-	*ram_start = DRAM_ADDR;
-	*ram_len = R0_RAM_ADDR - DRAM_ADDR;
-}
-
-void __init mach_sched_init (struct irqaction *timer_action)
-{
-	/* The simulator actually cycles through all interrupts
-	   periodically.  We just pay attention to IRQ0, which gives us
-	   1/64 the rate of the periodic interrupts.  */
-	setup_irq (0, timer_action);
-}
-
-void mach_gettimeofday (struct timespec *tv)
-{
-	tv->tv_sec = 0;
-	tv->tv_nsec = 0;
-}
-
-/* Interrupts */
-
-struct nb85e_intc_irq_init irq_inits[] = {
-	{ "IRQ", 0, NUM_MACH_IRQS, 1, 7 },
-	{ 0 }
-};
-struct hw_interrupt_type hw_itypes[1];
-
-/* Initialize interrupts.  */
-void __init mach_init_irqs (void)
-{
-	nb85e_intc_init_irq_types (irq_inits, hw_itypes);
-}
-
-
-void machine_halt (void) __attribute__ ((noreturn));
-void machine_halt (void)
-{
-	SIMFIN = 0;		/* Halt immediately.  */
-	for (;;) {}
-}
-
-void machine_restart (char *__unused)
-{
-	machine_halt ();
-}
-
-void machine_power_off (void)
-{
-	machine_halt ();
-}
diff -Nru a/arch/v850/kernel/teg.c b/arch/v850/kernel/teg.c
--- a/arch/v850/kernel/teg.c	Sat Jul 19 12:54:26 2003
+++ b/arch/v850/kernel/teg.c	Sat Jul 19 12:54:26 2003
@@ -22,7 +22,7 @@
 #include <asm/atomic.h>
 #include <asm/page.h>
 #include <asm/machdep.h>
-#include <asm/nb85e_timer_d.h>
+#include <asm/v850e_timer_d.h>
 
 #include "mach.h"
 
@@ -31,12 +31,12 @@
 	/* Select timer interrupt instead of external pin.  */
 	TEG_ISS |= 0x1;
 	/* Start hardware timer.  */
-	nb85e_timer_d_configure (0, HZ);
+	v850e_timer_d_configure (0, HZ);
 	/* Install timer interrupt handler.  */
 	setup_irq (IRQ_INTCMD(0), timer_action);
 }
 
-static struct nb85e_intc_irq_init irq_inits[] = {
+static struct v850e_intc_irq_init irq_inits[] = {
 	{ "IRQ", 0,		NUM_CPU_IRQS,	1, 7 },
 	{ "CMD", IRQ_INTCMD(0),	IRQ_INTCMD_NUM,	1, 5 },
 	{ "SER", IRQ_INTSER(0),	IRQ_INTSER_NUM,	1, 3 },
@@ -51,7 +51,7 @@
 /* Initialize MA chip interrupts.  */
 void __init teg_init_irqs (void)
 {
-	nb85e_intc_init_irq_types (irq_inits, hw_itypes);
+	v850e_intc_init_irq_types (irq_inits, hw_itypes);
 }
 
 /* Called before configuring an on-chip UART.  */
diff -Nru a/arch/v850/kernel/v850e2_cache.c b/arch/v850/kernel/v850e2_cache.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/v850/kernel/v850e2_cache.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,127 @@
+/*
+ * arch/v850/kernel/v850e2_cache.c -- Cache control for V850E2 cache
+ * 	memories
+ *
+ *  Copyright (C) 2003  NEC Electronics Corporation
+ *  Copyright (C) 2003  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#include <linux/mm.h>
+
+#include <asm/v850e2_cache.h>
+
+/* Cache operations we can do.  The encoding corresponds directly to the
+   value we need to write into the COPR register.  */
+enum cache_op {
+	OP_SYNC_IF_DIRTY 	   = V850E2_CACHE_COPR_CFC(0), /* 000 */
+	OP_SYNC_IF_VALID 	   = V850E2_CACHE_COPR_CFC(1), /* 001 */
+	OP_SYNC_IF_VALID_AND_CLEAR = V850E2_CACHE_COPR_CFC(3), /* 011 */
+	OP_WAY_CLEAR 		   = V850E2_CACHE_COPR_CFC(4), /* 100 */
+	OP_FILL 		   = V850E2_CACHE_COPR_CFC(5), /* 101 */
+	OP_CLEAR 		   = V850E2_CACHE_COPR_CFC(6), /* 110 */
+	OP_CREATE_DIRTY 	   = V850E2_CACHE_COPR_CFC(7)  /* 111 */
+};
+
+/* Which cache to use.  This encoding also corresponds directly to the
+   value we need to write into the COPR register. */
+enum cache {
+	ICACHE = 0,
+	DCACHE = V850E2_CACHE_COPR_LBSL
+};
+
+/* Returns ADDR rounded down to the beginning of its cache-line.  */
+#define CACHE_LINE_ADDR(addr)  \
+   ((addr) & ~(V850E2_CACHE_LINE_SIZE - 1))
+/* Returns END_ADDR rounded up to the `limit' of its cache-line.  */
+#define CACHE_LINE_END_ADDR(end_addr)  \
+   CACHE_LINE_ADDR(end_addr + (V850E2_CACHE_LINE_SIZE - 1))
+
+
+/* Low-level cache ops.  */
+
+/* Apply cache-op OP to all entries in CACHE.  */
+static inline void cache_op_all (enum cache_op op, enum cache cache)
+{
+	int cmd = op | cache | V850E2_CACHE_COPR_WSLE | V850E2_CACHE_COPR_STRT;
+
+	if (op != OP_WAY_CLEAR) {
+		/* The WAY_CLEAR operation does the whole way, but other
+		   ops take begin-index and count params; we just indicate
+		   the entire cache.  */
+		V850E2_CACHE_CADL = 0;
+		V850E2_CACHE_CADH = 0;
+		V850E2_CACHE_CCNT = V850E2_CACHE_WAY_SIZE - 1;
+	}
+
+	V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(0); /* way 0 */
+	V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(1); /* way 1 */
+	V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(2); /* way 2 */
+	V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(3); /* way 3 */
+}
+
+/* Apply cache-op OP to all entries in CACHE covering addresses ADDR
+   through ADDR+LEN.  */
+static inline void cache_op_range (enum cache_op op, u32 addr, u32 len,
+				   enum cache cache)
+{
+	u32 start = CACHE_LINE_ADDR (addr);
+	u32 end = CACHE_LINE_END_ADDR (addr + len);
+	u32 num_lines = (end - start) >> V850E2_CACHE_LINE_SIZE_BITS;
+
+	V850E2_CACHE_CADL = start & 0xFFFF;
+	V850E2_CACHE_CADH = start >> 16;
+	V850E2_CACHE_CCNT = num_lines - 1;
+
+	V850E2_CACHE_COPR = op | cache | V850E2_CACHE_COPR_STRT;
+}
+
+
+/* High-level ops.  */
+
+static void cache_exec_after_store_all (void)
+{
+	cache_op_all (OP_SYNC_IF_DIRTY, DCACHE);
+	cache_op_all (OP_WAY_CLEAR, ICACHE);
+}
+
+static void cache_exec_after_store_range (u32 start, u32 len)
+{
+	cache_op_range (OP_SYNC_IF_DIRTY, start, len, DCACHE);
+	cache_op_range (OP_CLEAR, start, len, ICACHE);
+}
+
+
+/* Exported functions.  */
+
+void flush_icache (void)
+{
+	cache_exec_after_store_all ();
+}
+
+void flush_icache_range (unsigned long start, unsigned long end)
+{
+	cache_exec_after_store_range (start, end - start);
+}
+
+void flush_icache_page (struct vm_area_struct *vma, struct page *page)
+{
+	cache_exec_after_store_range (page_to_virt (page), PAGE_SIZE);
+}
+
+void flush_icache_user_range (struct vm_area_struct *vma, struct page *page,
+			      unsigned long addr, int len)
+{
+	cache_exec_after_store_range (addr, len);
+}
+
+void flush_cache_sigtramp (unsigned long addr)
+{
+	/* For the exact size, see signal.c, but 16 bytes should be enough.  */
+	cache_exec_after_store_range (addr, 16);
+}
diff -Nru a/arch/v850/kernel/v850e_cache.c b/arch/v850/kernel/v850e_cache.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/v850/kernel/v850e_cache.c	Sat Jul 19 12:54:26 2003
@@ -0,0 +1,173 @@
+/*
+ * arch/v850/kernel/v850e_cache.c -- Cache control for V850E cache memories
+ *
+ *  Copyright (C) 2003  NEC Electronics Corporation
+ *  Copyright (C) 2003  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+/* This file implements cache control for the rather simple cache used on
+   some V850E CPUs, specifically the NB85E/TEG CPU-core and the V850E/ME2
+   CPU.  V850E2 processors have their own (better) cache
+   implementation.  */
+
+#include <asm/entry.h>
+#include <asm/v850e_cache.h>
+
+#define WAIT_UNTIL_CLEAR(value) while (value) {}
+
+/* Set caching params via the BHC and DCC registers.  */
+void v850e_cache_enable (u16 bhc, u16 icc, u16 dcc)
+{
+	unsigned long *r0_ram = (unsigned long *)R0_RAM_ADDR;
+	register u16 bhc_val asm ("r6") = bhc;
+
+	/* Read the instruction cache control register (ICC) and confirm
+	   that bits 0 and 1 (TCLR0, TCLR1) are all cleared.  */
+	WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
+	V850E_CACHE_ICC = icc;
+
+#ifdef V850E_CACHE_DCC
+	/* Configure data-cache.  */
+	V850E_CACHE_DCC = dcc;
+#endif /* V850E_CACHE_DCC */
+
+	/* Configure caching for various memory regions by writing the BHC
+	   register.  The documentation says that an instruction _cannot_
+	   enable/disable caching for the memory region in which the
+	   instruction itself exists; to work around this, we store
+	   appropriate instructions into the on-chip RAM area (which is never
+	   cached), and briefly jump there to do the work.  */
+#ifdef V850E_CACHE_WRITE_IBS
+	*r0_ram++ 	= 0xf0720760;	/* st.h r0, 0xfffff072[r0] */
+#endif
+	*r0_ram++ 	= 0xf06a3760;	/* st.h r6, 0xfffff06a[r0] */
+	*r0_ram 	= 0x5640006b;	/* jmp [r11] */
+
+	asm ("mov hilo(1f), r11; jmp [%1]; 1:;"
+	     :: "r" (bhc_val), "r" (R0_RAM_ADDR) : "r11");
+}
+
+static void clear_icache (void)
+{
+	/* 1. Read the instruction cache control register (ICC) and confirm
+	      that bits 0 and 1 (TCLR0, TCLR1) are all cleared.  */
+	WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
+
+	/* 2. Read the ICC register and confirm that bit 12 (LOCK0) is
+  	      cleared.  Bit 13 of the ICC register is always cleared.  */
+	WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x1000);
+
+	/* 3. Set the TCLR0 and TCLR1 bits of the ICC register as follows,
+	      when clearing way 0 and way 1 at the same time:
+	        (a) Set the TCLR0 and TCLR1 bits.
+		(b) Read the TCLR0 and TCLR1 bits to confirm that these bits
+		    are cleared.
+		(c) Perform (a) and (b) above again.  */
+	V850E_CACHE_ICC |= 0x3;
+	WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
+
+#ifdef V850E_CACHE_REPEAT_ICC_WRITE
+	/* Do it again.  */
+	V850E_CACHE_ICC |= 0x3;
+	WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3);
+#endif
+}
+
+#ifdef V850E_CACHE_DCC
+/* Flush or clear (or both) the data cache, depending on the value of FLAGS;
+   the procedure is the same for both, just the control bits used differ (and
+   both may be performed simultaneously).  */
+static void dcache_op (unsigned short flags)
+{
+	/* 1. Read the data cache control register (DCC) and confirm that bits
+	      0, 1, 4, and 5 (DC00, DC01, DC04, DC05) are all cleared.  */
+	WAIT_UNTIL_CLEAR (V850E_CACHE_DCC & 0x33);
+
+	/* 2. Clear DCC register bit 12 (DC12), bit 13 (DC13), or both
+	      depending on the way for which tags are to be cleared.  */
+	V850E_CACHE_DCC &= ~0xC000;
+
+	/* 3. Set DCC register bit 0 (DC00), bit 1 (DC01) or both depending on
+	      the way for which tags are to be cleared.
+	      ...
+	      Set DCC register bit 4 (DC04), bit 5 (DC05), or both depending
+	      on the way to be data flushed.  */
+	V850E_CACHE_DCC |= flags;
+
+	/* 4. Read DCC register bit DC00, DC01 [DC04, DC05], or both depending
+	      on the way for which tags were cleared [flushed] and confirm
+	      that that bit is cleared.  */
+	WAIT_UNTIL_CLEAR (V850E_CACHE_DCC & flags);
+}
+#endif /* V850E_CACHE_DCC */
+
+/* Flushes the contents of the dcache to memory.  */
+static inline void flush_dcache (void)
+{
+#ifdef V850E_CACHE_DCC
+	/* We only need to do something if in write-back mode.  */
+	if (V850E_CACHE_DCC & 0x0400)
+		dcache_op (0x30);
+#endif /* V850E_CACHE_DCC */
+}
+
+/* Flushes the contents of the dcache to memory, and then clears it.  */
+static inline void clear_dcache (void)
+{
+#ifdef V850E_CACHE_DCC
+	/* We only need to do something if the dcache is enabled.  */
+	if (V850E_CACHE_DCC & 0x0C00)
+		dcache_op (0x33);
+#endif /* V850E_CACHE_DCC */
+}
+
+/* Clears the dcache without flushing to memory first.  */
+static inline void clear_dcache_no_flush (void)
+{
+#ifdef V850E_CACHE_DCC
+	/* We only need to do something if the dcache is enabled.  */
+	if (V850E_CACHE_DCC & 0x0C00)
+		dcache_op (0x3);
+#endif /* V850E_CACHE_DCC */
+}
+
+static inline void cache_exec_after_store (void)
+{
+	flush_dcache ();
+	clear_icache ();
+}
+
+
+/* Exported functions.  */
+
+void flush_icache (void)
+{
+	cache_exec_after_store ();
+}
+
+void flush_icache_range (unsigned long start, unsigned long end)
+{
+	cache_exec_after_store ();
+}
+
+void flush_icache_page (struct vm_area_struct *vma, struct page *page)
+{
+	cache_exec_after_store ();
+}
+
+void flush_icache_user_range (struct vm_area_struct *vma, struct page *page,
+			      unsigned long adr, int len)
+{
+	cache_exec_after_store ();
+}
+
+void flush_cache_sigtramp (unsigned long addr)
+{
+	cache_exec_after_store ();
+}
diff -Nru a/arch/v850/kernel/v850e_intc.c b/arch/v850/kernel/v850e_intc.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/v850/kernel/v850e_intc.c	Sat Jul 19 12:54:24 2003
@@ -0,0 +1,104 @@
+/*
+ * arch/v850/kernel/v850e_intc.c -- V850E interrupt controller (INTC)
+ *
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/v850e_intc.h>
+
+static void irq_nop (unsigned irq) { }
+
+static unsigned v850e_intc_irq_startup (unsigned irq)
+{
+	v850e_intc_clear_pending_irq (irq);
+	v850e_intc_enable_irq (irq);
+	return 0;
+}
+
+static void v850e_intc_end_irq (unsigned irq)
+{
+	unsigned long psw, temp;
+
+	/* Clear the highest-level bit in the In-service priority register
+	   (ISPR), to allow this interrupt (or another of the same or
+	   lesser priority) to happen again.
+
+	   The `reti' instruction normally does this automatically when the
+	   PSW bits EP and NP are zero, but we can't always rely on reti
+	   being used consistently to return after an interrupt (another
+	   process can be scheduled, for instance, which can delay the
+	   associated reti for a long time, or this process may be being
+	   single-stepped, which uses the `dbret' instruction to return
+	   from the kernel).
+
+	   We also set the PSW EP bit, which prevents reti from also
+	   trying to modify the ISPR itself.  */
+
+	/* Get PSW and disable interrupts.  */
+	asm volatile ("stsr psw, %0; di" : "=r" (psw));
+	/* We don't want to do anything for NMIs (they don't use the ISPR).  */
+	if (! (psw & 0xC0)) {
+		/* Transition to `trap' state, so that an eventual real
+		   reti instruction won't modify the ISPR.  */
+		psw |= 0x40;
+		/* Fake an interrupt return, which automatically clears the
+		   appropriate bit in the ISPR.  */
+		asm volatile ("mov hilo(1f), %0;"
+			      "ldsr %0, eipc; ldsr %1, eipsw;"
+			      "reti;"
+			      "1:"
+			      : "=&r" (temp) : "r" (psw));
+	}
+}
+
+/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
+   INITS (which is terminated by an entry with the name field == 0).  */
+void __init v850e_intc_init_irq_types (struct v850e_intc_irq_init *inits,
+				       struct hw_interrupt_type *hw_irq_types)
+{
+	struct v850e_intc_irq_init *init;
+	for (init = inits; init->name; init++) {
+		unsigned i;
+		struct hw_interrupt_type *hwit = hw_irq_types++;
+
+		hwit->typename = init->name;
+
+		hwit->startup  = v850e_intc_irq_startup;
+		hwit->shutdown = v850e_intc_disable_irq;
+		hwit->enable   = v850e_intc_enable_irq;
+		hwit->disable  = v850e_intc_disable_irq;
+		hwit->ack      = irq_nop;
+		hwit->end      = v850e_intc_end_irq;
+		
+		/* Initialize kernel IRQ infrastructure for this interrupt.  */
+		init_irq_handlers(init->base, init->num, init->interval, hwit);
+
+		/* Set the interrupt priorities.  */
+		for (i = 0; i < init->num; i++) {
+			unsigned irq = init->base + i * init->interval;
+
+			/* If the interrupt is currently enabled (all
+			   interrupts are initially disabled), then
+			   assume whoever enabled it has set things up
+			   properly, and avoid messing with it.  */
+			if (! v850e_intc_irq_enabled (irq))
+				/* This write also (1) disables the
+				   interrupt, and (2) clears any pending
+				   interrupts.  */
+				V850E_INTC_IC (irq)
+					= (V850E_INTC_IC_PR (init->priority)
+					   | V850E_INTC_IC_MK);
+		}
+	}
+}
diff -Nru a/arch/v850/kernel/v850e_timer_d.c b/arch/v850/kernel/v850e_timer_d.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/v850/kernel/v850e_timer_d.c	Sat Jul 19 12:54:25 2003
@@ -0,0 +1,54 @@
+/*
+ * include/asm-v850/v850e_timer_d.c -- `Timer D' component often used
+ *	with V850E CPUs
+ *
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#include <linux/kernel.h>
+
+#include <asm/v850e_utils.h>
+#include <asm/v850e_timer_d.h>
+
+/* Start interval timer TIMER (0-3).  The timer will issue the
+   corresponding INTCMD interrupt RATE times per second.
+   This function does not enable the interrupt.  */
+void v850e_timer_d_configure (unsigned timer, unsigned rate)
+{
+	unsigned divlog2, count;
+
+	/* Calculate params for timer.  */
+	if (! calc_counter_params (
+		    V850E_TIMER_D_BASE_FREQ, rate,
+		    V850E_TIMER_D_TMCD_CS_MIN, V850E_TIMER_D_TMCD_CS_MAX, 16,
+		    &divlog2, &count))
+		printk (KERN_WARNING
+			"Cannot find interval timer %d setting suitable"
+			" for rate of %dHz.\n"
+			"Using rate of %dHz instead.\n",
+			timer, rate,
+			(V850E_TIMER_D_BASE_FREQ >> divlog2) >> 16);
+
+	/* Do the actual hardware timer initialization:  */
+
+	/* Enable timer.  */
+	V850E_TIMER_D_TMCD(timer) = V850E_TIMER_D_TMCD_CAE;
+	/* Set clock divider.  */
+	V850E_TIMER_D_TMCD(timer)
+		= V850E_TIMER_D_TMCD_CAE
+		| V850E_TIMER_D_TMCD_CS(divlog2);
+	/* Set timer compare register.  */
+	V850E_TIMER_D_CMD(timer) = count;
+	/* Start counting.  */
+	V850E_TIMER_D_TMCD(timer)
+		= V850E_TIMER_D_TMCD_CAE
+		| V850E_TIMER_D_TMCD_CS(divlog2)
+		| V850E_TIMER_D_TMCD_CE;
+}
diff -Nru a/arch/v850/kernel/v850e_utils.c b/arch/v850/kernel/v850e_utils.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/v850/kernel/v850e_utils.c	Sat Jul 19 12:54:23 2003
@@ -0,0 +1,62 @@
+/*
+ * include/asm-v850/v850e_utils.h -- Utility functions associated with
+ *	V850E CPUs
+ *
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#include <asm/v850e_utils.h>
+
+/* Calculate counter clock-divider and count values to attain the
+   desired frequency RATE from the base frequency BASE_FREQ.  The
+   counter is expected to have a clock-divider, which can divide the
+   system cpu clock by a power of two value from MIN_DIVLOG2 to
+   MAX_DIV_LOG2, and a word-size of COUNTER_SIZE bits (the counter
+   counts up and resets whenever it's equal to the compare register,
+   generating an interrupt or whatever when it does so).  The returned
+   values are: *DIVLOG2 -- log2 of the desired clock divider and *COUNT
+   -- the counter compare value to use.  Returns true if it was possible
+   to find a reasonable value, otherwise false (and the other return
+   values will be set to be as good as possible).  */
+int calc_counter_params (unsigned long base_freq,
+			 unsigned long rate,
+			 unsigned min_divlog2, unsigned max_divlog2,
+			 unsigned counter_size,
+			 unsigned *divlog2, unsigned *count)
+{
+	unsigned _divlog2;
+	int ok = 0;
+
+	/* Find the lowest clock divider setting that can represent RATE.  */
+	for (_divlog2 = min_divlog2; _divlog2 <= max_divlog2; _divlog2++) {
+		/* Minimum interrupt rate possible using this divider.  */
+		unsigned min_int_rate
+			= (base_freq >> _divlog2) >> counter_size;
+
+		if (min_int_rate <= rate) {
+			/* This setting is the highest resolution
+			   setting that's slow enough enough to attain
+			   RATE interrupts per second, so use it.  */
+			ok = 1;
+			break;
+		}
+	}
+
+	if (_divlog2 > max_divlog2)
+		/* Can't find correct setting.  */
+		_divlog2 = max_divlog2;
+
+	if (divlog2)
+		*divlog2 = _divlog2;
+	if (count)
+		*count = ((base_freq >> _divlog2) + rate/2) / rate;
+
+	return ok;
+}
diff -Nru a/arch/v850/rte_me2_cb.ld b/arch/v850/rte_me2_cb.ld
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/v850/rte_me2_cb.ld	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,30 @@
+/* Linker script for the Midas labs RTE-V850E/ME2-CB evaluation board
+   (CONFIG_RTE_CB_ME2), with kernel in SDRAM.  */
+
+MEMORY {
+	/* 128Kbyte of IRAM */
+	IRAM : ORIGIN = 0x00000000, LENGTH = 0x00020000
+	
+	/* 32MB of SDRAM.  */
+	SDRAM : ORIGIN = 0x00800000, LENGTH = 0x02000000
+}
+
+#define KRAM SDRAM
+
+SECTIONS {
+	.text : {
+		__kram_start = . ;
+		TEXT_CONTENTS
+		INTV_CONTENTS	/* copy to iRAM (0x0-0x620) */
+	} > KRAM
+
+	.data : {
+		DATA_CONTENTS
+		BSS_CONTENTS
+		RAMK_INIT_CONTENTS
+		__kram_end = . ;
+		BOOTMAP_CONTENTS
+	} > KRAM
+	
+	.root ALIGN (4096) : { ROOT_FS_CONTENTS } > SDRAM
+}
diff -Nru a/arch/v850/sim85e2.ld b/arch/v850/sim85e2.ld
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/v850/sim85e2.ld	Sat Jul 19 12:54:29 2003
@@ -0,0 +1,44 @@
+/* Linker script for the sim85e2c simulator, which is a verilog simulation of
+   the V850E2 NA85E2C cpu core (CONFIG_V850E2_SIM85E2C).  */
+
+MEMORY {
+	/* 1MB of `instruction RAM', starting at 0.
+	   Instruction fetches are much faster from IRAM than from DRAM.
+	   This should match IRAM_ADDR in "include/asm-v580/sim85e2c.h".    */
+	IRAM		: ORIGIN = 0x00000000, LENGTH = 0x00100000
+
+	/* 1MB of `data RAM', below and contiguous with the I/O space.
+	   Data fetches are much faster from DRAM than from IRAM.
+	   This should match DRAM_ADDR in "include/asm-v580/sim85e2c.h".  */
+	DRAM		: ORIGIN = 0xfff00000, LENGTH = 0x000ff000
+	/* We have to load DRAM at a mirror-address of 0x1ff00000,
+	   because the simulator's preprocessing script isn't smart
+	   enough to deal with the above LMA.  */
+	DRAM_LOAD 	: ORIGIN = 0x1ff00000, LENGTH = 0x000ff000
+
+	/* `external ram' (CS1 area), comes after IRAM.
+	   This should match ERAM_ADDR in "include/asm-v580/sim85e2c.h".  */
+	ERAM		: ORIGIN = 0x00100000, LENGTH = 0x07f00000
+
+	/* Dynamic RAM; uses memory controller.  */
+	/* SDRAM	: ORIGIN = 0x10000000, LENGTH = 0x01000000 */
+	SDRAM		: ORIGIN = 0x10000000, LENGTH = 0x00200000/*use 2MB*/
+}
+
+SECTIONS {
+	.iram : {
+		INTV_CONTENTS
+		*arch/v850/kernel/head.o
+		*(.early.text)
+	} > IRAM
+	.dram : {
+		_memcons_output = . ;
+		. = . + 0x8000 ;
+		_memcons_output_end = . ;
+	} > DRAM
+	.sdram : {
+		/* We stick console output into a buffer here.  */
+		RAMK_KRAM_CONTENTS
+		ROOT_FS_CONTENTS
+	} > SDRAM
+}
diff -Nru a/arch/v850/sim85e2c.ld b/arch/v850/sim85e2c.ld
--- a/arch/v850/sim85e2c.ld	Sat Jul 19 12:54:29 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,44 +0,0 @@
-/* Linker script for the sim85e2c simulator, which is a verilog simulation of
-   the V850E2 NA85E2C cpu core (CONFIG_V850E2_SIM85E2C).  */
-
-MEMORY {
-	/* 1MB of `instruction RAM', starting at 0.
-	   Instruction fetches are much faster from IRAM than from DRAM.
-	   This should match IRAM_ADDR in "include/asm-v580/sim85e2c.h".    */
-	IRAM	: ORIGIN = 0x00000000, LENGTH = 0x00100000
-
-	/* 1MB of `data RAM', below and contiguous with the I/O space.
-	   Data fetches are much faster from DRAM than from IRAM.
-	   This should match DRAM_ADDR in "include/asm-v580/sim85e2c.h".  */
-	DRAM	: ORIGIN = 0xfff00000, LENGTH = 0x000ff000
-	/* We have to load DRAM at a mirror-address of 0x1ff00000,
-	   because the simulator's preprocessing script isn't smart
-	   enough to deal with the above LMA.  */
-	DRAM_LOAD : ORIGIN = 0x1ff00000, LENGTH = 0x000ff000
-
-	/* `external ram' (CS1 area), comes after IRAM.
-	   This should match ERAM_ADDR in "include/asm-v580/sim85e2c.h".  */
-	ERAM	: ORIGIN = 0x00100000, LENGTH = 0x07f00000
-}
-
-SECTIONS {
-	.iram : {
-		INTV_CONTENTS
-		TEXT_CONTENTS
-		RAMK_INIT_CONTENTS
-	} > IRAM
-	.data : {
-		__kram_start = . ;
-		DATA_CONTENTS
-		BSS_CONTENTS
-		ROOT_FS_CONTENTS
-
-		/* We stick console output into a buffer here.  */
-		_memcons_output = . ;
-		. = . + 0x8000 ;
-		_memcons_output_end = . ;
-
-		__kram_end = . ;
-		BOOTMAP_CONTENTS
-	} > DRAM  AT> DRAM_LOAD
-}
diff -Nru a/arch/v850/vmlinux.lds.S b/arch/v850/vmlinux.lds.S
--- a/arch/v850/vmlinux.lds.S	Sat Jul 19 12:54:25 2003
+++ b/arch/v850/vmlinux.lds.S	Sat Jul 19 12:54:25 2003
@@ -206,8 +206,8 @@
 # include "sim.ld"
 #endif
 
-#ifdef CONFIG_V850E2_SIM85E2C
-# include "sim85e2c.ld"
+#ifdef CONFIG_V850E2_SIM85E2
+# include "sim85e2.ld"
 #endif
 
 #ifdef CONFIG_V850E2_FPGA85E2C
@@ -247,3 +247,8 @@
 #  include "rte_nb85e_cb.ld"
 # endif
 #endif
+
+#ifdef CONFIG_RTE_CB_ME2
+#  include "rte_me2_cb.ld"
+#endif
+
diff -Nru a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
--- a/arch/x86_64/mm/init.c	Sat Jul 19 12:54:23 2003
+++ b/arch/x86_64/mm/init.c	Sat Jul 19 12:54:23 2003
@@ -19,9 +19,6 @@
 #include <linux/swap.h>
 #include <linux/smp.h>
 #include <linux/init.h>
-#ifdef CONFIG_BLK_DEV_INITRD
-#include <linux/blk.h>
-#endif
 #include <linux/pagemap.h>
 #include <linux/bootmem.h>
 #include <linux/proc_fs.h>
diff -Nru a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
--- a/arch/x86_64/mm/numa.c	Sat Jul 19 12:54:27 2003
+++ b/arch/x86_64/mm/numa.c	Sat Jul 19 12:54:27 2003
@@ -8,7 +8,6 @@
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/mmzone.h>
-#include <linux/blk.h>
 #include <linux/ctype.h>
 #include <asm/e820.h>
 #include <asm/proto.h>
diff -Nru a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
--- a/drivers/acorn/block/fd1772.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/acorn/block/fd1772.c	Sat Jul 19 12:54:24 2003
@@ -152,8 +152,6 @@
 #include <asm/uaccess.h>
 
 
-#include <linux/blk.h>
-
 /* Note: FD_MAX_UNITS could be redefined to 2 for the Atari (with
  * little additional rework in this file). But I'm not yet sure if
  * some other code depends on the number of floppies... (It is defined
diff -Nru a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
--- a/drivers/acorn/block/mfmhd.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/acorn/block/mfmhd.c	Sat Jul 19 12:54:23 2003
@@ -111,7 +111,6 @@
 #include <linux/major.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/blk.h>
 #include <linux/blkpg.h>
 
 #include <asm/system.h>
diff -Nru a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c
--- a/drivers/acpi/executer/exutils.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/acpi/executer/exutils.c	Sat Jul 19 12:54:23 2003
@@ -290,7 +290,7 @@
 	 * acpi_integer is unsigned, so we don't worry about a '-'
 	 */
 	if ((current_value = value) == 0) {
-	    return_VALUE (1);
+		return_VALUE (1);
 	}
 
 	num_digits = 0;
diff -Nru a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c
--- a/drivers/acpi/hardware/hwregs.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/acpi/hardware/hwregs.c	Sat Jul 19 12:54:27 2003
@@ -357,9 +357,9 @@
 
 	/*
 	 * Decode the Register ID
-	 * Register id = Register block id | bit id
+	 * Register ID = [Register block ID] | [bit ID]
 	 *
-	 * Check bit id to fine locate Register offset.
+	 * Check bit ID to fine locate Register offset.
 	 * Check Mask to determine Register offset, and then read-write.
 	 */
 	switch (bit_reg_info->parent_register) {
@@ -367,9 +367,9 @@
 
 		/*
 		 * Status Registers are different from the rest.  Clear by
-		 * writing 1, writing 0 has no effect.  So, the only relevant
+		 * writing 1, and writing 0 has no effect.  So, the only relevant
 		 * information is the single bit we're interested in, all others should
-		 * be written as 0 so they will be left unchanged
+		 * be written as 0 so they will be left unchanged.
 		 */
 		value = ACPI_REGISTER_PREPARE_BITS (value,
 				 bit_reg_info->bit_position, bit_reg_info->access_bit_mask);
@@ -394,17 +394,17 @@
 	case ACPI_REGISTER_PM1_CONTROL:
 
 		/*
-		 * Read the PM1 Control register.
+		 * Write the PM1 Control register.
 		 * Note that at this level, the fact that there are actually TWO
-		 * registers (A and B - and that B may not exist) is abstracted.
+		 * registers (A and B - and B may not exist) is abstracted.
 		 */
 		ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", register_value));
 
 		ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position,
 				bit_reg_info->access_bit_mask, value);
 
-		status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, register_id,
-				(u16) register_value);
+		status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK,
+				  ACPI_REGISTER_PM1_CONTROL, (u16) register_value);
 		break;
 
 
@@ -724,7 +724,7 @@
 
 	/*
 	 * Three address spaces supported:
-	 * Memory, Io, or PCI config.
+	 * Memory, IO, or PCI_Config.
 	 */
 	switch (reg->address_space_id) {
 	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
@@ -808,9 +808,10 @@
 		(!reg->address)) {
 		return (AE_OK);
 	}
+
 	/*
 	 * Three address spaces supported:
-	 * Memory, Io, or PCI config.
+	 * Memory, IO, or PCI_Config.
 	 */
 	switch (reg->address_space_id) {
 	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c
--- a/drivers/acpi/osl.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/acpi/osl.c	Sat Jul 19 12:54:27 2003
@@ -35,6 +35,7 @@
 #include <linux/kmod.h>
 #include <linux/delay.h>
 #include <linux/workqueue.h>
+#include <linux/nmi.h>
 #include <acpi/acpi.h>
 #include <asm/io.h>
 #include <acpi/acpi_bus.h>
@@ -291,11 +292,14 @@
 void
 acpi_os_stall(u32 us)
 {
-	if (us > 10000) {
-		mdelay(us / 1000);
-	}
-	else {
-		udelay(us);
+	while (us) {
+		u32 delay = 1000;
+
+		if (delay > us)
+			delay = us;
+		udelay(delay);
+		touch_nmi_watchdog();
+		us -= delay;
 	}
 }
 
diff -Nru a/drivers/acpi/processor.c b/drivers/acpi/processor.c
--- a/drivers/acpi/processor.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/acpi/processor.c	Sat Jul 19 12:54:26 2003
@@ -1351,7 +1351,7 @@
 						PDE(inode)->data);
 }
 
-static int
+static ssize_t
 acpi_processor_write_throttling (
         struct file		*file,
         const char		*buffer,
@@ -1414,7 +1414,7 @@
 						PDE(inode)->data);
 }
 
-static int
+static ssize_t
 acpi_processor_write_limit (
 	struct file		*file,
 	const char		*buffer,
diff -Nru a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c
--- a/drivers/acpi/tables/tbconvrt.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/acpi/tables/tbconvrt.c	Sat Jul 19 12:54:24 2003
@@ -75,14 +75,10 @@
 	ACPI_FUNCTION_ENTRY ();
 
 
-#if ACPI_MACHINE_WIDTH != 64
-
 	if (RSDP->revision < 2) {
 		pointer_size = sizeof (u32);
 	}
-	else
-#endif
-	{
+	else {
 		pointer_size = sizeof (u64);
 	}
 
diff -Nru a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c
--- a/drivers/acpi/tables/tbget.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/acpi/tables/tbget.c	Sat Jul 19 12:54:26 2003
@@ -145,7 +145,7 @@
 		/* Create a logical address for the physical pointer*/
 
 		status = acpi_os_map_memory (address->pointer.physical, sizeof (struct acpi_table_header),
-				  (void **) &header);
+				  (void *) &header);
 		if (ACPI_FAILURE (status)) {
 			ACPI_REPORT_ERROR (("Could not map memory at %8.8X%8.8X for length %X\n",
 				ACPI_HIDWORD (address->pointer.physical),
@@ -361,7 +361,7 @@
 		 * into our address space.
 		 */
 		status = acpi_os_map_memory (address->pointer.physical, (acpi_size) header->length,
-				  (void **) &full_table);
+				  (void *) &full_table);
 		if (ACPI_FAILURE (status)) {
 			ACPI_REPORT_ERROR (("Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X\n",
 				header->signature,
diff -Nru a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
--- a/drivers/acpi/tables/tbinstal.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/acpi/tables/tbinstal.c	Sat Jul 19 12:54:23 2003
@@ -271,22 +271,40 @@
 		if (list_head->next) {
 			return_ACPI_STATUS (AE_ALREADY_EXISTS);
 		}
-	}
 
-	/*
-	 * Link the new table in to the list of tables of this type.
-	 * Just insert at the start of the list, order unimportant.
-	 *
-	 * table_desc->Prev is already NULL from calloc()
-	 */
-	table_desc->next = list_head->next;
-	list_head->next = table_desc;
+		table_desc->next = list_head->next;
+		list_head->next = table_desc;
+
+		if (table_desc->next) {
+			table_desc->next->prev = table_desc;
+		}
 
-	if (table_desc->next) {
-		table_desc->next->prev = table_desc;
+		list_head->count++;
 	}
+	else {
+		/*
+		 * Link the new table in to the list of tables of this type.
+		 * Insert at the end of the list, order IS IMPORTANT.
+		 *
+		 * table_desc->Prev & Next are already NULL from calloc()
+		 */
+		list_head->count++;
+
+		if (!list_head->next) {
+			list_head->next = table_desc;
+		}
+		else {
+			table_desc->next = list_head->next;
 
-	list_head->count++;
+			while (table_desc->next->next) {
+				table_desc->next = table_desc->next->next;
+			}
+
+			table_desc->next->next = table_desc;
+			table_desc->prev = table_desc->next;
+			table_desc->next = NULL;
+		}
+	}
 
 	/* Finish initialization of the table descriptor */
 
diff -Nru a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c
--- a/drivers/acpi/tables/tbrsdt.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/acpi/tables/tbrsdt.c	Sat Jul 19 12:54:25 2003
@@ -85,7 +85,7 @@
 		 * Obtain access to the RSDP structure
 		 */
 		status = acpi_os_map_memory (address->pointer.physical, sizeof (struct rsdp_descriptor),
-				  (void **) &rsdp);
+				  (void *) &rsdp);
 		if (ACPI_FAILURE (status)) {
 			return_ACPI_STATUS (status);
 		}
diff -Nru a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c
--- a/drivers/acpi/tables/tbxfroot.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/acpi/tables/tbxfroot.c	Sat Jul 19 12:54:26 2003
@@ -179,7 +179,7 @@
 
 		if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
 			status = acpi_os_map_memory (rsdp_address.pointer.physical, sizeof (struct rsdp_descriptor),
-					  (void **) &acpi_gbl_RSDP);
+					  (void *) &acpi_gbl_RSDP);
 			if (ACPI_FAILURE (status)) {
 				return_ACPI_STATUS (status);
 			}
@@ -423,7 +423,7 @@
 		 * 1) Search EBDA (low memory) paragraphs
 		 */
 		status = acpi_os_map_memory ((u64) ACPI_LO_RSDP_WINDOW_BASE, ACPI_LO_RSDP_WINDOW_SIZE,
-				  (void **) &table_ptr);
+				  (void *) &table_ptr);
 		if (ACPI_FAILURE (status)) {
 			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n",
 				ACPI_LO_RSDP_WINDOW_BASE, ACPI_LO_RSDP_WINDOW_SIZE));
@@ -447,7 +447,7 @@
 		 * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h
 		 */
 		status = acpi_os_map_memory ((u64) ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE,
-				  (void **) &table_ptr);
+				  (void *) &table_ptr);
 		if (ACPI_FAILURE (status)) {
 			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n",
 				ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE));
diff -Nru a/drivers/acpi/tables.c b/drivers/acpi/tables.c
--- a/drivers/acpi/tables.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/acpi/tables.c	Sat Jul 19 12:54:24 2003
@@ -33,6 +33,7 @@
 #include <linux/irq.h>
 #include <linux/errno.h>
 #include <linux/acpi.h>
+#include <linux/bootmem.h>
 
 #define PREFIX			"ACPI: "
 
@@ -61,16 +62,14 @@
 
 /* System Description Table (RSDT/XSDT) */
 struct acpi_table_sdt {
-	unsigned long		pa;		/* Physical Address */
-	unsigned long		count;		/* Table count */
-	struct {
-		unsigned long		pa;
-		enum acpi_table_id	id;
-		unsigned long		size;
-	}			entry[ACPI_MAX_TABLES];
+	unsigned long		pa;
+	enum acpi_table_id	id;
+	unsigned long		size;
 } __attribute__ ((packed));
 
-static struct acpi_table_sdt	sdt;
+static unsigned long		sdt_pa;		/* Physical Address */
+static unsigned long		sdt_count;	/* Table count */
+static struct acpi_table_sdt	*sdt_entry;
 
 void
 acpi_table_print (
@@ -236,11 +235,11 @@
 
 	/* Locate the table. */
 
-	for (i = 0; i < sdt.count; i++) {
-		if (sdt.entry[i].id != temp_id)
+	for (i = 0; i < sdt_count; i++) {
+		if (sdt_entry[i].id != temp_id)
 			continue;
 		*header = (void *)
-			__acpi_map_table(sdt.entry[i].pa, sdt.entry[i].size);
+			__acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size);
 		if (!*header) {
 			printk(KERN_WARNING PREFIX "Unable to map %s\n",
 			       acpi_table_signatures[temp_id]);
@@ -289,11 +288,11 @@
 
 	/* Locate the MADT (if exists). There should only be one. */
 
-	for (i = 0; i < sdt.count; i++) {
-		if (sdt.entry[i].id != id)
+	for (i = 0; i < sdt_count; i++) {
+		if (sdt_entry[i].id != id)
 			continue;
 		madt = (void *)
-			__acpi_map_table(sdt.entry[i].pa, sdt.entry[i].size);
+			__acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size);
 		if (!madt) {
 			printk(KERN_WARNING PREFIX "Unable to map %s\n",
 			       acpi_table_signatures[id]);
@@ -308,7 +307,7 @@
 		return -ENODEV;
 	}
 
-	madt_end = (unsigned long) madt + sdt.entry[i].size;
+	madt_end = (unsigned long) madt + sdt_entry[i].size;
 
 	/* Parse all entries looking for a match. */
 
@@ -349,10 +348,10 @@
 	if (!handler)
 		return -EINVAL;
 
-	for (i = 0; i < sdt.count; i++) {
-		if (sdt.entry[i].id != id)
+	for (i = 0; i < sdt_count; i++) {
+		if (sdt_entry[i].id != id)
 			continue;
-		handler(sdt.entry[i].pa, sdt.entry[i].size);
+		handler(sdt_entry[i].pa, sdt_entry[i].size);
 		count++;
 	}
 
@@ -377,11 +376,11 @@
 			
 		struct acpi_table_xsdt	*mapped_xsdt = NULL;
 
-		sdt.pa = ((struct acpi20_table_rsdp*)rsdp)->xsdt_address;
+		sdt_pa = ((struct acpi20_table_rsdp*)rsdp)->xsdt_address;
 
 		/* map in just the header */
 		header = (struct acpi_table_header *)
-			__acpi_map_table(sdt.pa, sizeof(struct acpi_table_header));
+			__acpi_map_table(sdt_pa, sizeof(struct acpi_table_header));
 
 		if (!header) {
 			printk(KERN_WARNING PREFIX "Unable to map XSDT header\n");
@@ -390,7 +389,7 @@
 
 		/* remap in the entire table before processing */
 		mapped_xsdt = (struct acpi_table_xsdt *)
-			__acpi_map_table(sdt.pa, header->length);
+			__acpi_map_table(sdt_pa, header->length);
 		if (!mapped_xsdt) {
 			printk(KERN_WARNING PREFIX "Unable to map XSDT\n");
 			return -ENODEV;
@@ -407,15 +406,21 @@
 			return -ENODEV;
 		}
 
-		sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 3;
-		if (sdt.count > ACPI_MAX_TABLES) {
+		sdt_count = (header->length - sizeof(struct acpi_table_header)) >> 3;
+		if (sdt_count > ACPI_MAX_TABLES) {
 			printk(KERN_WARNING PREFIX "Truncated %lu XSDT entries\n",
-				(sdt.count - ACPI_MAX_TABLES));
-			sdt.count = ACPI_MAX_TABLES;
+				(sdt_count - ACPI_MAX_TABLES));
+			sdt_count = ACPI_MAX_TABLES;
 		}
 
-		for (i = 0; i < sdt.count; i++)
-			sdt.entry[i].pa = (unsigned long) mapped_xsdt->entry[i];
+		sdt_entry = alloc_bootmem(sdt_count * sizeof(struct acpi_table_sdt));
+		if (!sdt_entry) {
+			printk(KERN_ERR "ACPI: Could not allocate mem for SDT entries!\n");
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < sdt_count; i++)
+			sdt_entry[i].pa = (unsigned long) mapped_xsdt->entry[i];
 	}
 
 	/* Then check RSDT */
@@ -424,11 +429,11 @@
 
 		struct acpi_table_rsdt	*mapped_rsdt = NULL;
 
-		sdt.pa = rsdp->rsdt_address;
+		sdt_pa = rsdp->rsdt_address;
 
 		/* map in just the header */
 		header = (struct acpi_table_header *)
-			__acpi_map_table(sdt.pa, sizeof(struct acpi_table_header));
+			__acpi_map_table(sdt_pa, sizeof(struct acpi_table_header));
 		if (!header) {
 			printk(KERN_WARNING PREFIX "Unable to map RSDT header\n");
 			return -ENODEV;
@@ -436,7 +441,7 @@
 
 		/* remap in the entire table before processing */
 		mapped_rsdt = (struct acpi_table_rsdt *)
-			__acpi_map_table(sdt.pa, header->length);
+			__acpi_map_table(sdt_pa, header->length);
 		if (!mapped_rsdt) {
 			printk(KERN_WARNING PREFIX "Unable to map RSDT\n");
 			return -ENODEV;
@@ -453,15 +458,21 @@
 			return -ENODEV;
 		}
 
-		sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 2;
-		if (sdt.count > ACPI_MAX_TABLES) {
+		sdt_count = (header->length - sizeof(struct acpi_table_header)) >> 2;
+		if (sdt_count > ACPI_MAX_TABLES) {
 			printk(KERN_WARNING PREFIX "Truncated %lu RSDT entries\n",
-				(sdt.count - ACPI_TABLE_COUNT));
-			sdt.count = ACPI_MAX_TABLES;
+				(sdt_count - ACPI_MAX_TABLES));
+			sdt_count = ACPI_MAX_TABLES;
 		}
 
-		for (i = 0; i < sdt.count; i++)
-			sdt.entry[i].pa = (unsigned long) mapped_rsdt->entry[i];
+		sdt_entry = alloc_bootmem(sdt_count * sizeof(struct acpi_table_sdt));
+		if (!sdt_entry) {
+			printk(KERN_ERR "ACPI: Could not allocate mem for SDT entries!\n");
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < sdt_count; i++)
+			sdt_entry[i].pa = (unsigned long) mapped_rsdt->entry[i];
 	}
 
 	else {
@@ -469,38 +480,38 @@
 		return -ENODEV;
 	}
 
-	acpi_table_print(header, sdt.pa);
+	acpi_table_print(header, sdt_pa);
 
-	for (i = 0; i < sdt.count; i++) {
+	for (i = 0; i < sdt_count; i++) {
 
 		/* map in just the header */
 		header = (struct acpi_table_header *)
-			__acpi_map_table(sdt.entry[i].pa,
+			__acpi_map_table(sdt_entry[i].pa,
 				sizeof(struct acpi_table_header));
 		if (!header)
 			continue;
 
 		/* remap in the entire table before processing */
 		header = (struct acpi_table_header *)
-			__acpi_map_table(sdt.entry[i].pa,
+			__acpi_map_table(sdt_entry[i].pa,
 				header->length);
 		if (!header)
 			continue;
 	               
-		acpi_table_print(header, sdt.entry[i].pa);
+		acpi_table_print(header, sdt_entry[i].pa);
 
 		if (acpi_table_compute_checksum(header, header->length)) {
 			printk(KERN_WARNING "  >>> ERROR: Invalid checksum\n");
 			continue;
 		}
 
-		sdt.entry[i].size = header->length;
+		sdt_entry[i].size = header->length;
 
 		for (id = 0; id < ACPI_TABLE_COUNT; id++) {
 			if (!strncmp((char *) &header->signature,
 				acpi_table_signatures[id],
 				sizeof(header->signature))) {
-				sdt.entry[i].id = id;
+				sdt_entry[i].id = id;
 			}
 		}
 	}
@@ -524,8 +535,6 @@
 	struct acpi_table_rsdp	*rsdp = NULL;
 	unsigned long		rsdp_phys = 0;
 	int			result = 0;
-
-	memset(&sdt, 0, sizeof(struct acpi_table_sdt));
 
 	/* Locate and map the Root System Description Table (RSDP) */
 
diff -Nru a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
--- a/drivers/acpi/thermal.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/acpi/thermal.c	Sat Jul 19 12:54:27 2003
@@ -84,11 +84,11 @@
 static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file);
 static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file);
 static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file);
-static int acpi_thermal_write_trip_points (struct file*,const char *,size_t,loff_t *);
+static ssize_t acpi_thermal_write_trip_points (struct file*,const char *,size_t,loff_t *);
 static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file);
-static int acpi_thermal_write_cooling_mode (struct file*,const char *,size_t,loff_t *);
+static ssize_t acpi_thermal_write_cooling_mode (struct file*,const char *,size_t,loff_t *);
 static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file);
-static int acpi_thermal_write_polling(struct file*,const char *,size_t,loff_t *);
+static ssize_t acpi_thermal_write_polling(struct file*,const char *,size_t,loff_t *);
 
 static struct acpi_driver acpi_thermal_driver = {
 	.name =		ACPI_THERMAL_DRIVER_NAME,
@@ -881,7 +881,7 @@
 	return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data);
 }
 
-static int
+static ssize_t
 acpi_thermal_write_trip_points (
         struct file		*file,
         const char		*buffer,
@@ -950,7 +950,7 @@
 							PDE(inode)->data);
 }
 
-static int
+static ssize_t
 acpi_thermal_write_cooling_mode (
 	struct file		*file,
 	const char		*buffer,
@@ -1011,7 +1011,7 @@
 							PDE(inode)->data);
 }
 
-static int
+static ssize_t
 acpi_thermal_write_polling (
 	struct file		*file,
 	const char		*buffer,
diff -Nru a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
--- a/drivers/acpi/utilities/utglobal.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/acpi/utilities/utglobal.c	Sat Jul 19 12:54:23 2003
@@ -307,9 +307,9 @@
 	/***********    Name,   Signature, Global typed pointer     Signature size,      Type                  How many allowed?,    Contains valid AML? */
 
 	/* RSDP 0 */ {RSDP_NAME, RSDP_SIG, NULL,                    sizeof (RSDP_SIG)-1, ACPI_TABLE_ROOT     | ACPI_TABLE_SINGLE},
-	/* DSDT 1 */ {DSDT_SIG,  DSDT_SIG, (void **) &acpi_gbl_DSDT, sizeof (DSDT_SIG)-1, ACPI_TABLE_SECONDARY| ACPI_TABLE_SINGLE  | ACPI_TABLE_EXECUTABLE},
-	/* FADT 2 */ {FADT_SIG,  FADT_SIG, (void **) &acpi_gbl_FADT, sizeof (FADT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_SINGLE},
-	/* FACS 3 */ {FACS_SIG,  FACS_SIG, (void **) &acpi_gbl_FACS, sizeof (FACS_SIG)-1, ACPI_TABLE_SECONDARY| ACPI_TABLE_SINGLE},
+	/* DSDT 1 */ {DSDT_SIG,  DSDT_SIG, (void *) &acpi_gbl_DSDT, sizeof (DSDT_SIG)-1, ACPI_TABLE_SECONDARY| ACPI_TABLE_SINGLE  | ACPI_TABLE_EXECUTABLE},
+	/* FADT 2 */ {FADT_SIG,  FADT_SIG, (void *) &acpi_gbl_FADT, sizeof (FADT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_SINGLE},
+	/* FACS 3 */ {FACS_SIG,  FACS_SIG, (void *) &acpi_gbl_FACS, sizeof (FACS_SIG)-1, ACPI_TABLE_SECONDARY| ACPI_TABLE_SINGLE},
 	/* PSDT 4 */ {PSDT_SIG,  PSDT_SIG, NULL,                    sizeof (PSDT_SIG)-1, ACPI_TABLE_PRIMARY  | ACPI_TABLE_MULTIPLE | ACPI_TABLE_EXECUTABLE},
 	/* SSDT 5 */ {SSDT_SIG,  SSDT_SIG, NULL,                    sizeof (SSDT_SIG)-1, ACPI_TABLE_PRIMARY  | ACPI_TABLE_MULTIPLE | ACPI_TABLE_EXECUTABLE},
 	/* XSDT 6 */ {XSDT_SIG,  XSDT_SIG, NULL,                    sizeof (RSDT_SIG)-1, ACPI_TABLE_ROOT     | ACPI_TABLE_SINGLE},
diff -Nru a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c
--- a/drivers/atm/atmtcp.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/atm/atmtcp.c	Sat Jul 19 12:54:26 2003
@@ -66,7 +66,7 @@
 	*(struct atm_vcc **) &new_msg->vcc = vcc;
 	old_test = test_bit(flag,&vcc->flags);
 	out_vcc->push(out_vcc,skb);
-	add_wait_queue(&vcc->sleep,&wait);
+	add_wait_queue(vcc->sk->sk_sleep, &wait);
 	while (test_bit(flag,&vcc->flags) == old_test) {
 		mb();
 		out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL;
@@ -78,7 +78,7 @@
 		schedule();
 	}
 	current->state = TASK_RUNNING;
-	remove_wait_queue(&vcc->sleep,&wait);
+	remove_wait_queue(vcc->sk->sk_sleep, &wait);
 	return error;
 }
 
@@ -90,7 +90,7 @@
 	vcc->vpi = msg->addr.sap_addr.vpi;
 	vcc->vci = msg->addr.sap_addr.vci;
 	vcc->qos = msg->qos;
-	vcc->reply = msg->result;
+	vcc->sk->sk_err = -msg->result;
 	switch (msg->type) {
 	    case ATMTCP_CTRL_OPEN:
 		change_bit(ATM_VF_READY,&vcc->flags);
@@ -103,7 +103,7 @@
 		    msg->type);
 		return -EINVAL;
 	}
-	wake_up(&vcc->sleep);
+	wake_up(vcc->sk->sk_sleep);
 	return 0;
 }
 
@@ -134,7 +134,7 @@
 	clear_bit(ATM_VF_READY,&vcc->flags); /* just in case ... */
 	error = atmtcp_send_control(vcc,ATMTCP_CTRL_OPEN,&msg,ATM_VF_READY);
 	if (error) return error;
-	return vcc->reply;
+	return -vcc->sk->sk_err;
 }
 
 
@@ -257,7 +257,7 @@
 		walk = atm_sk(s);
 		if (walk->dev != atmtcp_dev)
 			continue;
-		wake_up(&walk->sleep);
+		wake_up(walk->sk->sk_sleep);
 	}
 	read_unlock(&vcc_sklist_lock);
 }
diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c
--- a/drivers/block/DAC960.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/block/DAC960.c	Sat Jul 19 12:54:26 2003
@@ -23,7 +23,6 @@
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/blk.h>
 #include <linux/blkdev.h>
 #include <linux/bio.h>
 #include <linux/completion.h>
diff -Nru a/drivers/block/Kconfig b/drivers/block/Kconfig
--- a/drivers/block/Kconfig	Sat Jul 19 12:54:23 2003
+++ b/drivers/block/Kconfig	Sat Jul 19 12:54:23 2003
@@ -264,6 +264,7 @@
 
 config BLK_DEV_CRYPTOLOOP
 	tristate "Cryptoloop Support"
+	select CRYPTO
 	depends on BLK_DEV_LOOP
 	---help---
 	  Say Y here if you want to be able to use the ciphers that are 
@@ -339,7 +340,7 @@
 
 config LBD
 	bool "Support for Large Block Devices"
-	depends on X86
+	depends on X86 || MIPS32 || PPC32 || ARCH_S390_31 || SUPERH
 	help
 	  Say Y here if you want to attach large (bigger than 2TB) discs to
 	  your machine, or if you want to have a raid or loopback device
diff -Nru a/drivers/block/acsi.c b/drivers/block/acsi.c
--- a/drivers/block/acsi.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/block/acsi.c	Sat Jul 19 12:54:30 2003
@@ -55,7 +55,6 @@
 #include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/major.h>
-#include <linux/blk.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <scsi/scsi.h> /* for SCSI_IOCTL_GET_IDLUN */
diff -Nru a/drivers/block/amiflop.c b/drivers/block/amiflop.c
--- a/drivers/block/amiflop.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/block/amiflop.c	Sat Jul 19 12:54:25 2003
@@ -79,7 +79,6 @@
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
 #include <asm/irq.h>
-#include <linux/blk.h>
 
 #undef DEBUG /* print _LOTS_ of infos */
 
diff -Nru a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c
--- a/drivers/block/as-iosched.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/block/as-iosched.c	Sat Jul 19 12:54:21 2003
@@ -12,7 +12,6 @@
 #include <linux/blkdev.h>
 #include <linux/elevator.h>
 #include <linux/bio.h>
-#include <linux/blk.h>
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -834,10 +833,11 @@
 							+ 2*1024*64);
 
 		aic->seek_samples += 256;
-		aic->seek_total += 256*seek_dist;
+		aic->seek_total += (u64)256*seek_dist;
 		if (aic->seek_samples) {
-			aic->seek_mean = aic->seek_total + 128;
-			sector_div(aic->seek_mean, aic->seek_samples);
+			u64 total = aic->seek_total + (aic->seek_samples>>1);
+			do_div(total, aic->seek_samples);
+			aic->seek_mean = (sector_t)total;
 		}
 		aic->seek_samples = (aic->seek_samples>>1)
 					+ (aic->seek_samples>>2);
@@ -1306,6 +1306,15 @@
 	as_update_arq(ad, arq); /* keep state machine up to date */
 }
 
+/*
+ * FIXME: HACK for AS requeue problems
+ */
+static void as_requeue_request(request_queue_t *q, struct request *rq)
+{
+	elv_completed_request(q, rq);
+	__elv_add_request(q, rq, 0, 0);
+}
+
 static void
 as_insert_request(request_queue_t *q, struct request *rq,
 			struct list_head *insert_here)
@@ -1821,6 +1830,7 @@
 	.elevator_next_req_fn =		as_next_request,
 	.elevator_add_req_fn =		as_insert_request,
 	.elevator_remove_req_fn =	as_remove_request,
+	.elevator_requeue_req_fn = 	as_requeue_request,
 	.elevator_queue_empty_fn =	as_queue_empty,
 	.elevator_completed_req_fn =	as_completed_request,
 	.elevator_former_req_fn =	as_former_request,
diff -Nru a/drivers/block/ataflop.c b/drivers/block/ataflop.c
--- a/drivers/block/ataflop.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/block/ataflop.c	Sat Jul 19 12:54:23 2003
@@ -91,7 +91,6 @@
 #include <asm/atariints.h>
 #include <asm/atari_stdma.h>
 #include <asm/atari_stram.h>
-#include <linux/blk.h>
 #include <linux/blkpg.h>
 
 #define	FD_MAX_UNITS 2
diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c
--- a/drivers/block/cciss.c	Sat Jul 19 12:54:29 2003
+++ b/drivers/block/cciss.c	Sat Jul 19 12:54:29 2003
@@ -41,7 +41,6 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-#include <linux/blk.h>
 #include <linux/blkdev.h>
 #include <linux/genhd.h>
 #include <linux/completion.h>
diff -Nru a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
--- a/drivers/block/cciss_scsi.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/block/cciss_scsi.c	Sat Jul 19 12:54:23 2003
@@ -712,7 +712,8 @@
 	sh->hostdata[0] = (unsigned long) hba[ctlr];
 	sh->irq = hba[ctlr]->intr;
 	sh->unique_id = sh->irq;
-	scsi_add_host(sh, &hba[ctlr]->pdev->dev);
+	scsi_add_host(sh, &hba[ctlr]->pdev->dev); /* XXX handle failure */
+	scsi_scan_host(sh);
 
 	return 1;
 }
diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
--- a/drivers/block/cpqarray.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/block/cpqarray.c	Sat Jul 19 12:54:23 2003
@@ -38,7 +38,6 @@
 #include <linux/init.h>
 #include <linux/hdreg.h>
 #include <linux/spinlock.h>
-#include <linux/blk.h>
 #include <linux/blkdev.h>
 #include <linux/genhd.h>
 #include <asm/uaccess.h>
diff -Nru a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c
--- a/drivers/block/cryptoloop.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/block/cryptoloop.c	Sat Jul 19 12:54:25 2003
@@ -26,7 +26,6 @@
 #include <linux/crypto.h>
 #include <linux/blkdev.h>
 #include <linux/loop.h>
-#include <linux/blk.h>
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
 
diff -Nru a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c
--- a/drivers/block/deadline-iosched.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/block/deadline-iosched.c	Sat Jul 19 12:54:27 2003
@@ -10,7 +10,6 @@
 #include <linux/blkdev.h>
 #include <linux/elevator.h>
 #include <linux/bio.h>
-#include <linux/blk.h>
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/slab.h>
diff -Nru a/drivers/block/elevator.c b/drivers/block/elevator.c
--- a/drivers/block/elevator.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/block/elevator.c	Sat Jul 19 12:54:26 2003
@@ -29,7 +29,6 @@
 #include <linux/blkdev.h>
 #include <linux/elevator.h>
 #include <linux/bio.h>
-#include <linux/blk.h>
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -214,6 +213,18 @@
 		e->elevator_merge_req_fn(q, rq, next);
 }
 
+void elv_requeue_request(request_queue_t *q, struct request *rq)
+{
+	/*
+	 * if iosched has an explicit requeue hook, then use that. otherwise
+	 * just put the request at the front of the queue
+	 */
+	if (q->elevator.elevator_requeue_req_fn)
+		q->elevator.elevator_requeue_req_fn(q, rq);
+	else
+		__elv_add_request(q, rq, 0, 0);
+}
+
 void __elv_add_request(request_queue_t *q, struct request *rq, int at_end,
 		       int plug)
 {
@@ -417,6 +428,7 @@
 
 EXPORT_SYMBOL(elv_add_request);
 EXPORT_SYMBOL(__elv_add_request);
+EXPORT_SYMBOL(elv_requeue_request);
 EXPORT_SYMBOL(elv_next_request);
 EXPORT_SYMBOL(elv_remove_request);
 EXPORT_SYMBOL(elv_queue_empty);
diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c
--- a/drivers/block/floppy.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/block/floppy.c	Sat Jul 19 12:54:23 2003
@@ -242,7 +242,7 @@
 #define LOCAL_END_REQUEST
 #define DEVICE_NAME "floppy"
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <linux/cdrom.h> /* for the compatibility eject ioctl */
 #include <linux/completion.h>
diff -Nru a/drivers/block/floppy98.c b/drivers/block/floppy98.c
--- a/drivers/block/floppy98.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/block/floppy98.c	Sat Jul 19 12:54:24 2003
@@ -277,7 +277,6 @@
 #define LOCAL_END_REQUEST
 #define DEVICE_NAME "floppy"
 
-#include <linux/blk.h>
 #include <linux/blkpg.h>
 #include <linux/cdrom.h> /* for the compatibility eject ioctl */
 #include <linux/completion.h>
diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c
--- a/drivers/block/genhd.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/block/genhd.c	Sat Jul 19 12:54:25 2003
@@ -7,7 +7,7 @@
 #include <linux/fs.h>
 #include <linux/genhd.h>
 #include <linux/kernel.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/seq_file.h>
diff -Nru a/drivers/block/ioctl.c b/drivers/block/ioctl.c
--- a/drivers/block/ioctl.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/block/ioctl.c	Sat Jul 19 12:54:22 2003
@@ -1,5 +1,5 @@
 #include <linux/sched.h>		/* for capable() */
-#include <linux/blk.h>			/* for set_device_ro() */
+#include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <linux/backing-dev.h>
 #include <linux/buffer_head.h>
@@ -166,13 +166,11 @@
 			return -EINVAL;
 		if (get_user(n, (int *) arg))
 			return -EFAULT;
-		if (n > PAGE_SIZE || n < 512 || (n & (n - 1)))
-			return -EINVAL;
 		if (bd_claim(bdev, &holder) < 0)
 			return -EBUSY;
-		set_blocksize(bdev, n);
+		ret = set_blocksize(bdev, n);
 		bd_release(bdev);
-		return 0;
+		return ret;
 	case BLKPG:
 		return blkpg_ioctl(bdev, (struct blkpg_ioctl_arg *) arg);
 	case BLKRRPART:
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/block/ll_rw_blk.c	Sat Jul 19 12:54:22 2003
@@ -17,7 +17,7 @@
 #include <linux/module.h>
 #include <linux/backing-dev.h>
 #include <linux/bio.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/highmem.h>
 #include <linux/mm.h>
 #include <linux/kernel_stat.h>
@@ -1494,6 +1494,23 @@
 
 	return rq;
 }
+/**
+ * blk_requeue_request - put a request back on queue
+ * @q:		request queue where request should be inserted
+ * @rq:		request to be inserted
+ *
+ * Description:
+ *    Drivers often keep queueing requests until the hardware cannot accept
+ *    more, when that condition happens we need to put the request back
+ *    on the queue. Must be called with queue lock held.
+ */
+void blk_requeue_request(request_queue_t *q, struct request *rq)
+{
+	if (blk_rq_tagged(rq))
+		blk_queue_end_tag(q, rq);
+
+	elv_requeue_request(q, rq);
+}
 
 /**
  * blk_insert_request - insert a special request in to a request queue
@@ -2730,6 +2747,7 @@
 EXPORT_SYMBOL(blk_get_request);
 EXPORT_SYMBOL(blk_put_request);
 EXPORT_SYMBOL(blk_insert_request);
+EXPORT_SYMBOL(blk_requeue_request);
 
 EXPORT_SYMBOL(blk_queue_prep_rq);
 EXPORT_SYMBOL(blk_queue_merge_bvec);
diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c
--- a/drivers/block/nbd.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/block/nbd.c	Sat Jul 19 12:54:23 2003
@@ -44,7 +44,6 @@
 
 #include <linux/major.h>
 
-#include <linux/blk.h>
 #include <linux/blkdev.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -55,8 +54,6 @@
 #include <linux/errno.h>
 #include <linux/file.h>
 #include <linux/ioctl.h>
-#include <linux/blkdev.h>
-#include <linux/blk.h>
 #include <net/sock.h>
 
 #include <linux/devfs_fs_kernel.h>
@@ -261,7 +258,8 @@
 	dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%luB)\n",
 			lo->disk->disk_name, req,
 			nbdcmd_to_ascii(nbd_cmd(req)),
-			req->sector << 9, req->nr_sectors << 9);
+			(unsigned long long)req->sector << 9,
+			req->nr_sectors << 9);
 	result = sock_xmit(sock, 1, &request, sizeof(request),
 			(nbd_cmd(req) == NBD_CMD_WRITE)? MSG_MORE: 0);
 	if (result <= 0) {
diff -Nru a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
--- a/drivers/block/paride/pcd.c	Sat Jul 19 12:54:29 2003
+++ b/drivers/block/paride/pcd.c	Sat Jul 19 12:54:30 2003
@@ -137,7 +137,7 @@
 #include <linux/delay.h>
 #include <linux/cdrom.h>
 #include <linux/spinlock.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <asm/uaccess.h>
 
 static spinlock_t pcd_lock;
diff -Nru a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
--- a/drivers/block/paride/pd.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/block/paride/pd.c	Sat Jul 19 12:54:27 2003
@@ -150,7 +150,7 @@
 #include <linux/delay.h>
 #include <linux/hdreg.h>
 #include <linux/cdrom.h>	/* for the eject ioctl */
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <asm/uaccess.h>
 
diff -Nru a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
--- a/drivers/block/paride/pf.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/block/paride/pf.c	Sat Jul 19 12:54:26 2003
@@ -150,7 +150,7 @@
 #include <linux/hdreg.h>
 #include <linux/cdrom.h>
 #include <linux/spinlock.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <asm/uaccess.h>
 
@@ -222,9 +222,6 @@
 #define ATAPI_READ_10		0x28
 #define ATAPI_WRITE_10		0x2a
 
-#ifdef MODULE
-void cleanup_module(void);
-#endif
 static int pf_open(struct inode *inode, struct file *file);
 static void do_pf_request(request_queue_t * q);
 static int pf_ioctl(struct inode *inode, struct file *file,
diff -Nru a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
--- a/drivers/block/ps2esdi.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/block/ps2esdi.c	Sat Jul 19 12:54:21 2003
@@ -38,7 +38,7 @@
 #include <linux/kernel.h>
 #include <linux/genhd.h>
 #include <linux/ps2esdi.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/mca.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
diff -Nru a/drivers/block/swim3.c b/drivers/block/swim3.c
--- a/drivers/block/swim3.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/block/swim3.c	Sat Jul 19 12:54:24 2003
@@ -24,7 +24,6 @@
 #include <linux/delay.h>
 #include <linux/fd.h>
 #include <linux/ioctl.h>
-#include <linux/blk.h>
 #include <linux/devfs_fs_kernel.h>
 #include <asm/io.h>
 #include <asm/dbdma.h>
diff -Nru a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c
--- a/drivers/block/swim_iop.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/block/swim_iop.c	Sat Jul 19 12:54:21 2003
@@ -30,7 +30,6 @@
 #include <linux/timer.h>
 #include <linux/delay.h>
 #include <linux/fd.h>
-#include <linux/blk.h>
 #include <linux/ioctl.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
diff -Nru a/drivers/block/umem.c b/drivers/block/umem.c
--- a/drivers/block/umem.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/block/umem.c	Sat Jul 19 12:54:30 2003
@@ -99,7 +99,7 @@
 
 static int major_nr;
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/blkpg.h>
 
 struct cardinfo {
diff -Nru a/drivers/block/xd.c b/drivers/block/xd.c
--- a/drivers/block/xd.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/block/xd.c	Sat Jul 19 12:54:27 2003
@@ -46,7 +46,7 @@
 #include <linux/init.h>
 #include <linux/wait.h>
 #include <linux/devfs_fs_kernel.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/blkpg.h>
 
 #include <asm/system.h>
diff -Nru a/drivers/block/z2ram.c b/drivers/block/z2ram.c
--- a/drivers/block/z2ram.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/block/z2ram.c	Sat Jul 19 12:54:26 2003
@@ -30,7 +30,6 @@
 #include <linux/major.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#include <linux/blk.h>
 #include <linux/init.h>
 #include <linux/module.h>
 
diff -Nru a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
--- a/drivers/cdrom/aztcd.c	Sat Jul 19 12:54:28 2003
+++ b/drivers/cdrom/aztcd.c	Sat Jul 19 12:54:28 2003
@@ -166,7 +166,7 @@
 */
 
 #include <linux/version.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include "aztcd.h"
 
 #include <linux/module.h>
diff -Nru a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
--- a/drivers/cdrom/cdrom.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/cdrom/cdrom.c	Sat Jul 19 12:54:23 2003
@@ -268,6 +268,7 @@
 #include <linux/init.h>
 #include <linux/fcntl.h>
 #include <linux/blkdev.h>
+#include <linux/times.h>
 
 #include <asm/uaccess.h>
 
@@ -2171,6 +2172,7 @@
 			return -ENOSYS;
 		cdinfo(CD_DO_IOCTL, "entering CDROM_SEND_PACKET\n"); 
 		IOCTL_IN(arg, struct cdrom_generic_command, cgc);
+		cgc.timeout = clock_t_to_jiffies(cgc.timeout);
 		return cdrom_do_cmd(cdi, &cgc);
 		}
 	case CDROM_NEXT_WRITABLE: {
diff -Nru a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
--- a/drivers/cdrom/cdu31a.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/cdrom/cdu31a.c	Sat Jul 19 12:54:26 2003
@@ -177,7 +177,7 @@
 #include "cdu31a.h"
 
 #define MAJOR_NR CDU31A_CDROM_MAJOR
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 
 #define CDU31A_READAHEAD 4	/* 128 sector, 64kB, 32 reads read-ahead */
 #define CDU31A_MAX_CONSECUTIVE_ATTENTIONS 10
diff -Nru a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
--- a/drivers/cdrom/cm206.c	Sat Jul 19 12:54:28 2003
+++ b/drivers/cdrom/cm206.c	Sat Jul 19 12:54:28 2003
@@ -199,7 +199,7 @@
 
 #define MAJOR_NR CM206_CDROM_MAJOR
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 
 #undef DEBUG
 #define STATISTICS		/* record times and frequencies of events */
diff -Nru a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
--- a/drivers/cdrom/gscd.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/cdrom/gscd.c	Sat Jul 19 12:54:21 2003
@@ -69,7 +69,7 @@
 #include <asm/uaccess.h>
 
 #define MAJOR_NR GOLDSTAR_CDROM_MAJOR
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #define gscd_port gscd		/* for compatible parameter passing with "insmod" */
 #include "gscd.h"
 
diff -Nru a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c
--- a/drivers/cdrom/mcd.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/cdrom/mcd.c	Sat Jul 19 12:54:25 2003
@@ -101,7 +101,7 @@
 #include <asm/io.h>
 #include <asm/current.h>
 #include <asm/uaccess.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 
 #define mcd_port mcd		/* for compatible parameter passing with "insmod" */
 #include "mcd.h"
diff -Nru a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
--- a/drivers/cdrom/mcdx.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/cdrom/mcdx.c	Sat Jul 19 12:54:25 2003
@@ -74,7 +74,7 @@
 
 #include <linux/major.h>
 #define MAJOR_NR MITSUMI_X_CDROM_MAJOR
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/devfs_fs_kernel.h>
 
 /* for compatible parameter passing with "insmod" */
diff -Nru a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
--- a/drivers/cdrom/optcd.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/cdrom/optcd.c	Sat Jul 19 12:54:23 2003
@@ -73,7 +73,7 @@
 #include <linux/init.h>
 
 #include <asm/io.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 
 #include <linux/cdrom.h>
 #include "optcd.h"
diff -Nru a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
--- a/drivers/cdrom/sbpcd.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/cdrom/sbpcd.c	Sat Jul 19 12:54:23 2003
@@ -387,7 +387,7 @@
 #include "sbpcd.h"
 
 #define MAJOR_NR MATSUSHITA_CDROM_MAJOR
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 
 /*==========================================================================*/
 #if SBPCD_DIS_IRQ
diff -Nru a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
--- a/drivers/cdrom/sjcd.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/cdrom/sjcd.c	Sat Jul 19 12:54:26 2003
@@ -74,7 +74,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include "sjcd.h"
 
 static int sjcd_present = 0;
diff -Nru a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
--- a/drivers/cdrom/sonycd535.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/cdrom/sonycd535.c	Sat Jul 19 12:54:24 2003
@@ -134,7 +134,7 @@
 #include <linux/cdrom.h>
 
 #define MAJOR_NR CDU535_CDROM_MAJOR
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 
 #define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */
 #include "sonycd535.h"
diff -Nru a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
--- a/drivers/char/agp/i460-agp.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/char/agp/i460-agp.c	Sat Jul 19 12:54:25 2003
@@ -608,7 +608,7 @@
 	.name		= "agpgart-intel-i460",
 	.id_table	= agp_intel_i460_pci_table,
 	.probe		= agp_intel_i460_probe,
-	.remove		= agp_intel_i460_remove,
+	.remove		= __devexit_p(agp_intel_i460_remove),
 };
 
 static int __init agp_intel_i460_init(void)
diff -Nru a/drivers/char/busmouse.c b/drivers/char/busmouse.c
--- a/drivers/char/busmouse.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/char/busmouse.c	Sat Jul 19 12:54:27 2003
@@ -357,25 +357,23 @@
 {
 	unsigned int msedev = MINOR_TO_MOUSE(ops->minor);
 	struct busmouse_data *mse;
-	int ret;
+	int ret = -EINVAL;
 
 	if (msedev >= NR_MICE) {
 		printk(KERN_ERR "busmouse: trying to allocate mouse on minor %d\n",
 		       ops->minor);
-		return -EINVAL;
+		goto out;
 	}
 
+	ret = -ENOMEM;
 	mse = kmalloc(sizeof(*mse), GFP_KERNEL);
 	if (!mse)
-		return -ENOMEM;
+		goto out;
 
 	down(&mouse_sem);
+	ret = -EBUSY;
 	if (busmouse_data[msedev])
-	{
-		up(&mouse_sem);
-		kfree(mse);
-		return -EBUSY;
-	}
+		goto freemem;
 
 	memset(mse, 0, sizeof(*mse));
 
@@ -386,14 +384,22 @@
 	mse->lock = (spinlock_t)SPIN_LOCK_UNLOCKED;
 	init_waitqueue_head(&mse->wait);
 
-	busmouse_data[msedev] = mse;
 
 	ret = misc_register(&mse->miscdev);
-	if (!ret)
-		ret = msedev;
+
+	if (ret < 0) 
+		goto freemem;
+
+	busmouse_data[msedev] = mse;
+	ret = msedev;
+out:
 	up(&mouse_sem);
-	
 	return ret;
+
+
+freemem:
+	kfree(mse);
+	goto out;
 }
 
 /**
diff -Nru a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c
--- a/drivers/char/ftape/lowlevel/fdc-io.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/char/ftape/lowlevel/fdc-io.c	Sat Jul 19 12:54:23 2003
@@ -66,6 +66,7 @@
 
 /*      Local vars.
  */
+static spinlock_t fdc_io_lock; 
 static unsigned int fdc_calibr_count;
 static unsigned int fdc_calibr_time;
 static int fdc_status;
@@ -89,14 +90,13 @@
 {
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&fdc_io_lock, flags);
 	if (count == 0) {
 		ft_expected_stray_interrupts = 0;
 	} else {
 		ft_expected_stray_interrupts += count;
 	}
-	restore_flags(flags);
+	spin_unlock_irqrestore(&fdc_io_lock, flags);
 }
 
 /*  Wait during a timeout period for a given FDC status.
@@ -194,8 +194,7 @@
 	TRACE_FUN(ft_t_any);
 
 	fdc_usec_wait(FT_RQM_DELAY);	/* wait for valid RQM status */
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&fdc_io_lock, flags);
 	if (!in_interrupt())
 		/* Yes, I know, too much comments inside this function
 		 * ...
@@ -242,12 +241,11 @@
 
 			}
 			fdc_usec_wait(FT_RQM_DELAY);	/* wait for valid RQM status */
-			save_flags(flags);
-			cli();
+			spin_lock_irqsave(&fdc_io_lock, flags);
 		}
 	fdc_status = inb(fdc.msr);
 	if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_IN_READY) {
-		restore_flags(flags);
+		spin_unlock_irqrestore(&fdc_io_lock, flags);
 		TRACE_ABORT(-EBUSY, ft_t_err, "fdc not ready");
 	} 
 	fdc_mode = *cmd_data;	/* used by isr */
@@ -289,7 +287,7 @@
 		last_time = ftape_timestamp();
 	}
 #endif
-	restore_flags(flags);
+	spin_unlock_irqrestore(&fdc_io_lock, flags);
 	TRACE_EXIT result;
 }
 
@@ -305,15 +303,14 @@
 	int retry = 0;
 	TRACE_FUN(ft_t_any);
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&fdc_io_lock, flags);
 	fdc_status = inb(fdc.msr);
 	if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_OUT_READY) {
 		TRACE(ft_t_err, "fdc not ready");
 		result = -EBUSY;
 	} else while (count) {
 		if (!(fdc_status & FDC_BUSY)) {
-			restore_flags(flags);
+			spin_unlock_irqrestore(&fdc_io_lock, flags);
 			TRACE_ABORT(-EIO, ft_t_err, "premature end of result phase");
 		}
 		result = fdc_read(res_data);
@@ -336,7 +333,7 @@
 			++res_data;
 		}
 	}
-	restore_flags(flags);
+	spin_unlock_irqrestore(&fdc_io_lock, flags);
 	fdc_usec_wait(FT_RQM_DELAY);	/* allow FDC to negate BSY */
 	TRACE_EXIT result;
 }
@@ -609,8 +606,7 @@
 	unsigned long flags;
 	TRACE_FUN(ft_t_any);
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&fdc_io_lock, flags);
 
 	fdc_dor_reset(1); /* keep unit selected */
 
@@ -629,7 +625,7 @@
 	 */
 	fdc_update_dsr();               /* restore data rate and precomp */
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&fdc_io_lock, flags);
 
         /*
          *	Wait for first polling cycle to complete
@@ -928,8 +924,7 @@
 	 */
         TRACE(ft_t_fdc_dma,
 	      "phys. addr. = %lx", virt_to_bus((void*) buff->ptr));
-	save_flags(flags);
-	cli();			/* could be called from ISR ! */
+	spin_lock_irqsave(&fdc_io_lock, flags);
 	fdc_setup_dma(DMA_MODE_WRITE, buff->ptr, FT_SECTORS_PER_SEGMENT * 4);
 	/* Issue FDC command to start reading/writing.
 	 */
@@ -937,7 +932,7 @@
 	out[4] = buff->gap3;
 	TRACE_CATCH(fdc_setup_error = fdc_command(out, sizeof(out)),
 		    restore_flags(flags); fdc_mode = fdc_idle);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&fdc_io_lock, flags);
 	TRACE_EXIT 0;
 }
 
@@ -977,11 +972,10 @@
 		break;
 	default:
 		TRACE_ABORT(-EIO,
-			    ft_t_bug, "bug: illegal operation parameter");
+			    ft_t_bug, "bug: invalid operation parameter");
 	}
 	TRACE(ft_t_fdc_dma, "phys. addr. = %lx",virt_to_bus((void*)buff->ptr));
-	save_flags(flags);
-	cli();			/* could be called from ISR ! */
+	spin_lock_irqsave(&fdc_io_lock, flags);
 	if (operation != FDC_VERIFY) {
 		fdc_setup_dma(dma_mode, buff->ptr,
 			      FT_SECTOR_SIZE * buff->sector_count);
@@ -999,7 +993,7 @@
 	out[8] = 0xff;		/* No limit to transfer size. */
 	TRACE(ft_t_fdc_dma, "C: 0x%02x, H: 0x%02x, R: 0x%02x, cnt: 0x%02x",
 		out[2], out[3], out[4], out[6] - out[4] + 1);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&fdc_io_lock, flags);
 	TRACE_CATCH(fdc_setup_error = fdc_command(out, 9),fdc_mode = fdc_idle);
 	TRACE_EXIT 0;
 }
diff -Nru a/drivers/char/ftape/lowlevel/ftape-calibr.c b/drivers/char/ftape/lowlevel/ftape-calibr.c
--- a/drivers/char/ftape/lowlevel/ftape-calibr.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/char/ftape/lowlevel/ftape-calibr.c	Sat Jul 19 12:54:24 2003
@@ -49,6 +49,8 @@
 static unsigned long ps_per_cycle = 0;
 #endif
 
+static spinlock_t calibr_lock;
+
 /*
  * Note: On Intel PCs, the clock ticks at 100 Hz (HZ==100) which is
  * too slow for certain timeouts (and that clock doesn't even tick
@@ -75,13 +77,12 @@
 	__u16 lo;
 	__u16 hi;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&calibr_lock, flags);
 	outb_p(0x00, 0x43);	/* latch the count ASAP */
 	lo = inb_p(0x40);	/* read the latched count */
 	lo |= inb(0x40) << 8;
 	hi = jiffies;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&calibr_lock, flags);
 	return ((hi + 1) * (unsigned int) LATCH) - lo;  /* downcounter ! */
 #endif
 }
@@ -94,12 +95,11 @@
 	unsigned int count;
  	unsigned long flags;
  
- 	save_flags(flags);
- 	cli();
+	spin_lock_irqsave(&calibr_lock, flags);
  	outb_p(0x00, 0x43);	/* latch the count ASAP */
 	count = inb_p(0x40);	/* read the latched count */
 	count |= inb(0x40) << 8;
- 	restore_flags(flags);
+	spin_unlock_irqrestore(&calibr_lock, flags);
 	return (LATCH - count);	/* normal: downcounter */
 #endif
 }
@@ -150,14 +150,13 @@
 	int status;
 	TRACE_FUN(ft_t_any);
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&calibr_lock, flags);
 	t0 = short_ftape_timestamp();
 	for (i = 0; i < 1000; ++i) {
 		status = inb(fdc.msr);
 	}
 	t1 = short_ftape_timestamp();
-	restore_flags(flags);
+	spin_unlock_irqrestore(&calibr_lock, flags);
 	TRACE(ft_t_info, "inb() duration: %d nsec", ftape_timediff(t0, t1));
 	TRACE_EXIT;
 }
@@ -241,8 +240,7 @@
 
 		*calibr_count =
 		*calibr_time = count;	/* set TC to 1 */
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&calibr_lock, flags);
 		fun(0);		/* dummy, get code into cache */
 		t0 = short_ftape_timestamp();
 		fun(0);		/* overhead + one test */
@@ -252,7 +250,7 @@
 		fun(count);		/* overhead + count tests */
 		t1 = short_ftape_timestamp();
 		multiple = diff(t0, t1);
-		restore_flags(flags);
+		spin_unlock_irqrestore(&calibr_lock, flags);
 		time = ftape_timediff(0, multiple - once);
 		tc = (1000 * time) / (count - 1);
 		TRACE(ft_t_any, "once:%3d us,%6d times:%6d us, TC:%5d ns",
diff -Nru a/drivers/char/ftape/lowlevel/ftape-format.c b/drivers/char/ftape/lowlevel/ftape-format.c
--- a/drivers/char/ftape/lowlevel/ftape-format.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/char/ftape/lowlevel/ftape-format.c	Sat Jul 19 12:54:25 2003
@@ -44,6 +44,8 @@
 #define FT_FMT_SEGS_PER_BUF (FT_BUFF_SIZE/(4*FT_SECTORS_PER_SEGMENT))
 #endif
 
+static spinlock_t ftape_format_lock;
+
 /*
  *  first segment of the new buffer
  */
@@ -129,9 +131,9 @@
 	head->status = formatting;
 	TRACE_CATCH(ftape_seek_head_to_track(track),);
 	TRACE_CATCH(ftape_command(QIC_LOGICAL_FORWARD),);
-	save_flags(flags); cli();
+	spin_lock_irqsave(&ftape_format_lock, flags);
 	TRACE_CATCH(fdc_setup_formatting(head), restore_flags(flags));
-	restore_flags(flags);	
+	spin_unlock_irqrestore(&ftape_format_lock, flags);
 	TRACE_EXIT 0;
 }
 
diff -Nru a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c
--- a/drivers/char/ftape/zftape/zftape-init.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/char/ftape/zftape/zftape-init.c	Sat Jul 19 12:54:24 2003
@@ -118,7 +118,7 @@
 	     > 
 	    FTAPE_SEL_D) {
 		clear_bit(0,&busy_flag);
-		TRACE_ABORT(-ENXIO, ft_t_err, "failed: illegal unit nr");
+		TRACE_ABORT(-ENXIO, ft_t_err, "failed: invalid unit nr");
 	}
 	orig_sigmask = current->blocked;
 	sigfillset(&current->blocked);
diff -Nru a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c
--- a/drivers/char/ip2/i2lib.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/char/ip2/i2lib.c	Sat Jul 19 12:54:30 2003
@@ -1089,7 +1089,7 @@
 
 			// Move the data
 			if ( user ) {
-				COPY_FROM_USER(rc, (char*)(DATA_OF(pInsert)), pSource,
+				rc = copy_from_user((char*)(DATA_OF(pInsert)), pSource,
 						amountToMove );
 			} else {
 				memcpy( (char*)(DATA_OF(pInsert)), pSource, amountToMove );
diff -Nru a/drivers/char/ip2/i2os.h b/drivers/char/ip2/i2os.h
--- a/drivers/char/ip2/i2os.h	Sat Jul 19 12:54:25 2003
+++ b/drivers/char/ip2/i2os.h	Sat Jul 19 12:54:25 2003
@@ -19,8 +19,6 @@
 #ifndef I2OS_H    /* To prevent multiple includes */
 #define I2OS_H 1
 
-#define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq))
-
 //-------------------------------------------------
 // Required Includes
 //-------------------------------------------------
@@ -45,22 +43,6 @@
 //--------------------------------------------
 // Interrupt control
 //--------------------------------------------
-
-#if LINUX_VERSION_CODE < 0x00020100
-typedef int spinlock_t;
-#define spin_lock_init() 
-#define spin_lock(a)
-#define spin_unlock(a)
-#define spin_lock_irqsave(a,b)			{save_flags((b));cli();}
-#define spin_unlock_irqrestore(a,b)		{restore_flags((b));}
-#define write_lock_irqsave(a,b)			spin_lock_irqsave(a,b)
-#define write_unlock_irqrestore(a,b)	spin_unlock_irqrestore(a,b)
-#define read_lock_irqsave(a,b)			spin_lock_irqsave(a,b)
-#define read_unlock_irqrestore(a,b)		spin_unlock_irqrestore(a,b)
-#endif
-
-//#define SAVE_AND_DISABLE_INTS(a,b)	spin_lock_irqsave(a,b)
-//#define RESTORE_INTS(a,b)         	spin_unlock_irqrestore(a,b)
 
 #define LOCK_INIT(a)	rwlock_init(a)
 
diff -Nru a/drivers/char/ip2.c b/drivers/char/ip2.c
--- a/drivers/char/ip2.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/char/ip2.c	Sat Jul 19 12:54:25 2003
@@ -38,16 +38,14 @@
 
 static int poll_only = 0;
 
-#	if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
-		MODULE_AUTHOR("Doug McNash");
-		MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
-		MODULE_PARM(irq,"1-"__MODULE_STRING(IP2_MAX_BOARDS) "i");
-		MODULE_PARM_DESC(irq,"Interrupts for IntelliPort Cards");
-		MODULE_PARM(io,"1-"__MODULE_STRING(IP2_MAX_BOARDS) "i");
-		MODULE_PARM_DESC(io,"I/O ports for IntelliPort Cards");
-		MODULE_PARM(poll_only,"1i");
-		MODULE_PARM_DESC(poll_only,"Do not use card interrupts");
-#	endif	/* LINUX_VERSION */
+MODULE_AUTHOR("Doug McNash");
+MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
+MODULE_PARM(irq,"1-"__MODULE_STRING(IP2_MAX_BOARDS) "i");
+MODULE_PARM_DESC(irq,"Interrupts for IntelliPort Cards");
+MODULE_PARM(io,"1-"__MODULE_STRING(IP2_MAX_BOARDS) "i");
+MODULE_PARM_DESC(io,"I/O ports for IntelliPort Cards");
+MODULE_PARM(poll_only,"1i");
+MODULE_PARM_DESC(poll_only,"Do not use card interrupts");
 
 
 //======================================================================
diff -Nru a/drivers/char/ip2main.c b/drivers/char/ip2main.c
--- a/drivers/char/ip2main.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/char/ip2main.c	Sat Jul 19 12:54:30 2003
@@ -83,7 +83,6 @@
 /* Includes */
 /************/
 #include <linux/config.h>
-// Uncomment the following if you want it compiled with modversions
 
 #include <linux/version.h>
 
@@ -120,82 +119,11 @@
 #include <asm/irq.h>
 #include <asm/bitops.h>
 
-#ifndef KERNEL_VERSION
-#define KERNEL_VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq))
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
-#	include <linux/vmalloc.h>
-#	include <linux/init.h>
-#	include <asm/serial.h>
-#else
-#	include <linux/bios32.h>
-#endif
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <asm/serial.h>
 
-// These VERSION switches maybe inexact because I simply don't know
-// when the various features appeared in the 2.1.XX kernels.
-// They are good enough for 2.0 vs 2.2 and if you are fooling with
-// the 2.1.XX stuff then it would be trivial for you to fix.
-// Most of these macros were stolen from some other drivers
-// so blame them.
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,4)
-#	define GET_USER(error,value,addr) error = get_user(value,addr)
-#	define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0
-#	define PUT_USER(error,value,addr) error = put_user(value,addr)
-#	define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0
-
-#	if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,5)
-#		include <asm/uaccess.h>
-#		define		pcibios_strerror(status)	\
-					printk( KERN_ERR "IP2: PCI error 0x%x \n", status );
-#	endif
-
-#else  /* 2.0.x and 2.1.x before 2.1.4 */
-
-#	define		proc_register_dynamic(a,b) proc_register(a,b) 
-
-#	define GET_USER(error,value,addr)					  \
-	do {									  \
-		error = verify_area (VERIFY_READ, (void *) addr, sizeof (value)); \
-		if (error == 0)							  \
-			value = get_user(addr);					  \
-	} while (0)
-
-#	define COPY_FROM_USER(error,dest,src,size)				  \
-	do {									  \
-		error = verify_area (VERIFY_READ, (void *) src, size);		  \
-		if (error == 0)							  \
-			memcpy_fromfs (dest, src, size);			  \
-	} while (0)
-
-#	define PUT_USER(error,value,addr)					   \
-	do {									   \
-		error = verify_area (VERIFY_WRITE, (void *) addr, sizeof (value)); \
-		if (error == 0)							   \
-			put_user (value, addr);					   \
-	} while (0)
-
-#	define COPY_TO_USER(error,dest,src,size)				  \
-	do {									  \
-		error = verify_area (VERIFY_WRITE, (void *) dest, size);		  \
-		if (error == 0)							  \
-			memcpy_tofs (dest, src, size);				  \
-	} while (0)
-
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
-#define __init
-#define __initfunc(a) a
-#define __initdata
-#define ioremap(a,b) vremap((a),(b))
-#define iounmap(a) vfree((a))
-#define SERIAL_TYPE_NORMAL	1
-#define schedule_timeout(a){current->timeout = jiffies + (a); schedule();}
-#define signal_pending(a) ((a)->signal & ~(a)->blocked)
-#define in_interrupt()	intr_count
-#endif
+#include <asm/uaccess.h>
 
 #include "./ip2/ip2types.h"
 #include "./ip2/ip2trace.h"
@@ -276,11 +204,7 @@
 static int get_serial_info(i2ChanStrPtr, struct serial_struct *);
 static int set_serial_info(i2ChanStrPtr, struct serial_struct *);
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
-static int     ip2_ipl_read(struct inode *, char *, size_t , loff_t *);
-#else
-static ssize_t ip2_ipl_read(struct file *, char *, size_t, loff_t *) ;
-#endif
+static ssize_t ip2_ipl_read(struct file *, char *, size_t, loff_t *);
 static ssize_t ip2_ipl_write(struct file *, const char *, size_t, loff_t *);
 static int ip2_ipl_ioctl(struct inode *, struct file *, UINT, ULONG);
 static int ip2_ipl_open(struct inode *, struct file *);
@@ -354,9 +278,6 @@
 #define DBG_CNT(s)
 #endif
 
-#define MIN(a,b)	( ( (a) < (b) ) ? (a) : (b) )
-#define MAX(a,b)	( ( (a) > (b) ) ? (a) : (b) )
-
 /********/
 /* Code */
 /********/
@@ -366,12 +287,9 @@
 #include "./ip2/i2lib.c"      /* High level interface services */
 
 /* Configuration area for modprobe */
-#ifdef MODULE
-#	if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
-		MODULE_AUTHOR("Doug McNash");
-		MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
-#	endif	/* LINUX_VERSION */
-#endif	/* MODULE */
+
+MODULE_AUTHOR("Doug McNash");
+MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
 
 static int poll_only = 0;
 
@@ -660,53 +578,6 @@
 			break;
 		case PCI:
 #ifdef CONFIG_PCI
-#if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */
-			if (pcibios_present()) {
-				unsigned char pci_bus, pci_devfn;
-				int Pci_index = 0;
-				status = pcibios_find_device(PCI_VENDOR_ID_COMPUTONE,
-							  PCI_DEVICE_ID_COMPUTONE_IP2EX, Pci_index,
-							  &pci_bus, &pci_devfn);
-				if (status == 0) {
-					unsigned int addr;
-					unsigned char pci_irq;
-
-					ip2config.type[i] = PCI;
-					/* 
-					 * Update Pci_index, so that the next time we go
-					 * searching for a PCI board we find a different
-					 * one.
-					 */
-					++Pci_index;
-
-					pcibios_read_config_dword(pci_bus, pci_devfn,
-								  PCI_BASE_ADDRESS_1, &addr);
-					if ( addr & 1 ) {
-						ip2config.addr[i]=(USHORT)(addr&0xfffe);
-					} else {
-						printk( KERN_ERR "IP2: PCI I/O address error\n");
-					}
-					pcibios_read_config_byte(pci_bus, pci_devfn,
-								  PCI_INTERRUPT_LINE, &pci_irq);
-
-//		If the PCI BIOS assigned it, lets try and use it.  If we
-//		can't acquire it or it screws up, deal with it then.
-
-//					if (!is_valid_irq(pci_irq)) {
-//						printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq);
-//						pci_irq = 0;
-//					}
-					ip2config.irq[i] = pci_irq;
-				} else {	// ann error
-					ip2config.addr[i] = 0;
-					if (status == PCIBIOS_DEVICE_NOT_FOUND) {
-						printk( KERN_ERR "IP2: PCI board %d not found\n", i );
-					} else {
-						pcibios_strerror(status);
-					}
-				} 
-			} 
-#else /* LINUX_VERSION_CODE > 2.1.99 */
 			{
 				struct pci_dev *pci_dev_i = NULL;
 				pci_dev_i = pci_find_device(PCI_VENDOR_ID_COMPUTONE,
@@ -739,11 +610,10 @@
 					if (status == PCIBIOS_DEVICE_NOT_FOUND) {
 						printk( KERN_ERR "IP2: PCI board %d not found\n", i );
 					} else {
-						pcibios_strerror(status);
+						printk( KERN_ERR "IP2: PCI error 0x%x \n", status );
 					}
 				} 
 			}
-#endif	/* ! 2_0_X */
 #else
 			printk( KERN_ERR "IP2: PCI card specified but PCI support not\n");
 			printk( KERN_ERR "IP2: configured in this kernel.\n");
@@ -2193,7 +2063,7 @@
 
 		ip2trace (CHANN, ITRC_IOCTL, 6, 1, rc );
 
-			PUT_USER(rc,C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
+			rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
 		if (rc)	
 			return rc;
 	break;
@@ -2202,7 +2072,7 @@
 
 		ip2trace (CHANN, ITRC_IOCTL, 7, 1, rc );
 
-		GET_USER(rc,arg,(unsigned long *) arg);
+		rc = get_user(arg,(unsigned long *) arg);
 		if (rc) 
 			return rc;
 		tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL)
@@ -2243,7 +2113,7 @@
 			return -EINTR;
 		}
 #endif
-		PUT_USER(rc,
+		rc = put_user(
 				    ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0)
 				  | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0)
 				  | ((pCh->dataSetIn  & I2_DCD) ? TIOCM_CAR : 0)
@@ -2333,17 +2203,17 @@
 		cnow = pCh->icount;
 		restore_flags(flags);
 		p_cuser = (struct serial_icounter_struct *) arg;
-		PUT_USER(rc,cnow.cts, &p_cuser->cts);
-		PUT_USER(rc,cnow.dsr, &p_cuser->dsr);
-		PUT_USER(rc,cnow.rng, &p_cuser->rng);
-		PUT_USER(rc,cnow.dcd, &p_cuser->dcd);
-		PUT_USER(rc,cnow.rx, &p_cuser->rx);
-		PUT_USER(rc,cnow.tx, &p_cuser->tx);
-		PUT_USER(rc,cnow.frame, &p_cuser->frame);
-		PUT_USER(rc,cnow.overrun, &p_cuser->overrun);
-		PUT_USER(rc,cnow.parity, &p_cuser->parity);
-		PUT_USER(rc,cnow.brk, &p_cuser->brk);
-		PUT_USER(rc,cnow.buf_overrun, &p_cuser->buf_overrun);
+		rc = put_user(cnow.cts, &p_cuser->cts);
+		rc = put_user(cnow.dsr, &p_cuser->dsr);
+		rc = put_user(cnow.rng, &p_cuser->rng);
+		rc = put_user(cnow.dcd, &p_cuser->dcd);
+		rc = put_user(cnow.rx, &p_cuser->rx);
+		rc = put_user(cnow.tx, &p_cuser->tx);
+		rc = put_user(cnow.frame, &p_cuser->frame);
+		rc = put_user(cnow.overrun, &p_cuser->overrun);
+		rc = put_user(cnow.parity, &p_cuser->parity);
+		rc = put_user(cnow.brk, &p_cuser->brk);
+		rc = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
 		break;
 
 	/*
@@ -2387,7 +2257,7 @@
 	int rc;
 	unsigned int arg;
 
-	GET_USER(rc,arg,value);
+	rc = get_user(arg,value);
 	if (rc)
 		return rc;
 	switch(cmd) {
@@ -2469,7 +2339,7 @@
 	tmp.close_delay = pCh->ClosingDelay;
 	tmp.closing_wait = pCh->ClosingWaitTime;
 	tmp.custom_divisor = pCh->BaudDivisor;
-   	COPY_TO_USER(rc,retinfo,&tmp,sizeof(*retinfo));
+   	rc = copy_to_user(retinfo,&tmp,sizeof(*retinfo));
    return rc;
 }
 
@@ -2489,15 +2359,15 @@
 {
 	struct serial_struct ns;
 	int   old_flags, old_baud_divisor;
-	int     rc = 0;
 
 	if ( !new_info ) {
 		return -EFAULT;
 	}
-	COPY_FROM_USER(rc, &ns, new_info, sizeof (ns) );
-	if (rc) {
-		return rc;
+
+	if (copy_from_user(&ns, new_info, sizeof (ns))) {
+		return -EFAULT;
 	}
+
 	/*
 	 * We don't allow setserial to change IRQ, board address, type or baud
 	 * base. Also line nunber as such is meaningless but we use it for our
@@ -2537,7 +2407,7 @@
 		set_params( pCh, NULL );
 	}
 
-	return rc;
+	return 0;
 }
 
 /******************************************************************************/
@@ -2860,16 +2730,10 @@
 /******************************************************************************/
 
 static 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
-int
-ip2_ipl_read(struct inode *pInode, char *pData, size_t count, loff_t *off )
-	unsigned int minor = minor( pInode->i_rdev );
-#else
 ssize_t
 ip2_ipl_read(struct file *pFile, char *pData, size_t count, loff_t *off )
 {
 	unsigned int minor = minor( pFile->f_dentry->d_inode->i_rdev );
-#endif
 	int rc = 0;
 
 #ifdef IP2DEBUG_IPL
@@ -2904,7 +2768,7 @@
 {
 #ifdef DEBUG_FIFO
 	int rc;
-	COPY_TO_USER(rc, pData, DBGBuf, count);
+	rc = copy_to_user(pData, DBGBuf, count);
 
 	printk(KERN_DEBUG "Last index %d\n", I );
 
@@ -2925,10 +2789,10 @@
 	if ( count < (sizeof(int) * 6) ) {
 		return -EIO;
 	}
-	PUT_USER(rc, tracewrap, pIndex );
-	PUT_USER(rc, TRACEMAX, ++pIndex );
-	PUT_USER(rc, tracestrip, ++pIndex );
-	PUT_USER(rc, tracestuff, ++pIndex );
+	rc = put_user(tracewrap, pIndex );
+	rc = put_user(TRACEMAX, ++pIndex );
+	rc = put_user(tracestrip, ++pIndex );
+	rc = put_user(tracestuff, ++pIndex );
 	pData += sizeof(int) * 6;
 	count -= sizeof(int) * 6;
 
@@ -2941,7 +2805,7 @@
 	}
 	chunk = TRACEMAX - tracestrip;
 	if ( dumpcount > chunk ) {
-		COPY_TO_USER(rc, pData, &tracebuf[tracestrip],
+		rc = copy_to_user(pData, &tracebuf[tracestrip],
 			      chunk * sizeof(tracebuf[0]) );
 		pData += chunk * sizeof(tracebuf[0]);
 		tracestrip = 0;
@@ -2949,13 +2813,13 @@
 	} else {
 		chunk = dumpcount;
 	}
-	COPY_TO_USER(rc, pData, &tracebuf[tracestrip],
+	rc = copy_to_user(pData, &tracebuf[tracestrip],
 		      chunk * sizeof(tracebuf[0]) );
 	tracestrip += chunk;
 	tracewrap = 0;
 
-	PUT_USER(rc, tracestrip, ++pIndex );
-	PUT_USER(rc, tracestuff, ++pIndex );
+	rc = put_user(tracestrip, ++pIndex );
+	rc = put_user(tracestuff, ++pIndex );
 
 	return dumpcount;
 #else
@@ -3019,15 +2883,15 @@
 	case 13:
 		switch ( cmd ) {
 		case 64:	/* Driver - ip2stat */
-			PUT_USER(rc, ip2_tty_driver->refcount, pIndex++ );
-			PUT_USER(rc, irq_counter, pIndex++  );
-			PUT_USER(rc, bh_counter, pIndex++  );
+			rc = put_user(ip2_tty_driver->refcount, pIndex++ );
+			rc = put_user(irq_counter, pIndex++  );
+			rc = put_user(bh_counter, pIndex++  );
 			break;
 
 		case 65:	/* Board  - ip2stat */
 			if ( pB ) {
-				COPY_TO_USER(rc, (char*)arg, (char*)pB, sizeof(i2eBordStr) );
-				PUT_USER(rc, INB(pB->i2eStatus),
+				rc = copy_to_user((char*)arg, (char*)pB, sizeof(i2eBordStr) );
+				rc = put_user(INB(pB->i2eStatus),
 					(ULONG*)(arg + (ULONG)(&pB->i2eStatus) - (ULONG)pB ) );
 			} else {
 				rc = -ENODEV;
@@ -3039,7 +2903,7 @@
 				pCh = DevTable[cmd];
 				if ( pCh )
 				{
-					COPY_TO_USER(rc, (char*)arg, (char*)pCh, sizeof(i2ChanStr) );
+					rc = copy_to_user((char*)arg, (char*)pCh, sizeof(i2ChanStr) );
 				} else {
 					rc = -ENODEV;
 				}
@@ -3054,60 +2918,60 @@
 		break;
 	case 3:	    // Trace device
 		if ( cmd == 1 ) {
-			PUT_USER(rc, iiSendPendingMail, pIndex++ );
-			PUT_USER(rc, i2InitChannels, pIndex++ );
-			PUT_USER(rc, i2QueueNeeds, pIndex++ );
-			PUT_USER(rc, i2QueueCommands, pIndex++ );
-			PUT_USER(rc, i2GetStatus, pIndex++ );
-			PUT_USER(rc, i2Input, pIndex++ );
-			PUT_USER(rc, i2InputFlush, pIndex++ );
-			PUT_USER(rc, i2Output, pIndex++ );
-			PUT_USER(rc, i2FlushOutput, pIndex++ );
-			PUT_USER(rc, i2DrainWakeup, pIndex++ );
-			PUT_USER(rc, i2DrainOutput, pIndex++ );
-			PUT_USER(rc, i2OutputFree, pIndex++ );
-			PUT_USER(rc, i2StripFifo, pIndex++ );
-			PUT_USER(rc, i2StuffFifoBypass, pIndex++ );
-			PUT_USER(rc, i2StuffFifoFlow, pIndex++ );
-			PUT_USER(rc, i2StuffFifoInline, pIndex++ );
-			PUT_USER(rc, i2ServiceBoard, pIndex++ );
-			PUT_USER(rc, serviceOutgoingFifo, pIndex++ );
-			// PUT_USER(rc, ip2_init, pIndex++ );
-			PUT_USER(rc, ip2_init_board, pIndex++ );
-			PUT_USER(rc, find_eisa_board, pIndex++ );
-			PUT_USER(rc, set_irq, pIndex++ );
-			PUT_USER(rc, ip2_interrupt, pIndex++ );
-			PUT_USER(rc, ip2_poll, pIndex++ );
-			PUT_USER(rc, service_all_boards, pIndex++ );
-			PUT_USER(rc, do_input, pIndex++ );
-			PUT_USER(rc, do_status, pIndex++ );
+			rc = put_user(iiSendPendingMail, pIndex++ );
+			rc = put_user(i2InitChannels, pIndex++ );
+			rc = put_user(i2QueueNeeds, pIndex++ );
+			rc = put_user(i2QueueCommands, pIndex++ );
+			rc = put_user(i2GetStatus, pIndex++ );
+			rc = put_user(i2Input, pIndex++ );
+			rc = put_user(i2InputFlush, pIndex++ );
+			rc = put_user(i2Output, pIndex++ );
+			rc = put_user(i2FlushOutput, pIndex++ );
+			rc = put_user(i2DrainWakeup, pIndex++ );
+			rc = put_user(i2DrainOutput, pIndex++ );
+			rc = put_user(i2OutputFree, pIndex++ );
+			rc = put_user(i2StripFifo, pIndex++ );
+			rc = put_user(i2StuffFifoBypass, pIndex++ );
+			rc = put_user(i2StuffFifoFlow, pIndex++ );
+			rc = put_user(i2StuffFifoInline, pIndex++ );
+			rc = put_user(i2ServiceBoard, pIndex++ );
+			rc = put_user(serviceOutgoingFifo, pIndex++ );
+			// rc = put_user(ip2_init, pIndex++ );
+			rc = put_user(ip2_init_board, pIndex++ );
+			rc = put_user(find_eisa_board, pIndex++ );
+			rc = put_user(set_irq, pIndex++ );
+			rc = put_user(ip2_interrupt, pIndex++ );
+			rc = put_user(ip2_poll, pIndex++ );
+			rc = put_user(service_all_boards, pIndex++ );
+			rc = put_user(do_input, pIndex++ );
+			rc = put_user(do_status, pIndex++ );
 #ifndef IP2DEBUG_OPEN
-			PUT_USER(rc, 0, pIndex++ );
+			rc = put_user(0, pIndex++ );
 #else
-			PUT_USER(rc, open_sanity_check, pIndex++ );
+			rc = put_user(open_sanity_check, pIndex++ );
 #endif
-			PUT_USER(rc, ip2_open, pIndex++ );
-			PUT_USER(rc, ip2_close, pIndex++ );
-			PUT_USER(rc, ip2_hangup, pIndex++ );
-			PUT_USER(rc, ip2_write, pIndex++ );
-			PUT_USER(rc, ip2_putchar, pIndex++ );
-			PUT_USER(rc, ip2_flush_chars, pIndex++ );
-			PUT_USER(rc, ip2_write_room, pIndex++ );
-			PUT_USER(rc, ip2_chars_in_buf, pIndex++ );
-			PUT_USER(rc, ip2_flush_buffer, pIndex++ );
-
-			//PUT_USER(rc, ip2_wait_until_sent, pIndex++ );
-			PUT_USER(rc, 0, pIndex++ );
-
-			PUT_USER(rc, ip2_throttle, pIndex++ );
-			PUT_USER(rc, ip2_unthrottle, pIndex++ );
-			PUT_USER(rc, ip2_ioctl, pIndex++ );
-			PUT_USER(rc, set_modem_info, pIndex++ );
-			PUT_USER(rc, get_serial_info, pIndex++ );
-			PUT_USER(rc, set_serial_info, pIndex++ );
-			PUT_USER(rc, ip2_set_termios, pIndex++ );
-			PUT_USER(rc, ip2_set_line_discipline, pIndex++ );
-			PUT_USER(rc, set_params, pIndex++ );
+			rc = put_user(ip2_open, pIndex++ );
+			rc = put_user(ip2_close, pIndex++ );
+			rc = put_user(ip2_hangup, pIndex++ );
+			rc = put_user(ip2_write, pIndex++ );
+			rc = put_user(ip2_putchar, pIndex++ );
+			rc = put_user(ip2_flush_chars, pIndex++ );
+			rc = put_user(ip2_write_room, pIndex++ );
+			rc = put_user(ip2_chars_in_buf, pIndex++ );
+			rc = put_user(ip2_flush_buffer, pIndex++ );
+
+			//rc = put_user(ip2_wait_until_sent, pIndex++ );
+			rc = put_user(0, pIndex++ );
+
+			rc = put_user(ip2_throttle, pIndex++ );
+			rc = put_user(ip2_unthrottle, pIndex++ );
+			rc = put_user(ip2_ioctl, pIndex++ );
+			rc = put_user(set_modem_info, pIndex++ );
+			rc = put_user(get_serial_info, pIndex++ );
+			rc = put_user(set_serial_info, pIndex++ );
+			rc = put_user(ip2_set_termios, pIndex++ );
+			rc = put_user(ip2_set_line_discipline, pIndex++ );
+			rc = put_user(set_params, pIndex++ );
 		} else {
 			rc = -EINVAL;
 		}
diff -Nru a/drivers/char/istallion.c b/drivers/char/istallion.c
--- a/drivers/char/istallion.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/char/istallion.c	Sat Jul 19 12:54:25 2003
@@ -650,8 +650,6 @@
  */
 
 #ifdef MODULE
-int		init_module(void);
-void		cleanup_module(void);
 static void	stli_argbrds(void);
 static int	stli_parsebrd(stlconf_t *confp, char **argp);
 
diff -Nru a/drivers/char/moxa.c b/drivers/char/moxa.c
--- a/drivers/char/moxa.c	Sat Jul 19 12:54:29 2003
+++ b/drivers/char/moxa.c	Sat Jul 19 12:54:29 2003
@@ -216,10 +216,7 @@
 static struct semaphore moxaBuffSem;
 
 int moxa_init(void);
-#ifdef MODULE
-int init_module(void);
-void cleanup_module(void);
-#endif
+
 /*
  * static functions:
  */
diff -Nru a/drivers/char/nwbutton.h b/drivers/char/nwbutton.h
--- a/drivers/char/nwbutton.h	Sat Jul 19 12:54:24 2003
+++ b/drivers/char/nwbutton.h	Sat Jul 19 12:54:24 2003
@@ -32,10 +32,6 @@
 int button_add_callback (void (*callback) (void), int count);
 int button_del_callback (void (*callback) (void));
 static void button_consume_callbacks (int bpcount);
-#ifdef MODULE
-int init_module (void);
-void cleanup_module (void);
-#endif /* MODULE */
 
 #else /* Not compiling the driver itself */
 
diff -Nru a/drivers/char/pcxx.c b/drivers/char/pcxx.c
--- a/drivers/char/pcxx.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/char/pcxx.c	Sat Jul 19 12:54:25 2003
@@ -209,17 +209,9 @@
 
 #ifdef MODULE
 
-/*
- * pcxe_init() is our init_module():
- */
-#define pcxe_init init_module
-
-void	cleanup_module(void);
-
-
 /*****************************************************************************/
 
-void cleanup_module()
+static void pcxe_cleanup()
 {
 
 	unsigned long	flags;
@@ -240,6 +232,12 @@
 	kfree(digi_channels);
 	restore_flags(flags);
 }
+
+/*
+ * pcxe_init() is our init_module():
+ */
+module_init(pcxe_init);
+module_cleanup(pcxe_cleanup);
 #endif
 
 static inline struct channel *chan(register struct tty_struct *tty)
diff -Nru a/drivers/char/stallion.c b/drivers/char/stallion.c
--- a/drivers/char/stallion.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/char/stallion.c	Sat Jul 19 12:54:26 2003
@@ -472,8 +472,6 @@
  */
 
 #ifdef MODULE
-int		init_module(void);
-void		cleanup_module(void);
 static void	stl_argbrds(void);
 static int	stl_parsebrd(stlconf_t *confp, char **argp);
 
diff -Nru a/drivers/char/watchdog/acquirewdt.c b/drivers/char/watchdog/acquirewdt.c
--- a/drivers/char/watchdog/acquirewdt.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/char/watchdog/acquirewdt.c	Sat Jul 19 12:54:25 2003
@@ -143,7 +143,7 @@
 			return -EBUSY;
 		}
 		if (nowayout)
-			MOD_INC_USE_COUNT;
+			__module_get(THIS_MODULE);
 
 		/* Activate */
 		acq_is_open=1;
diff -Nru a/drivers/char/watchdog/i810-tco.c b/drivers/char/watchdog/i810-tco.c
--- a/drivers/char/watchdog/i810-tco.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/char/watchdog/i810-tco.c	Sat Jul 19 12:54:21 2003
@@ -25,7 +25,8 @@
  *	82801AA & 82801AB  chip : document number 290655-003, 290677-004,
  *	82801BA & 82801BAM chip : document number 290687-002, 298242-005,
  *	82801CA & 82801CAM chip : document number 290716-001, 290718-001,
- *	82801DB & 82801E   chip : document number 290744-001, 273599-001
+ *	82801DB & 82801E   chip : document number 290744-001, 273599-001,
+ *	82801EB & 82801ER  chip : document number 252516-001
  *
  *  20000710 Nils Faerber
  *	Initial Version 0.01
@@ -42,9 +43,11 @@
  *	     clean up ioctls (WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS and
  *	     WDIOC_SETOPTIONS), made i810tco_getdevice __init,
  *	     removed boot_status, removed tco_timer_read,
- *	     added support for 82801DB and 82801E chipset, general cleanup.
+ *	     added support for 82801DB and 82801E chipset,
+ *	     added support for 82801EB and 8280ER chipset,
+ *	     general cleanup.
  */
- 
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/miscdevice.h>
@@ -164,7 +167,7 @@
  * Reload (trigger) the timer. Lock is needed so we don't reload it during
  * a reprogramming event
  */
- 
+
 static void tco_timer_reload (void)
 {
 	spin_lock(&tco_lock);
@@ -307,6 +310,7 @@
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12,	PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,	PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0,	PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,	PCI_ANY_ID, PCI_ANY_ID, },
 	{ 0, },
 };
 MODULE_DEVICE_TABLE (pci, i810tco_pci_tbl);
diff -Nru a/drivers/char/watchdog/i810-tco.h b/drivers/char/watchdog/i810-tco.h
--- a/drivers/char/watchdog/i810-tco.h	Sat Jul 19 12:54:26 2003
+++ b/drivers/char/watchdog/i810-tco.h	Sat Jul 19 12:54:26 2003
@@ -1,5 +1,5 @@
 /*
- *	i810-tco 0.05:	TCO timer driver for i8xx chipsets
+ *	i810-tco:	TCO timer driver for i8xx chipsets
  *
  *	(c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
  *				http://www.kernelconcepts.de
@@ -8,7 +8,7 @@
  *	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.
- *	
+ *
  *	Neither kernel concepts nor Nils Faerber admit liability nor provide
  *	warranty for any of this software. This material is provided
  *	"AS-IS" and at no charge.
diff -Nru a/drivers/char/watchdog/ib700wdt.c b/drivers/char/watchdog/ib700wdt.c
--- a/drivers/char/watchdog/ib700wdt.c	Sat Jul 19 12:54:28 2003
+++ b/drivers/char/watchdog/ib700wdt.c	Sat Jul 19 12:54:28 2003
@@ -230,7 +230,7 @@
 			return -EBUSY;
 		}
 		if (nowayout)
-			MOD_INC_USE_COUNT;
+			__module_get(THIS_MODULE);
 
 		/* Activate */
 		ibwdt_is_open = 1;
diff -Nru a/drivers/char/watchdog/indydog.c b/drivers/char/watchdog/indydog.c
--- a/drivers/char/watchdog/indydog.c	Sat Jul 19 12:54:29 2003
+++ b/drivers/char/watchdog/indydog.c	Sat Jul 19 12:54:29 2003
@@ -54,7 +54,7 @@
 		return -EBUSY;
 
 	if (nowayout)
-		MOD_INC_USE_COUNT;
+		__module_get(THIS_MODULE);
 
 	/*
 	 *	Activate timer
diff -Nru a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c
--- a/drivers/char/watchdog/machzwd.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/char/watchdog/machzwd.c	Sat Jul 19 12:54:23 2003
@@ -392,7 +392,7 @@
 			}
 
 			if (nowayout)
-				MOD_INC_USE_COUNT;
+				__module_get(THIS_MODULE);
 
 			zf_is_open = 1;
 
diff -Nru a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c
--- a/drivers/char/watchdog/pcwd.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/char/watchdog/pcwd.c	Sat Jul 19 12:54:22 2003
@@ -431,7 +431,7 @@
 			atomic_inc( &open_allowed );
 			return -EBUSY;
 		}
-		MOD_INC_USE_COUNT;
+		__module_get(THIS_MODULE);
 		/*  Enable the port  */
 		if (revision == PCWD_REVISION_C) {
 			spin_lock(&io_lock);
diff -Nru a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c
--- a/drivers/char/watchdog/sbc60xxwdt.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/char/watchdog/sbc60xxwdt.c	Sat Jul 19 12:54:26 2003
@@ -207,9 +207,8 @@
 			/* Just in case we're already talking to someone... */
 			if(wdt_is_open)
 				return -EBUSY;
-			if (nowayout) {
-				MOD_INC_USE_COUNT;
-			}
+			if (nowayout) 
+				__module_get(THIS_MODULE);
 			/* Good, fire up the show */
 			wdt_is_open = 1;
 			wdt_startup();
diff -Nru a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c
--- a/drivers/char/watchdog/sc520_wdt.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/char/watchdog/sc520_wdt.c	Sat Jul 19 12:54:25 2003
@@ -231,7 +231,7 @@
 			/* Good, fire up the show */
 			wdt_startup();
 			if (nowayout)
-				MOD_INC_USE_COUNT;
+				__module_get(THIS_MODULE);
 
 			return 0;
 		default:
diff -Nru a/drivers/char/watchdog/shwdt.c b/drivers/char/watchdog/shwdt.c
--- a/drivers/char/watchdog/shwdt.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/char/watchdog/shwdt.c	Sat Jul 19 12:54:24 2003
@@ -3,7 +3,7 @@
  *
  * Watchdog driver for integrated watchdog in the SuperH processors.
  *
- * Copyright (C) 2001, 2002 Paul Mundt <lethal@0xd6.org>
+ * Copyright (C) 2001, 2002, 2003 Paul Mundt <lethal@linux-sh.org>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -12,6 +12,10 @@
  *
  * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
  *     Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *
+ * 19-Apr-2002 Rob Radez <rob@osinvestor.com>
+ *     Added expect close support, made emulated timeout runtime changeable
+ *     general cleanups, add some ioctls
  */
 #include <linux/config.h>
 #include <linux/module.h>
@@ -22,76 +26,50 @@
 #include <linux/reboot.h>
 #include <linux/notifier.h>
 #include <linux/ioport.h>
+#include <linux/fs.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
-
-#if defined(CONFIG_CPU_SH5)
-  #define WTCNT		CPRC_BASE + 0x10
-  #define WTCSR		CPRC_BASE + 0x18
-#elif defined(CONFIG_CPU_SH4)
-  #define WTCNT		0xffc00008
-  #define WTCSR		0xffc0000c
-#elif defined(CONFIG_CPU_SH3)
-  #define WTCNT		0xffffff84
-  #define WTCSR		0xffffff86
-#else
-  #error "Can't use SuperH watchdog on this platform"
-#endif
-
-#define WTCNT_HIGH	0x5a00
-#define WTCSR_HIGH	0xa500
-
-#define WTCSR_TME	0x80
-#define WTCSR_WT	0x40
-#define WTCSR_RSTS	0x20
-#define WTCSR_WOVF	0x10
-#define WTCSR_IOVF	0x08
-#define WTCSR_CKS2	0x04
-#define WTCSR_CKS1	0x02
-#define WTCSR_CKS0	0x01
-
-/*
- * CKS0-2 supports a number of clock division ratios. At the time the watchdog
- * is enabled, it defaults to a 41 usec overflow period .. we overload this to
- * something a little more reasonable, and really can't deal with anything
- * lower than WTCSR_CKS_1024, else we drop back into the usec range.
- *
- * Clock Division Ratio         Overflow Period
- * --------------------------------------------
- *     1/32 (initial value)       41 usecs
- *     1/64                       82 usecs
- *     1/128                     164 usecs
- *     1/256                     328 usecs
- *     1/512                     656 usecs
- *     1/1024                   1.31 msecs
- *     1/2048                   2.62 msecs
- *     1/4096                   5.25 msecs
- */
-#define WTCSR_CKS_32	0x00
-#define WTCSR_CKS_64	0x01
-#define WTCSR_CKS_128	0x02
-#define WTCSR_CKS_256	0x03
-#define WTCSR_CKS_512	0x04
-#define WTCSR_CKS_1024	0x05
-#define WTCSR_CKS_2048	0x06
-#define WTCSR_CKS_4096	0x07
+#include <asm/watchdog.h>
 
 /*
- * Default clock division ratio is 5.25 msecs. Overload this at module load
- * time. Any value not in the msec range will default to a timeout of one
- * jiffy, which exceeds the usec overflow periods.
+ * Default clock division ratio is 5.25 msecs. For an additional table of
+ * values, consult the asm-sh/watchdog.h. Overload this at module load
+ * time. 
+ *
+ * In order for this to work reliably we need to have HZ set to 1000 or
+ * something quite higher than 100 (or we need a proper high-res timer
+ * implementation that will deal with this properly), otherwise the 10ms
+ * resolution of a jiffy is enough to trigger the overflow. For things like
+ * the SH-4 and SH-5, this isn't necessarily that big of a problem, though
+ * for the SH-2 and SH-3, this isn't recommended unless the WDT is absolutely
+ * necssary.
+ *
+ * As a result of this timing problem, the only modes that are particularly
+ * feasible are the 4096 and the 2048 divisors, which yeild 5.25 and 2.62ms
+ * overflow periods respectively.
+ *
+ * Also, since we can't really expect userspace to be responsive enough
+ * before the overflow happens, we maintain two seperate timers .. One in
+ * the kernel for clearing out WOVF every 2ms or so (again, this depends on
+ * HZ == 1000), and another for monitoring userspace writes to the WDT device.
+ *
+ * As such, we currently use a configurable heartbeat interval which defaults
+ * to 30s. In this case, the userspace daemon is only responsible for periodic
+ * writes to the device before the next heartbeat is scheduled. If the daemon
+ * misses its deadline, the kernel timer will allow the WDT to overflow.
  */
 static int clock_division_ratio = WTCSR_CKS_4096;
 
-#define msecs_to_jiffies(msecs)	(jiffies + ((HZ * msecs + 999) / 1000))
+#define msecs_to_jiffies(msecs)	(jiffies + (HZ * msecs + 9999) / 10000)
 #define next_ping_period(cks)	msecs_to_jiffies(cks - 4)
-#define user_ping_period(cks)	(next_ping_period(cks) * 10)
 
-static unsigned long sh_is_open = 0;
+static unsigned long shwdt_is_open;
 static struct watchdog_info sh_wdt_info;
+static char shwdt_expect_close;
 static struct timer_list timer;
 static unsigned long next_heartbeat;
+static int heartbeat = 30;
 
 #ifdef CONFIG_WATCHDOG_NOWAYOUT
 static int nowayout = 1;
@@ -99,35 +77,6 @@
 static int nowayout = 0;
 #endif
 
-MODULE_PARM(nowayout,"i");
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
-
-/**
- *	sh_wdt_write_cnt - Write to Counter
- *
- *	@val: Value to write
- *
- *	Writes the given value @val to the lower byte of the timer counter.
- *	The upper byte is set manually on each write.
- */
-static void sh_wdt_write_cnt(__u8 val)
-{
-	ctrl_outw(WTCNT_HIGH | (__u16)val, WTCNT);
-}
-
-/**
- * 	sh_wdt_write_csr - Write to Control/Status Register
- *
- * 	@val: Value to write
- *
- * 	Writes the given value @val to the lower byte of the control/status
- * 	register. The upper byte is set manually on each write.
- */
-static void sh_wdt_write_csr(__u8 val)
-{
-	ctrl_outw(WTCSR_HIGH | (__u16)val, WTCSR);
-}
-
 /**
  * 	sh_wdt_start - Start the Watchdog
  *
@@ -135,13 +84,44 @@
  */
 static void sh_wdt_start(void)
 {
-	timer.expires = next_ping_period(clock_division_ratio);
-	next_heartbeat = user_ping_period(clock_division_ratio);
-	add_timer(&timer);
+	__u8 csr;
+
+	mod_timer(&timer, next_ping_period(clock_division_ratio));
+	next_heartbeat = jiffies + (heartbeat * HZ);
+
+	csr = sh_wdt_read_csr();
+	csr |= WTCSR_WT | clock_division_ratio;
+	sh_wdt_write_csr(csr);
 
-	sh_wdt_write_csr(WTCSR_WT | WTCSR_CKS_4096);
 	sh_wdt_write_cnt(0);
-	sh_wdt_write_csr((ctrl_inb(WTCSR) | WTCSR_TME));
+
+	/*
+	 * These processors have a bit of an inconsistent initialization
+	 * process.. starting with SH-3, RSTS was moved to WTCSR, and the
+	 * RSTCSR register was removed.
+	 *
+	 * On the SH-2 however, in addition with bits being in different
+	 * locations, we must deal with RSTCSR outright..
+	 */
+	csr = sh_wdt_read_csr();
+	csr |= WTCSR_TME;
+	csr &= ~WTCSR_RSTS;
+	sh_wdt_write_csr(csr);
+
+#ifdef CONFIG_CPU_SH2
+	/*
+	 * Whoever came up with the RSTCSR semantics must've been smoking
+	 * some of the good stuff, since in addition to the WTCSR/WTCNT write
+	 * brain-damage, it's managed to fuck things up one step further..
+	 *
+	 * If we need to clear the WOVF bit, the upper byte has to be 0xa5..
+	 * but if we want to touch RSTE or RSTS, the upper byte has to be
+	 * 0x5a..
+	 */
+	csr = sh_wdt_read_rstcsr();
+	csr &= ~RSTCSR_RSTS;
+	sh_wdt_write_rstcsr(csr);
+#endif	
 }
 
 /**
@@ -151,9 +131,13 @@
  */
 static void sh_wdt_stop(void)
 {
+	__u8 csr;
+
 	del_timer(&timer);
 
-	sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_TME));
+	csr = sh_wdt_read_csr();
+	csr &= ~WTCSR_TME;
+	sh_wdt_write_csr(csr);
 }
 
 /**
@@ -166,11 +150,15 @@
 static void sh_wdt_ping(unsigned long data)
 {
 	if (time_before(jiffies, next_heartbeat)) {
-		sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_IOVF));
+		__u8 csr;
+
+		csr = sh_wdt_read_csr();
+		csr &= ~WTCSR_IOVF;
+		sh_wdt_write_csr(csr);
+
 		sh_wdt_write_cnt(0);
 
-		timer.expires = next_ping_period(clock_division_ratio);
-		add_timer(&timer);
+		mod_timer(&timer, next_ping_period(clock_division_ratio));
 	}
 }
 
@@ -184,21 +172,12 @@
  */
 static int sh_wdt_open(struct inode *inode, struct file *file)
 {
-	switch (minor(inode->i_rdev)) {
-		case WATCHDOG_MINOR:
-			if (test_and_set_bit(0, &sh_is_open))
-				return -EBUSY;
+	if (test_and_set_bit(0, &shwdt_is_open))
+		return -EBUSY;
+	if (nowayout)
+		__module_get(THIS_MODULE);
 
-			if (nowayout) {
-				MOD_INC_USE_COUNT;
-			}
-
-			sh_wdt_start();
-
-			break;
-		default:
-			return -ENODEV;
-	}
+	sh_wdt_start();
 
 	return 0;
 }
@@ -213,33 +192,20 @@
  */
 static int sh_wdt_close(struct inode *inode, struct file *file)
 {
-	if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
-		if (!nowayout) {
-			sh_wdt_stop();
-		}
-		clear_bit(0, &sh_is_open);
+	if (!nowayout && shwdt_expect_close == 42) {
+		sh_wdt_stop();
+	} else {
+		printk(KERN_CRIT "shwdt: Unexpected close, not stopping watchdog!\n");
+		next_heartbeat = jiffies + (heartbeat * HZ);
 	}
+
+	clear_bit(0, &shwdt_is_open);
+	shwdt_expect_close = 0;
 	
 	return 0;
 }
 
 /**
- * 	sh_wdt_read - Read from Device
- *
- * 	@file: file handle of device
- * 	@buf: buffer to write to
- * 	@count: length of buffer
- * 	@ppos: offset
- *
- * 	Unsupported.
- */
-static ssize_t sh_wdt_read(struct file *file, char *buf,
-			   size_t count, loff_t *ppos)
-{
-	return -EINVAL;
-}
-
-/**
  * 	sh_wdt_write - Write to Device
  *
  * 	@file: file handle of device
@@ -257,11 +223,21 @@
 		return -ESPIPE;
 
 	if (count) {
-		next_heartbeat = user_ping_period(clock_division_ratio);
-		return 1;
+		size_t i;
+
+		shwdt_expect_close = 0;
+
+		for (i = 0; i != count; i++) {
+			char c;
+			if (get_user(c, buf + i))
+				return -EFAULT;
+			if (c == 'V')
+				shwdt_expect_close = 42;
+		}
+		next_heartbeat = jiffies + (heartbeat * HZ);
 	}
 
-	return 0;
+	return count;
 }
 
 /**
@@ -278,6 +254,8 @@
 static int sh_wdt_ioctl(struct inode *inode, struct file *file,
 			unsigned int cmd, unsigned long arg)
 {
+	int new_timeout;
+
 	switch (cmd) {
 		case WDIOC_GETSUPPORT:
 			if (copy_to_user((struct watchdog_info *)arg,
@@ -288,17 +266,41 @@
 			
 			break;
 		case WDIOC_GETSTATUS:
-			if (copy_to_user((int *)arg,
-					 &sh_is_open,
-					 sizeof(int))) {
+		case WDIOC_GETBOOTSTATUS:
+			return put_user(0, (int *)arg);
+		case WDIOC_KEEPALIVE:
+			next_heartbeat = jiffies + (heartbeat * HZ);
+
+			break;
+		case WDIOC_SETTIMEOUT:
+			if (get_user(new_timeout, (int *)arg))
 				return -EFAULT;
+			if (new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */
+				return -EINVAL;
+			heartbeat = new_timeout;
+			next_heartbeat = jiffies + (heartbeat * HZ);
+			/* Fall */
+		case WDIOC_GETTIMEOUT:
+			return put_user(heartbeat, (int *)arg);
+		case WDIOC_SETOPTIONS:
+		{
+			int options, retval = -EINVAL;
+
+			if (get_user(options, (int *)arg))
+				return -EFAULT;
+
+			if (options & WDIOS_DISABLECARD) {
+				sh_wdt_stop();
+				retval = 0;
 			}
 
-			break;
-		case WDIOC_KEEPALIVE:
-			next_heartbeat = user_ping_period(clock_division_ratio);
+			if (options & WDIOS_ENABLECARD) {
+				sh_wdt_start();
+				retval = 0;
+			}
 			
-			break;
+			return retval;
+		}
 		default:
 			return -ENOTTY;
 	}
@@ -328,7 +330,7 @@
 
 static struct file_operations sh_wdt_fops = {
 	.owner		= THIS_MODULE,
-	.read		= sh_wdt_read,
+	.llseek		= no_llseek,
 	.write		= sh_wdt_write,
 	.ioctl		= sh_wdt_ioctl,
 	.open		= sh_wdt_open,
@@ -336,21 +338,20 @@
 };
 
 static struct watchdog_info sh_wdt_info = {
-	.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
-	.firmware_version = 1,
-	.identity = "SH WDT",
+	.options		= WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+	.firmware_version	= 1,
+	.identity		= "SH WDT",
 };
 
 static struct notifier_block sh_wdt_notifier = {
-	.notifier_call = sh_wdt_notify_sys,
-	.next = NULL,
-	.priority = 0
+	.notifier_call		= sh_wdt_notify_sys,
+	.priority		= 0,
 };
 
 static struct miscdevice sh_wdt_miscdev = {
-	.minor = WATCHDOG_MINOR,
-	.name = "watchdog",
-	.fops &sh_wdt_fops,
+	.minor		= WATCHDOG_MINOR,
+	.name		= "watchdog",
+	.fops		= &sh_wdt_fops,
 };
 
 /**
@@ -366,23 +367,8 @@
 		return -EINVAL;
 	}
 
-	if (!request_region(WTCNT, 1, "shwdt")) {
-		printk(KERN_ERR "shwdt: Can't request WTCNT region\n");
-		misc_deregister(&sh_wdt_miscdev);
-		return -ENXIO;
-	}
-
-	if (!request_region(WTCSR, 1, "shwdt")) {
-		printk(KERN_ERR "shwdt: Can't request WTCSR region\n");
-		release_region(WTCNT, 1);
-		misc_deregister(&sh_wdt_miscdev);
-		return -ENXIO;
-	}
-
 	if (register_reboot_notifier(&sh_wdt_notifier)) {
 		printk(KERN_ERR "shwdt: Can't register reboot notifier\n");
-		release_region(WTCSR, 1);
-		release_region(WTCNT, 1);
 		misc_deregister(&sh_wdt_miscdev);
 		return -EINVAL;
 	}
@@ -403,16 +389,16 @@
 static void __exit sh_wdt_exit(void)
 {
 	unregister_reboot_notifier(&sh_wdt_notifier);
-	release_region(WTCSR, 1);
-	release_region(WTCNT, 1);
 	misc_deregister(&sh_wdt_miscdev);
 }
 
-MODULE_AUTHOR("Paul Mundt <lethal@0xd6.org>");
+MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
 MODULE_DESCRIPTION("SuperH watchdog driver");
 MODULE_LICENSE("GPL");
 MODULE_PARM(clock_division_ratio, "i");
 MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). Defaults to 0x7.");
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
 
 module_init(sh_wdt_init);
 module_exit(sh_wdt_exit);
diff -Nru a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c
--- a/drivers/char/watchdog/softdog.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/char/watchdog/softdog.c	Sat Jul 19 12:54:24 2003
@@ -104,9 +104,8 @@
 {
 	if(test_and_set_bit(0, &timer_alive))
 		return -EBUSY;
-	if (nowayout) {
-		MOD_INC_USE_COUNT;
-	}
+	if (nowayout) 
+		__module_get(THIS_MODULE);
 	/*
 	 *	Activate timer
 	 */
diff -Nru a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c
--- a/drivers/char/watchdog/wdt977.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/char/watchdog/wdt977.c	Sat Jul 19 12:54:27 2003
@@ -16,6 +16,8 @@
  *	19-Dec-2001 Woody Suwalski: Netwinder fixes, ioctl interface
  *	06-Jan-2002 Woody Suwalski: For compatibility, convert all timeouts
  *				    from minutes to seconds.
+ *      07-Jul-2003 Daniele Bellucci: Audit return code of misc_register in
+ *                                    nwwatchdog_init.
  */
 
 #include <linux/module.h>
@@ -99,7 +101,7 @@
 
 	if (nowayout)
 	{
-		MOD_INC_USE_COUNT;
+		__module_get(THIS_MODULE);
 
 		/* do not permit disabling the watchdog by writing 0 to reg. 0xF2 */
 		if (!timeoutM) timeoutM = DEFAULT_TIMEOUT;
@@ -343,12 +345,14 @@
 
 static int __init nwwatchdog_init(void)
 {
+	int retval;
 	if (!machine_is_netwinder())
 		return -ENODEV;
 
-	misc_register(&wdt977_miscdev);
-	printk(KERN_INFO "Wdt977 Watchdog sleeping.\n");
-	return 0;
+	retval = misc_register(&wdt977_miscdev);
+	if (!retval)
+		printk(KERN_INFO "Wdt977 Watchdog sleeping.\n");
+	return retval;
 }
 
 static void __exit nwwatchdog_exit(void)
diff -Nru a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c
--- a/drivers/char/watchdog/wdt_pci.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/char/watchdog/wdt_pci.c	Sat Jul 19 12:54:25 2003
@@ -367,7 +367,7 @@
 				return -EBUSY;
 
 			if (nowayout) {
-				MOD_INC_USE_COUNT;
+				__module_get(THIS_MODULE);
 			}
 			/*
 			 *	Activate 
diff -Nru a/drivers/fc4/fc.c b/drivers/fc4/fc.c
--- a/drivers/fc4/fc.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/fc4/fc.c	Sat Jul 19 12:54:25 2003
@@ -33,7 +33,6 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/blk.h>
 
 #include <asm/pgtable.h>
 #include <asm/irq.h>
diff -Nru a/drivers/fc4/fcp_impl.h b/drivers/fc4/fcp_impl.h
--- a/drivers/fc4/fcp_impl.h	Sat Jul 19 12:54:24 2003
+++ b/drivers/fc4/fcp_impl.h	Sat Jul 19 12:54:24 2003
@@ -8,7 +8,6 @@
 #define _FCP_SCSI_H
 
 #include <linux/types.h>
-#include <linux/blk.h>
 #include "../scsi/scsi.h"
 
 #include "fc.h"
diff -Nru a/drivers/ide/Kconfig b/drivers/ide/Kconfig
--- a/drivers/ide/Kconfig	Sat Jul 19 12:54:25 2003
+++ b/drivers/ide/Kconfig	Sat Jul 19 12:54:25 2003
@@ -521,7 +521,7 @@
 
 	  If you say Y here, you also need to say Y to "Use DMA by default
 	  when available", above.  Please read the comments at the top of
-	  <file:drivers/ide/alim15x3.c>.
+	  <file:drivers/ide/pci/alim15x3.c>.
 
 	  If unsure, say N.
 
@@ -608,7 +608,7 @@
 	depends on BLK_DEV_HPT34X && IDEDMA_PCI_WIP
 	help
 	  This is a dangerous thing to attempt currently! Please read the
-	  comments at the top of <file:drivers/ide/hpt34x.c>.  If you say Y
+	  comments at the top of <file:drivers/ide/pci/hpt34x.c>.  If you say Y
 	  here, then say Y to "Use DMA by default when available" as well.
 
 	  If unsure, say N.
@@ -670,14 +670,14 @@
 	  This driver adds detection and support for the NS87415 chip
 	  (used in SPARC64, among others).
 
-	  Please read the comments at the top of <file:drivers/ide/ns87415.c>.
+	  Please read the comments at the top of <file:drivers/ide/pci/ns87415.c>.
 
 config BLK_DEV_OPTI621
 	tristate "OPTi 82C621 chipset enhanced support (EXPERIMENTAL)"
 	depends on PCI && BLK_DEV_IDEPCI && EXPERIMENTAL
 	help
 	  This is a driver for the OPTi 82C621 EIDE controller.
-	  Please read the comments at the top of <file:drivers/ide/opti621.c>.
+	  Please read the comments at the top of <file:drivers/ide/pci/opti621.c>.
 
 config BLK_DEV_PDC202XX_OLD
 	tristate "PROMISE PDC202{46|62|65|67} support"
@@ -696,7 +696,7 @@
 	  when the PDC20265 BIOS has been disabled (for faster boot up).
 
 	  Please read the comments at the top of
-	  <file:drivers/ide/pdc202xx.c>.
+	  <file:drivers/ide/pci/pdc202xx_old.c>.
 
 	  If unsure, say N.
 
@@ -754,7 +754,7 @@
 	  If you say Y here, you need to say Y to "Use DMA by default when
 	  available" as well.
 
-	  Please read the comments at the top of <file:drivers/ide/sis5513.c>.
+	  Please read the comments at the top of <file:drivers/ide/pci/sis5513.c>.
 
 config BLK_DEV_SLC90E66
 	tristate "SLC90E66 chipset support"
@@ -770,7 +770,7 @@
 	  available" as well.
 
 	  Please read the comments at the top of
-	  drivers/ide/slc90e66.c.
+	  drivers/ide/pci/slc90e66.c.
 
 config BLK_DEV_TRM290
 	tristate "Tekram TRM290 chipset support"
@@ -779,7 +779,7 @@
 	  This driver adds support for bus master DMA transfers
 	  using the Tekram TRM290 PCI IDE chip. Volunteers are
 	  needed for further tweaking and development.
-	  Please read the comments at the top of <file:drivers/ide/trm290.c>.
+	  Please read the comments at the top of <file:drivers/ide/pci/trm290.c>.
 
 config BLK_DEV_VIA82CXXX
 	tristate "VIA82CXXX chipset support"
@@ -1010,7 +1010,7 @@
 	  boot parameter.  It enables support for the secondary IDE interface
 	  of the ALI M1439/1443/1445/1487/1489 chipsets, and permits faster
 	  I/O speeds to be set as well.  See the files
-	  <file:Documentation/ide.txt> and <file:drivers/ide/ali14xx.c> for
+	  <file:Documentation/ide.txt> and <file:drivers/ide/legacy/ali14xx.c> for
 	  more info.
 
 config BLK_DEV_DTC2278
@@ -1021,7 +1021,7 @@
 	  boot parameter. It enables support for the secondary IDE interface
 	  of the DTC-2278 card, and permits faster I/O speeds to be set as
 	  well. See the <file:Documentation/ide.txt> and
-	  <file:drivers/ide/dtc2278.c> files for more info.
+	  <file:drivers/ide/legacy/dtc2278.c> files for more info.
 
 config BLK_DEV_HT6560B
 	tristate "Holtek HT6560B support"
@@ -1031,7 +1031,7 @@
 	  boot parameter. It enables support for the secondary IDE interface
 	  of the Holtek card, and permits faster I/O speeds to be set as well.
 	  See the <file:Documentation/ide.txt> and
-	  <file:drivers/ide/ht6560b.c> files for more info.
+	  <file:drivers/ide/legacy/ht6560b.c> files for more info.
 
 config BLK_DEV_PDC4030
 	tristate "PROMISE DC4030 support (EXPERIMENTAL)"
@@ -1044,7 +1044,7 @@
 	  supported (and probably never will be since I don't think the cards
 	  support them). This driver is enabled at runtime using the "ide0=dc4030"
 	  or "ide1=dc4030" kernel boot parameter. See the
-	  <file:drivers/ide/pdc4030.c> file for more info.
+	  <file:drivers/ide/legacy/pdc4030.c> file for more info.
 
 config BLK_DEV_QD65XX
 	tristate "QDI QD65xx support"
@@ -1052,7 +1052,7 @@
 	help
 	  This driver is enabled at runtime using the "ide0=qd65xx" kernel
 	  boot parameter.  It permits faster I/O speeds to be set.  See the
-	  <file:Documentation/ide.txt> and <file:drivers/ide/qd65xx.c> for
+	  <file:Documentation/ide.txt> and <file:drivers/ide/legacy/qd65xx.c> for
 	  more info.
 
 config BLK_DEV_UMC8672
@@ -1063,7 +1063,7 @@
 	  boot parameter. It enables support for the secondary IDE interface
 	  of the UMC-8672, and permits faster I/O speeds to be set as well.
 	  See the files <file:Documentation/ide.txt> and
-	  <file:drivers/ide/umc8672.c> for more info.
+	  <file:drivers/ide/legacy/umc8672.c> for more info.
 
 config BLK_DEV_HD_ONLY
 	bool "Old hard disk (MFM/RLL/IDE) driver"
@@ -1132,7 +1132,7 @@
 	  available" as well.
 
 	  Please read the comments at the top of
-	  <file:drivers/ide/pdc202xx.c>.
+	  <file:drivers/ide/pdc202xx_old.c>.
 
 	  If unsure, say N.
 
diff -Nru a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
--- a/drivers/ide/ide-dma.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/ide/ide-dma.c	Sat Jul 19 12:54:25 2003
@@ -442,9 +442,10 @@
  *	the driver to resolve the problem, if a DMA transfer is still
  *	in progress we continue to wait (arguably we need to add a 
  *	secondary 'I don't care what the drive thinks' timeout here)
- *	Finally if we have an interrupt but for some reason got the
- *	timeout first we complete the I/O. This can occur if an 
- *	interrupt is lost or due to bugs.
+ *	Finally if we have an interrupt we let it complete the I/O.
+ *	But only one time - we clear expiry and if it's still not
+ *	completed after WAIT_CMD, we error and retry in PIO.
+ *	This can occur if an interrupt is lost or due to hang or bugs.
  */
  
 static int dma_timer_expiry (ide_drive_t *drive)
@@ -461,19 +462,16 @@
 	HWGROUP(drive)->expiry = NULL;	/* one free ride for now */
 
 	/* 1 dmaing, 2 error, 4 intr */
-	
-	if (dma_stat & 2) {	/* ERROR */
-		(void) hwif->ide_dma_end(drive);
-		return DRIVER(drive)->error(drive,
-			"dma_timer_expiry", hwif->INB(IDE_STATUS_REG));
-	}
+	if (dma_stat & 2)	/* ERROR */
+		return -1;
+
 	if (dma_stat & 1)	/* DMAing */
 		return WAIT_CMD;
 
 	if (dma_stat & 4)	/* Got an Interrupt */
-		HWGROUP(drive)->handler(drive);
+		return WAIT_CMD;
 
-	return 0;
+	return 0;	/* Status is unknown -- reset the bus */
 }
 
 /**
diff -Nru a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
--- a/drivers/ide/ide-io.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/ide/ide-io.c	Sat Jul 19 12:54:27 2003
@@ -949,14 +949,14 @@
 		 * happens anyway when any interrupt comes in, IDE or otherwise
 		 *  -- the kernel masks the IRQ while it is being handled.
 		 */
-		if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)
+		if (hwif->irq != masked_irq)
 			disable_irq_nosync(hwif->irq);
 		spin_unlock(&ide_lock);
 		local_irq_enable();
 			/* allow other IRQs while we start this request */
 		startstop = start_request(drive, rq);
 		spin_lock_irq(&ide_lock);
-		if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)
+		if (hwif->irq != masked_irq)
 			enable_irq(hwif->irq);
 		if (startstop == ide_released)
 			goto queue_next;
@@ -980,21 +980,25 @@
  * retry the current request in pio mode instead of risking tossing it
  * all away
  */
-void ide_dma_timeout_retry(ide_drive_t *drive)
+static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
 {
 	ide_hwif_t *hwif = HWIF(drive);
 	struct request *rq;
+	ide_startstop_t ret = ide_stopped;
 
 	/*
 	 * end current dma transaction
 	 */
-	(void) hwif->ide_dma_end(drive);
 
-	/*
-	 * complain a little, later we might remove some of this verbosity
-	 */
-	printk(KERN_WARNING "%s: timeout waiting for DMA\n", drive->name);
-	(void) hwif->ide_dma_timeout(drive);
+	if (error < 0) {
+		printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
+		(void)HWIF(drive)->ide_dma_end(drive);
+		ret = DRIVER(drive)->error(drive, "dma timeout error",
+						hwif->INB(IDE_STATUS_REG));
+	} else {
+		printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
+		(void) hwif->ide_dma_timeout(drive);
+	}
 
 	/*
 	 * disable dma for now, but remember that we did so because of
@@ -1018,9 +1022,9 @@
 	rq->hard_cur_sectors = rq->current_nr_sectors;
 	if (rq->bio)
 		rq->buffer = NULL;
-}
 
-EXPORT_SYMBOL(ide_dma_timeout_retry);
+	return ret;
+}
 
 /**
  *	ide_timer_expiry	-	handle lack of an IDE interrupt
@@ -1041,11 +1045,10 @@
 	ide_hwgroup_t	*hwgroup = (ide_hwgroup_t *) data;
 	ide_handler_t	*handler;
 	ide_expiry_t	*expiry;
- 	unsigned long	flags;
-	unsigned long	wait;
+	unsigned long	flags;
+	unsigned long	wait = -1;
 
 	spin_lock_irqsave(&ide_lock, flags);
-	del_timer(&hwgroup->timer);
 
 	if ((handler = hwgroup->handler) == NULL) {
 		/*
@@ -1072,7 +1075,7 @@
 			}
 			if ((expiry = hwgroup->expiry) != NULL) {
 				/* continue */
-				if ((wait = expiry(drive)) != 0) {
+				if ((wait = expiry(drive)) > 0) {
 					/* reset timer */
 					hwgroup->timer.expires  = jiffies + wait;
 					add_timer(&hwgroup->timer);
@@ -1107,15 +1110,15 @@
 				startstop = handler(drive);
 			} else {
 				if (drive->waiting_for_dma) {
-					startstop = ide_stopped;
-					ide_dma_timeout_retry(drive);
+					startstop = ide_dma_timeout_retry(drive, wait);
 				} else
-					startstop = DRIVER(drive)->error(drive, "irq timeout", hwif->INB(IDE_STATUS_REG));
+					startstop =
+					DRIVER(drive)->error(drive, "irq timeout", hwif->INB(IDE_STATUS_REG));
 			}
 			set_recovery_timer(hwif);
 			drive->service_time = jiffies - drive->service_start;
-			enable_irq(hwif->irq);
 			spin_lock_irq(&ide_lock);
+			enable_irq(hwif->irq);
 			if (startstop == ide_stopped)
 				hwgroup->busy = 0;
 		}
diff -Nru a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
--- a/drivers/ide/legacy/hd.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/ide/legacy/hd.c	Sat Jul 19 12:54:21 2003
@@ -26,7 +26,7 @@
 /* Uncomment the following if you want verbose error reports. */
 /* #define VERBOSE_ERRORS */
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/interrupt.h>
diff -Nru a/drivers/ide/legacy/hd98.c b/drivers/ide/legacy/hd98.c
--- a/drivers/ide/legacy/hd98.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/ide/legacy/hd98.c	Sat Jul 19 12:54:26 2003
@@ -46,8 +46,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
-#include <linux/blk.h>
-
 #include "io_ports.h"
 
 #ifdef __arm__
diff -Nru a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c
--- a/drivers/ide/ppc/mpc8xx.c	Sat Jul 19 12:54:29 2003
+++ b/drivers/ide/ppc/mpc8xx.c	Sat Jul 19 12:54:29 2003
@@ -27,7 +27,6 @@
 #include <linux/interrupt.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
-#include <linux/blk.h>
 #include <linux/ioport.h>
 #include <linux/ide.h>
 #include <linux/bootmem.h>
diff -Nru a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c
--- a/drivers/ieee1394/amdtp.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/ieee1394/amdtp.c	Sat Jul 19 12:54:25 2003
@@ -62,6 +62,12 @@
  * - Maybe make an ALSA interface, that is, create a file_ops
  *   implementation that recognizes ALSA ioctls and uses defaults for
  *   things that can't be controlled through ALSA (iso channel).
+ *
+ *   Changes:
+ *
+ * - Audit copy_from_user in amdtp_write.
+ *                           Daniele Bellucci <bellucda@tiscali.it>
+ *
  */
 
 #include <linux/module.h>
@@ -1112,7 +1118,8 @@
 
 	for (i = 0; i < count; i += length) {
 		p = buffer_put_bytes(s->input, count - i, &length);
-		copy_from_user(p, buffer + i, length);
+		if (copy_from_user(p, buffer + i, length))
+			return -EFAULT;
 		if (s->input->length < s->input->size)
 			continue;
 		
diff -Nru a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
--- a/drivers/ieee1394/sbp2.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/ieee1394/sbp2.c	Sat Jul 19 12:54:23 2003
@@ -52,7 +52,7 @@
 #include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/version.h>
diff -Nru a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
--- a/drivers/input/keyboard/sunkbd.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/input/keyboard/sunkbd.c	Sat Jul 19 12:54:21 2003
@@ -80,8 +80,8 @@
 	char name[64];
 	char phys[32];
 	char type;
-	char reset;
-	char layout;
+	volatile char reset;
+	volatile char layout;
 };
 
 /*
diff -Nru a/drivers/md/Kconfig b/drivers/md/Kconfig
--- a/drivers/md/Kconfig	Sat Jul 19 12:54:23 2003
+++ b/drivers/md/Kconfig	Sat Jul 19 12:54:23 2003
@@ -145,5 +145,12 @@
 
 	  If unsure, say N.
 
+config DM_IOCTL_V4
+	bool "ioctl interface version 4"
+	depends on BLK_DEV_DM
+	---help---
+	  Recent tools use a new version of the ioctl interface, only
+          select this option if you intend using such tools.
+
 endmenu
 
diff -Nru a/drivers/md/dm-ioctl-v1.c b/drivers/md/dm-ioctl-v1.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/md/dm-ioctl-v1.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,1160 @@
+/*
+ * Copyright (C) 2001, 2002 Sistina Software (UK) Limited.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm.h"
+
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/miscdevice.h>
+#include <linux/dm-ioctl.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/blk.h>
+#include <linux/slab.h>
+#include <linux/devfs_fs_kernel.h>
+
+#include <asm/uaccess.h>
+
+#define DM_DRIVER_EMAIL "dm@uk.sistina.com"
+
+/*-----------------------------------------------------------------
+ * The ioctl interface needs to be able to look up devices by
+ * name or uuid.
+ *---------------------------------------------------------------*/
+struct hash_cell {
+	struct list_head name_list;
+	struct list_head uuid_list;
+
+	char *name;
+	char *uuid;
+	struct mapped_device *md;
+};
+
+#define NUM_BUCKETS 64
+#define MASK_BUCKETS (NUM_BUCKETS - 1)
+static struct list_head _name_buckets[NUM_BUCKETS];
+static struct list_head _uuid_buckets[NUM_BUCKETS];
+
+void dm_hash_remove_all(void);
+
+/*
+ * Guards access to all three tables.
+ */
+static DECLARE_RWSEM(_hash_lock);
+
+static void init_buckets(struct list_head *buckets)
+{
+	unsigned int i;
+
+	for (i = 0; i < NUM_BUCKETS; i++)
+		INIT_LIST_HEAD(buckets + i);
+}
+
+int dm_hash_init(void)
+{
+	init_buckets(_name_buckets);
+	init_buckets(_uuid_buckets);
+	devfs_mk_dir(DM_DIR);
+	return 0;
+}
+
+void dm_hash_exit(void)
+{
+	dm_hash_remove_all();
+	devfs_remove(DM_DIR);
+}
+
+/*-----------------------------------------------------------------
+ * Hash function:
+ * We're not really concerned with the str hash function being
+ * fast since it's only used by the ioctl interface.
+ *---------------------------------------------------------------*/
+static unsigned int hash_str(const char *str)
+{
+	const unsigned int hash_mult = 2654435387U;
+	unsigned int h = 0;
+
+	while (*str)
+		h = (h + (unsigned int) *str++) * hash_mult;
+
+	return h & MASK_BUCKETS;
+}
+
+/*-----------------------------------------------------------------
+ * Code for looking up a device by name
+ *---------------------------------------------------------------*/
+static struct hash_cell *__get_name_cell(const char *str)
+{
+	struct list_head *tmp;
+	struct hash_cell *hc;
+	unsigned int h = hash_str(str);
+
+	list_for_each (tmp, _name_buckets + h) {
+		hc = list_entry(tmp, struct hash_cell, name_list);
+		if (!strcmp(hc->name, str))
+			return hc;
+	}
+
+	return NULL;
+}
+
+static struct hash_cell *__get_uuid_cell(const char *str)
+{
+	struct list_head *tmp;
+	struct hash_cell *hc;
+	unsigned int h = hash_str(str);
+
+	list_for_each (tmp, _uuid_buckets + h) {
+		hc = list_entry(tmp, struct hash_cell, uuid_list);
+		if (!strcmp(hc->uuid, str))
+			return hc;
+	}
+
+	return NULL;
+}
+
+/*-----------------------------------------------------------------
+ * Inserting, removing and renaming a device.
+ *---------------------------------------------------------------*/
+static inline char *kstrdup(const char *str)
+{
+	char *r = kmalloc(strlen(str) + 1, GFP_KERNEL);
+	if (r)
+		strcpy(r, str);
+	return r;
+}
+
+static struct hash_cell *alloc_cell(const char *name, const char *uuid,
+				    struct mapped_device *md)
+{
+	struct hash_cell *hc;
+
+	hc = kmalloc(sizeof(*hc), GFP_KERNEL);
+	if (!hc)
+		return NULL;
+
+	hc->name = kstrdup(name);
+	if (!hc->name) {
+		kfree(hc);
+		return NULL;
+	}
+
+	if (!uuid)
+		hc->uuid = NULL;
+
+	else {
+		hc->uuid = kstrdup(uuid);
+		if (!hc->uuid) {
+			kfree(hc->name);
+			kfree(hc);
+			return NULL;
+		}
+	}
+
+	INIT_LIST_HEAD(&hc->name_list);
+	INIT_LIST_HEAD(&hc->uuid_list);
+	hc->md = md;
+	return hc;
+}
+
+static void free_cell(struct hash_cell *hc)
+{
+	if (hc) {
+		kfree(hc->name);
+		kfree(hc->uuid);
+		kfree(hc);
+	}
+}
+
+/*
+ * devfs stuff.
+ */
+static int register_with_devfs(struct hash_cell *hc)
+{
+	struct gendisk *disk = dm_disk(hc->md);
+
+	devfs_mk_bdev(MKDEV(disk->major, disk->first_minor),
+		       S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP,
+		       DM_DIR "/%s", hc->name);
+	return 0;
+}
+
+static int unregister_with_devfs(struct hash_cell *hc)
+{
+	devfs_remove(DM_DIR"/%s", hc->name);
+	return 0;
+}
+
+/*
+ * The kdev_t and uuid of a device can never change once it is
+ * initially inserted.
+ */
+int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md)
+{
+	struct hash_cell *cell;
+
+	/*
+	 * Allocate the new cells.
+	 */
+	cell = alloc_cell(name, uuid, md);
+	if (!cell)
+		return -ENOMEM;
+
+	/*
+	 * Insert the cell into all three hash tables.
+	 */
+	down_write(&_hash_lock);
+	if (__get_name_cell(name))
+		goto bad;
+
+	list_add(&cell->name_list, _name_buckets + hash_str(name));
+
+	if (uuid) {
+		if (__get_uuid_cell(uuid)) {
+			list_del(&cell->name_list);
+			goto bad;
+		}
+		list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid));
+	}
+	register_with_devfs(cell);
+	dm_get(md);
+	up_write(&_hash_lock);
+
+	return 0;
+
+ bad:
+	up_write(&_hash_lock);
+	free_cell(cell);
+	return -EBUSY;
+}
+
+void __hash_remove(struct hash_cell *hc)
+{
+	/* remove from the dev hash */
+	list_del(&hc->uuid_list);
+	list_del(&hc->name_list);
+	unregister_with_devfs(hc);
+	dm_put(hc->md);
+	free_cell(hc);
+}
+
+void dm_hash_remove_all(void)
+{
+	int i;
+	struct hash_cell *hc;
+	struct list_head *tmp, *n;
+
+	down_write(&_hash_lock);
+	for (i = 0; i < NUM_BUCKETS; i++) {
+		list_for_each_safe (tmp, n, _name_buckets + i) {
+			hc = list_entry(tmp, struct hash_cell, name_list);
+			__hash_remove(hc);
+		}
+	}
+	up_write(&_hash_lock);
+}
+
+int dm_hash_rename(const char *old, const char *new)
+{
+	char *new_name, *old_name;
+	struct hash_cell *hc;
+
+	/*
+	 * duplicate new.
+	 */
+	new_name = kstrdup(new);
+	if (!new_name)
+		return -ENOMEM;
+
+	down_write(&_hash_lock);
+
+	/*
+	 * Is new free ?
+	 */
+	hc = __get_name_cell(new);
+	if (hc) {
+		DMWARN("asked to rename to an already existing name %s -> %s",
+		       old, new);
+		up_write(&_hash_lock);
+		kfree(new_name);
+		return -EBUSY;
+	}
+
+	/*
+	 * Is there such a device as 'old' ?
+	 */
+	hc = __get_name_cell(old);
+	if (!hc) {
+		DMWARN("asked to rename a non existent device %s -> %s",
+		       old, new);
+		up_write(&_hash_lock);
+		kfree(new_name);
+		return -ENXIO;
+	}
+
+	/*
+	 * rename and move the name cell.
+	 */
+	unregister_with_devfs(hc);
+
+	list_del(&hc->name_list);
+	old_name = hc->name;
+	hc->name = new_name;
+	list_add(&hc->name_list, _name_buckets + hash_str(new_name));
+
+	/* rename the device node in devfs */
+	register_with_devfs(hc);
+
+	up_write(&_hash_lock);
+	kfree(old_name);
+	return 0;
+}
+
+
+/*-----------------------------------------------------------------
+ * Implementation of the ioctl commands
+ *---------------------------------------------------------------*/
+
+/*
+ * All the ioctl commands get dispatched to functions with this
+ * prototype.
+ */
+typedef int (*ioctl_fn)(struct dm_ioctl *param, struct dm_ioctl *user);
+
+/*
+ * Check a string doesn't overrun the chunk of
+ * memory we copied from userland.
+ */
+static int valid_str(char *str, void *begin, void *end)
+{
+	while (((void *) str >= begin) && ((void *) str < end))
+		if (!*str++)
+			return 0;
+
+	return -EINVAL;
+}
+
+static int next_target(struct dm_target_spec *last, uint32_t next,
+		       void *begin, void *end,
+		       struct dm_target_spec **spec, char **params)
+{
+	*spec = (struct dm_target_spec *)
+	    ((unsigned char *) last + next);
+	*params = (char *) (*spec + 1);
+
+	if (*spec < (last + 1) || ((void *) *spec > end))
+		return -EINVAL;
+
+	return valid_str(*params, begin, end);
+}
+
+static int populate_table(struct dm_table *table, struct dm_ioctl *args)
+{
+	int r, first = 1;
+	unsigned int i = 0;
+	struct dm_target_spec *spec;
+	char *params;
+	void *begin, *end;
+
+	if (!args->target_count) {
+		DMWARN("populate_table: no targets specified");
+		return -EINVAL;
+	}
+
+	begin = (void *) args;
+	end = begin + args->data_size;
+
+	for (i = 0; i < args->target_count; i++) {
+
+		if (first)
+			r = next_target((struct dm_target_spec *) args,
+					args->data_start,
+					begin, end, &spec, &params);
+		else
+			r = next_target(spec, spec->next, begin, end,
+					&spec, &params);
+
+		if (r) {
+			DMWARN("unable to find target");
+			return -EINVAL;
+		}
+
+		r = dm_table_add_target(table, spec->target_type,
+					(sector_t) spec->sector_start,
+					(sector_t) spec->length,
+					params);
+		if (r) {
+			DMWARN("internal error adding target to table");
+			return -EINVAL;
+		}
+
+		first = 0;
+	}
+
+	return dm_table_complete(table);
+}
+
+/*
+ * Round up the ptr to the next 'align' boundary.  Obviously
+ * 'align' must be a power of 2.
+ */
+static inline void *align_ptr(void *ptr, unsigned int align)
+{
+	align--;
+	return (void *) (((unsigned long) (ptr + align)) & ~align);
+}
+
+/*
+ * Copies a dm_ioctl and an optional additional payload to
+ * userland.
+ */
+static int results_to_user(struct dm_ioctl *user, struct dm_ioctl *param,
+			   void *data, uint32_t len)
+{
+	int r;
+	void *ptr = NULL;
+
+	if (data) {
+		ptr = align_ptr(user + 1, sizeof(unsigned long));
+		param->data_start = ptr - (void *) user;
+	}
+
+	/*
+	 * The version number has already been filled in, so we
+	 * just copy later fields.
+	 */
+	r = copy_to_user(&user->data_size, &param->data_size,
+			 sizeof(*param) - sizeof(param->version));
+	if (r)
+		return -EFAULT;
+
+	if (data) {
+		if (param->data_start + len > param->data_size)
+			return -ENOSPC;
+
+		if (copy_to_user(ptr, data, len))
+			r = -EFAULT;
+	}
+
+	return r;
+}
+
+/*
+ * Fills in a dm_ioctl structure, ready for sending back to
+ * userland.
+ */
+static int __info(struct mapped_device *md, struct dm_ioctl *param)
+{
+	struct dm_table *table;
+	struct block_device *bdev;
+	struct gendisk *disk = dm_disk(md);
+
+	param->flags = DM_EXISTS_FLAG;
+	if (dm_suspended(md))
+		param->flags |= DM_SUSPEND_FLAG;
+
+	bdev = bdget_disk(disk, 0);
+	if (!bdev)
+		return -ENXIO;
+
+	param->dev = bdev->bd_dev;
+	param->open_count = bdev->bd_openers;
+	bdput(bdev);
+
+	if (disk->policy)
+		param->flags |= DM_READONLY_FLAG;
+
+	table = dm_get_table(md);
+	param->target_count = dm_table_get_num_targets(table);
+	dm_table_put(table);
+
+	return 0;
+}
+
+/*
+ * Always use UUID for lookups if it's present, otherwise use name.
+ */
+static inline struct mapped_device *find_device(struct dm_ioctl *param)
+{
+	struct hash_cell *hc;
+	struct mapped_device *md = NULL;
+
+	down_read(&_hash_lock);
+	hc = *param->uuid ? __get_uuid_cell(param->uuid) :
+		__get_name_cell(param->name);
+	if (hc) {
+		md = hc->md;
+
+		/*
+		 * Sneakily write in both the name and the uuid
+		 * while we have the cell.
+		 */
+		strlcpy(param->name, hc->name, sizeof(param->name));
+		if (hc->uuid)
+			strlcpy(param->uuid, hc->uuid, sizeof(param->uuid));
+		else
+			param->uuid[0] = '\0';
+
+		dm_get(md);
+	}
+	up_read(&_hash_lock);
+
+	return md;
+}
+
+#define ALIGNMENT sizeof(int)
+static void *_align(void *ptr, unsigned int a)
+{
+	register unsigned long align = --a;
+
+	return (void *) (((unsigned long) ptr + align) & ~align);
+}
+
+/*
+ * Copies device info back to user space, used by
+ * the create and info ioctls.
+ */
+static int info(struct dm_ioctl *param, struct dm_ioctl *user)
+{
+	struct mapped_device *md;
+
+	param->flags = 0;
+
+	md = find_device(param);
+	if (!md)
+		/*
+		 * Device not found - returns cleared exists flag.
+		 */
+		goto out;
+
+	__info(md, param);
+	dm_put(md);
+
+      out:
+	return results_to_user(user, param, NULL, 0);
+}
+
+static inline int get_mode(struct dm_ioctl *param)
+{
+	int mode = FMODE_READ | FMODE_WRITE;
+
+	if (param->flags & DM_READONLY_FLAG)
+		mode = FMODE_READ;
+
+	return mode;
+}
+
+static int check_name(const char *name)
+{
+	if (name[0] == '/') {
+		DMWARN("invalid device name");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int create(struct dm_ioctl *param, struct dm_ioctl *user)
+{
+	int r;
+	struct dm_table *t;
+	struct mapped_device *md;
+
+	r = check_name(param->name);
+	if (r)
+		return r;
+
+	r = dm_table_create(&t, get_mode(param));
+	if (r)
+		return r;
+
+	r = populate_table(t, param);
+	if (r) {
+		dm_table_put(t);
+		return r;
+	}
+
+	if (param->flags & DM_PERSISTENT_DEV_FLAG)
+		r = dm_create_with_minor(minor(to_kdev_t(param->dev)), &md);
+	else
+		r = dm_create(&md);
+
+	if (r) {
+		dm_table_put(t);
+		return r;
+	}
+
+	/* suspend the device */
+	r = dm_suspend(md);
+	if (r) {
+		DMWARN("suspend failed");
+		dm_table_put(t);
+		dm_put(md);
+		return r;
+	}
+	/* swap in the table */
+	r = dm_swap_table(md, t);
+	if (r) {
+		DMWARN("table swap failed");
+		dm_table_put(t);
+		dm_put(md);
+		return r;
+	}
+
+	/* resume the device */
+	r = dm_resume(md);
+	if (r) {
+		DMWARN("resume failed");
+		dm_table_put(t);
+		dm_put(md);
+		return r;
+	}
+
+	dm_table_put(t);	/* md will have grabbed its own reference */
+
+	set_disk_ro(dm_disk(md), (param->flags & DM_READONLY_FLAG) ? 1 : 0);
+	r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md);
+	dm_put(md);
+
+	return r ? r : info(param, user);
+}
+
+/*
+ * Build up the status struct for each target
+ */
+static int __status(struct mapped_device *md, struct dm_ioctl *param,
+		    char *outbuf, size_t *len)
+{
+	unsigned int i, num_targets;
+	struct dm_target_spec *spec;
+	char *outptr;
+	status_type_t type;
+	struct dm_table *table = dm_get_table(md);
+
+	if (param->flags & DM_STATUS_TABLE_FLAG)
+		type = STATUSTYPE_TABLE;
+	else
+		type = STATUSTYPE_INFO;
+
+	outptr = outbuf;
+
+	/* Get all the target info */
+	num_targets = dm_table_get_num_targets(table);
+	for (i = 0; i < num_targets; i++) {
+		struct dm_target *ti = dm_table_get_target(table, i);
+
+		if (outptr - outbuf +
+		    sizeof(struct dm_target_spec) > param->data_size) {
+			dm_table_put(table);
+			return -ENOMEM;
+		}
+
+		spec = (struct dm_target_spec *) outptr;
+
+		spec->status = 0;
+		spec->sector_start = ti->begin;
+		spec->length = ti->len;
+		strlcpy(spec->target_type, ti->type->name,
+			sizeof(spec->target_type));
+
+		outptr += sizeof(struct dm_target_spec);
+
+		/* Get the status/table string from the target driver */
+		if (ti->type->status)
+			ti->type->status(ti, type, outptr,
+					 outbuf + param->data_size - outptr);
+		else
+			outptr[0] = '\0';
+
+		outptr += strlen(outptr) + 1;
+		_align(outptr, ALIGNMENT);
+		spec->next = outptr - outbuf;
+	}
+
+	param->target_count = num_targets;
+	*len = outptr - outbuf;
+	dm_table_put(table);
+
+	return 0;
+}
+
+/*
+ * Return the status of a device as a text string for each
+ * target.
+ */
+static int get_status(struct dm_ioctl *param, struct dm_ioctl *user)
+{
+	struct mapped_device *md;
+	size_t len = 0;
+	int ret;
+	char *outbuf = NULL;
+
+	md = find_device(param);
+	if (!md)
+		/*
+		 * Device not found - returns cleared exists flag.
+		 */
+		goto out;
+
+	/* We haven't a clue how long the resultant data will be so
+	   just allocate as much as userland has allowed us and make sure
+	   we don't overun it */
+	outbuf = kmalloc(param->data_size, GFP_KERNEL);
+	if (!outbuf)
+		goto out;
+	/*
+	 * Get the status of all targets
+	 */
+	__status(md, param, outbuf, &len);
+
+	/*
+	 * Setup the basic dm_ioctl structure.
+	 */
+	__info(md, param);
+
+      out:
+	if (md)
+		dm_put(md);
+
+	ret = results_to_user(user, param, outbuf, len);
+
+	if (outbuf)
+		kfree(outbuf);
+
+	return ret;
+}
+
+/*
+ * Wait for a device to report an event
+ */
+static int wait_device_event(struct dm_ioctl *param, struct dm_ioctl *user)
+{
+	struct mapped_device *md;
+	DECLARE_WAITQUEUE(wq, current);
+
+	md = find_device(param);
+	if (!md)
+		/*
+		 * Device not found - returns cleared exists flag.
+		 */
+		goto out;
+
+	/*
+	 * Setup the basic dm_ioctl structure.
+	 */
+	__info(md, param);
+
+	/*
+	 * Wait for a notification event
+	 */
+	set_current_state(TASK_INTERRUPTIBLE);
+ 	if (!dm_add_wait_queue(md, &wq, dm_get_event_nr(md))) {
+ 		schedule();
+ 		dm_remove_wait_queue(md, &wq);
+ 	}
+  	set_current_state(TASK_RUNNING);
+ 	dm_put(md);
+
+      out:
+	return results_to_user(user, param, NULL, 0);
+}
+
+/*
+ * Retrieves a list of devices used by a particular dm device.
+ */
+static int dep(struct dm_ioctl *param, struct dm_ioctl *user)
+{
+	int r;
+	unsigned int count;
+	struct mapped_device *md;
+	struct list_head *tmp;
+	size_t len = 0;
+	struct dm_target_deps *deps = NULL;
+	struct dm_table *table;
+
+	md = find_device(param);
+	if (!md)
+		goto out;
+	table = dm_get_table(md);
+
+	/*
+	 * Setup the basic dm_ioctl structure.
+	 */
+	__info(md, param);
+
+	/*
+	 * Count the devices.
+	 */
+	count = 0;
+	list_for_each(tmp, dm_table_get_devices(table))
+	    count++;
+
+	/*
+	 * Allocate a kernel space version of the dm_target_status
+	 * struct.
+	 */
+	if (array_too_big(sizeof(*deps), sizeof(*deps->dev), count)) {
+		dm_table_put(table);
+		dm_put(md);
+		return -ENOMEM;
+	}
+
+	len = sizeof(*deps) + (sizeof(*deps->dev) * count);
+	deps = kmalloc(len, GFP_KERNEL);
+	if (!deps) {
+		dm_table_put(table);
+		dm_put(md);
+		return -ENOMEM;
+	}
+
+	/*
+	 * Fill in the devices.
+	 */
+	deps->count = count;
+	count = 0;
+	list_for_each(tmp, dm_table_get_devices(table)) {
+		struct dm_dev *dd = list_entry(tmp, struct dm_dev, list);
+		deps->dev[count++] = dd->bdev->bd_dev;
+	}
+	dm_table_put(table);
+	dm_put(md);
+
+      out:
+	r = results_to_user(user, param, deps, len);
+
+	kfree(deps);
+	return r;
+}
+
+static int remove(struct dm_ioctl *param, struct dm_ioctl *user)
+{
+	struct hash_cell *hc;
+
+	down_write(&_hash_lock);
+	hc = *param->uuid ? __get_uuid_cell(param->uuid) :
+		__get_name_cell(param->name);
+	if (!hc) {
+		DMWARN("device doesn't appear to be in the dev hash table.");
+		up_write(&_hash_lock);
+		return -EINVAL;
+	}
+
+	/*
+	 * You may ask the interface to drop its reference to an
+	 * in use device.  This is no different to unlinking a
+	 * file that someone still has open.  The device will not
+	 * actually be destroyed until the last opener closes it.
+	 * The name and uuid of the device (both are interface
+	 * properties) will be available for reuse immediately.
+	 *
+	 * You don't want to drop a _suspended_ device from the
+	 * interface, since that will leave you with no way of
+	 * resuming it.
+	 */
+	if (dm_suspended(hc->md)) {
+		DMWARN("refusing to remove a suspended device.");
+		up_write(&_hash_lock);
+		return -EPERM;
+	}
+
+	__hash_remove(hc);
+	up_write(&_hash_lock);
+	return 0;
+}
+
+static int remove_all(struct dm_ioctl *param, struct dm_ioctl *user)
+{
+	dm_hash_remove_all();
+	return 0;
+}
+
+static int suspend(struct dm_ioctl *param, struct dm_ioctl *user)
+{
+	int r;
+	struct mapped_device *md;
+
+	md = find_device(param);
+	if (!md)
+		return -ENXIO;
+
+	if (param->flags & DM_SUSPEND_FLAG)
+		r = dm_suspend(md);
+	else
+		r = dm_resume(md);
+
+	dm_put(md);
+	return r;
+}
+
+static int reload(struct dm_ioctl *param, struct dm_ioctl *user)
+{
+	int r;
+	struct mapped_device *md;
+	struct dm_table *t;
+
+	r = dm_table_create(&t, get_mode(param));
+	if (r)
+		return r;
+
+	r = populate_table(t, param);
+	if (r) {
+		dm_table_put(t);
+		return r;
+	}
+
+	md = find_device(param);
+	if (!md) {
+		dm_table_put(t);
+		return -ENXIO;
+	}
+
+	r = dm_swap_table(md, t);
+	if (r) {
+		dm_put(md);
+		dm_table_put(t);
+		return r;
+	}
+	dm_table_put(t);	/* md will have taken its own reference */
+
+	set_disk_ro(dm_disk(md), (param->flags & DM_READONLY_FLAG) ? 1 : 0);
+	dm_put(md);
+
+	r = info(param, user);
+	return r;
+}
+
+static int rename(struct dm_ioctl *param, struct dm_ioctl *user)
+{
+	int r;
+	char *new_name = (char *) param + param->data_start;
+
+	if (valid_str(new_name, (void *) param,
+		      (void *) param + param->data_size)) {
+		DMWARN("Invalid new logical volume name supplied.");
+		return -EINVAL;
+	}
+
+	r = check_name(new_name);
+	if (r)
+		return r;
+
+	return dm_hash_rename(param->name, new_name);
+}
+
+
+/*-----------------------------------------------------------------
+ * Implementation of open/close/ioctl on the special char
+ * device.
+ *---------------------------------------------------------------*/
+static ioctl_fn lookup_ioctl(unsigned int cmd)
+{
+	static struct {
+		int cmd;
+		ioctl_fn fn;
+	} _ioctls[] = {
+		{DM_VERSION_CMD, NULL},	/* version is dealt with elsewhere */
+		{DM_REMOVE_ALL_CMD, remove_all},
+		{DM_DEV_CREATE_CMD, create},
+		{DM_DEV_REMOVE_CMD, remove},
+		{DM_DEV_RELOAD_CMD, reload},
+		{DM_DEV_RENAME_CMD, rename},
+		{DM_DEV_SUSPEND_CMD, suspend},
+		{DM_DEV_DEPS_CMD, dep},
+		{DM_DEV_STATUS_CMD, info},
+		{DM_TARGET_STATUS_CMD, get_status},
+		{DM_TARGET_WAIT_CMD, wait_device_event},
+	};
+
+	return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn;
+}
+
+/*
+ * As well as checking the version compatibility this always
+ * copies the kernel interface version out.
+ */
+static int check_version(unsigned int cmd, struct dm_ioctl *user)
+{
+	uint32_t version[3];
+	int r = 0;
+
+	if (copy_from_user(version, user->version, sizeof(version)))
+		return -EFAULT;
+
+	if ((DM_VERSION_MAJOR != version[0]) ||
+	    (DM_VERSION_MINOR < version[1])) {
+		DMWARN("ioctl interface mismatch: "
+		       "kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)",
+		       DM_VERSION_MAJOR, DM_VERSION_MINOR,
+		       DM_VERSION_PATCHLEVEL,
+		       version[0], version[1], version[2], cmd);
+		r = -EINVAL;
+	}
+
+	/*
+	 * Fill in the kernel version.
+	 */
+	version[0] = DM_VERSION_MAJOR;
+	version[1] = DM_VERSION_MINOR;
+	version[2] = DM_VERSION_PATCHLEVEL;
+	if (copy_to_user(user->version, version, sizeof(version)))
+		return -EFAULT;
+
+	return r;
+}
+
+static void free_params(struct dm_ioctl *param)
+{
+	vfree(param);
+}
+
+static int copy_params(struct dm_ioctl *user, struct dm_ioctl **param)
+{
+	struct dm_ioctl tmp, *dmi;
+
+	if (copy_from_user(&tmp, user, sizeof(tmp)))
+		return -EFAULT;
+
+	if (tmp.data_size < sizeof(tmp))
+		return -EINVAL;
+
+	dmi = (struct dm_ioctl *) vmalloc(tmp.data_size);
+	if (!dmi)
+		return -ENOMEM;
+
+	if (copy_from_user(dmi, user, tmp.data_size)) {
+		vfree(dmi);
+		return -EFAULT;
+	}
+
+	*param = dmi;
+	return 0;
+}
+
+static int validate_params(uint cmd, struct dm_ioctl *param)
+{
+	/* Ignores parameters */
+	if (cmd == DM_REMOVE_ALL_CMD)
+		return 0;
+
+	/* Unless creating, either name of uuid but not both */
+	if (cmd != DM_DEV_CREATE_CMD) {
+		if ((!*param->uuid && !*param->name) ||
+		    (*param->uuid && *param->name)) {
+			DMWARN("one of name or uuid must be supplied");
+			return -EINVAL;
+		}
+	}
+
+	/* Ensure strings are terminated */
+	param->name[DM_NAME_LEN - 1] = '\0';
+	param->uuid[DM_UUID_LEN - 1] = '\0';
+
+	return 0;
+}
+
+static int ctl_ioctl(struct inode *inode, struct file *file,
+		     uint command, ulong u)
+{
+	int r = 0;
+	unsigned int cmd;
+	struct dm_ioctl *param;
+	struct dm_ioctl *user = (struct dm_ioctl *) u;
+	ioctl_fn fn = NULL;
+
+	/* only root can play with this */
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	if (_IOC_TYPE(command) != DM_IOCTL)
+		return -ENOTTY;
+
+	cmd = _IOC_NR(command);
+
+	/*
+	 * Check the interface version passed in.  This also
+	 * writes out the kernels interface version.
+	 */
+	r = check_version(cmd, user);
+	if (r)
+		return r;
+
+	/*
+	 * Nothing more to do for the version command.
+	 */
+	if (cmd == DM_VERSION_CMD)
+		return 0;
+
+	fn = lookup_ioctl(cmd);
+	if (!fn) {
+		DMWARN("dm_ctl_ioctl: unknown command 0x%x", command);
+		return -ENOTTY;
+	}
+
+	/*
+	 * Copy the parameters into kernel space.
+	 */
+	r = copy_params(user, &param);
+	if (r)
+		return r;
+
+	r = validate_params(cmd, param);
+	if (r) {
+		free_params(param);
+		return r;
+	}
+
+	r = fn(param, user);
+	free_params(param);
+	return r;
+}
+
+static struct file_operations _ctl_fops = {
+	.ioctl	 = ctl_ioctl,
+	.owner	 = THIS_MODULE,
+};
+
+static struct miscdevice _dm_misc = {
+	.minor		= MISC_DYNAMIC_MINOR,
+	.name		= DM_NAME,
+	.devfs_name	= "mapper/control",
+	.fops		= &_ctl_fops
+};
+
+/*
+ * Create misc character device and link to DM_DIR/control.
+ */
+int __init dm_interface_init(void)
+{
+	int r;
+
+	r = dm_hash_init();
+	if (r)
+		return r;
+
+	r = misc_register(&_dm_misc);
+	if (r) {
+		DMERR("misc_register failed for control device");
+		dm_hash_exit();
+		return r;
+	}
+
+	DMINFO("%d.%d.%d%s initialised: %s", DM_VERSION_MAJOR,
+	       DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, DM_VERSION_EXTRA,
+	       DM_DRIVER_EMAIL);
+	return 0;
+
+	if (misc_deregister(&_dm_misc) < 0)
+		DMERR("misc_deregister failed for control device");
+	dm_hash_exit();
+	return r;
+}
+
+void dm_interface_exit(void)
+{
+	if (misc_deregister(&_dm_misc) < 0)
+		DMERR("misc_deregister failed for control device");
+	dm_hash_exit();
+}
diff -Nru a/drivers/md/dm-ioctl-v4.c b/drivers/md/dm-ioctl-v4.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/md/dm-ioctl-v4.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,1252 @@
+/*
+ * Copyright (C) 2001, 2002 Sistina Software (UK) Limited.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm.h"
+
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/blk.h>
+#include <linux/slab.h>
+#include <linux/devfs_fs_kernel.h>
+
+#include <asm/uaccess.h>
+
+#define DM_DRIVER_EMAIL "dm@uk.sistina.com"
+
+/*-----------------------------------------------------------------
+ * The ioctl interface needs to be able to look up devices by
+ * name or uuid.
+ *---------------------------------------------------------------*/
+struct hash_cell {
+	struct list_head name_list;
+	struct list_head uuid_list;
+
+	char *name;
+	char *uuid;
+	struct mapped_device *md;
+	struct dm_table *new_map;
+};
+
+#define NUM_BUCKETS 64
+#define MASK_BUCKETS (NUM_BUCKETS - 1)
+static struct list_head _name_buckets[NUM_BUCKETS];
+static struct list_head _uuid_buckets[NUM_BUCKETS];
+
+void dm_hash_remove_all(void);
+
+/*
+ * Guards access to both hash tables.
+ */
+static DECLARE_RWSEM(_hash_lock);
+
+static void init_buckets(struct list_head *buckets)
+{
+	unsigned int i;
+
+	for (i = 0; i < NUM_BUCKETS; i++)
+		INIT_LIST_HEAD(buckets + i);
+}
+
+int dm_hash_init(void)
+{
+	init_buckets(_name_buckets);
+	init_buckets(_uuid_buckets);
+	devfs_mk_dir(DM_DIR);
+	return 0;
+}
+
+void dm_hash_exit(void)
+{
+	dm_hash_remove_all();
+	devfs_remove(DM_DIR);
+}
+
+/*-----------------------------------------------------------------
+ * Hash function:
+ * We're not really concerned with the str hash function being
+ * fast since it's only used by the ioctl interface.
+ *---------------------------------------------------------------*/
+static unsigned int hash_str(const char *str)
+{
+	const unsigned int hash_mult = 2654435387U;
+	unsigned int h = 0;
+
+	while (*str)
+		h = (h + (unsigned int) *str++) * hash_mult;
+
+	return h & MASK_BUCKETS;
+}
+
+/*-----------------------------------------------------------------
+ * Code for looking up a device by name
+ *---------------------------------------------------------------*/
+static struct hash_cell *__get_name_cell(const char *str)
+{
+	struct list_head *tmp;
+	struct hash_cell *hc;
+	unsigned int h = hash_str(str);
+
+	list_for_each (tmp, _name_buckets + h) {
+		hc = list_entry(tmp, struct hash_cell, name_list);
+		if (!strcmp(hc->name, str))
+			return hc;
+	}
+
+	return NULL;
+}
+
+static struct hash_cell *__get_uuid_cell(const char *str)
+{
+	struct list_head *tmp;
+	struct hash_cell *hc;
+	unsigned int h = hash_str(str);
+
+	list_for_each (tmp, _uuid_buckets + h) {
+		hc = list_entry(tmp, struct hash_cell, uuid_list);
+		if (!strcmp(hc->uuid, str))
+			return hc;
+	}
+
+	return NULL;
+}
+
+/*-----------------------------------------------------------------
+ * Inserting, removing and renaming a device.
+ *---------------------------------------------------------------*/
+static inline char *kstrdup(const char *str)
+{
+	char *r = kmalloc(strlen(str) + 1, GFP_KERNEL);
+	if (r)
+		strcpy(r, str);
+	return r;
+}
+
+static struct hash_cell *alloc_cell(const char *name, const char *uuid,
+				    struct mapped_device *md)
+{
+	struct hash_cell *hc;
+
+	hc = kmalloc(sizeof(*hc), GFP_KERNEL);
+	if (!hc)
+		return NULL;
+
+	hc->name = kstrdup(name);
+	if (!hc->name) {
+		kfree(hc);
+		return NULL;
+	}
+
+	if (!uuid)
+		hc->uuid = NULL;
+
+	else {
+		hc->uuid = kstrdup(uuid);
+		if (!hc->uuid) {
+			kfree(hc->name);
+			kfree(hc);
+			return NULL;
+		}
+	}
+
+	INIT_LIST_HEAD(&hc->name_list);
+	INIT_LIST_HEAD(&hc->uuid_list);
+	hc->md = md;
+	hc->new_map = NULL;
+	return hc;
+}
+
+static void free_cell(struct hash_cell *hc)
+{
+	if (hc) {
+		kfree(hc->name);
+		kfree(hc->uuid);
+		kfree(hc);
+	}
+}
+
+/*
+ * devfs stuff.
+ */
+static int register_with_devfs(struct hash_cell *hc)
+{
+	struct gendisk *disk = dm_disk(hc->md);
+
+	devfs_mk_bdev(MKDEV(disk->major, disk->first_minor),
+		      S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP,
+		      DM_DIR "/%s", hc->name);
+	return 0;
+}
+
+static int unregister_with_devfs(struct hash_cell *hc)
+{
+	devfs_remove(DM_DIR"/%s", hc->name);
+	return 0;
+}
+
+/*
+ * The kdev_t and uuid of a device can never change once it is
+ * initially inserted.
+ */
+int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md)
+{
+	struct hash_cell *cell;
+
+	/*
+	 * Allocate the new cells.
+	 */
+	cell = alloc_cell(name, uuid, md);
+	if (!cell)
+		return -ENOMEM;
+
+	/*
+	 * Insert the cell into both hash tables.
+	 */
+	down_write(&_hash_lock);
+	if (__get_name_cell(name))
+		goto bad;
+
+	list_add(&cell->name_list, _name_buckets + hash_str(name));
+
+	if (uuid) {
+		if (__get_uuid_cell(uuid)) {
+			list_del(&cell->name_list);
+			goto bad;
+		}
+		list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid));
+	}
+	register_with_devfs(cell);
+	dm_get(md);
+	up_write(&_hash_lock);
+
+	return 0;
+
+ bad:
+	up_write(&_hash_lock);
+	free_cell(cell);
+	return -EBUSY;
+}
+
+void __hash_remove(struct hash_cell *hc)
+{
+	/* remove from the dev hash */
+	list_del(&hc->uuid_list);
+	list_del(&hc->name_list);
+	unregister_with_devfs(hc);
+	dm_put(hc->md);
+	if (hc->new_map)
+		dm_table_put(hc->new_map);
+	free_cell(hc);
+}
+
+void dm_hash_remove_all(void)
+{
+	int i;
+	struct hash_cell *hc;
+	struct list_head *tmp, *n;
+
+	down_write(&_hash_lock);
+	for (i = 0; i < NUM_BUCKETS; i++) {
+		list_for_each_safe (tmp, n, _name_buckets + i) {
+			hc = list_entry(tmp, struct hash_cell, name_list);
+			__hash_remove(hc);
+		}
+	}
+	up_write(&_hash_lock);
+}
+
+int dm_hash_rename(const char *old, const char *new)
+{
+	char *new_name, *old_name;
+	struct hash_cell *hc;
+
+	/*
+	 * duplicate new.
+	 */
+	new_name = kstrdup(new);
+	if (!new_name)
+		return -ENOMEM;
+
+	down_write(&_hash_lock);
+
+	/*
+	 * Is new free ?
+	 */
+	hc = __get_name_cell(new);
+	if (hc) {
+		DMWARN("asked to rename to an already existing name %s -> %s",
+		       old, new);
+		up_write(&_hash_lock);
+		kfree(new_name);
+		return -EBUSY;
+	}
+
+	/*
+	 * Is there such a device as 'old' ?
+	 */
+	hc = __get_name_cell(old);
+	if (!hc) {
+		DMWARN("asked to rename a non existent device %s -> %s",
+		       old, new);
+		up_write(&_hash_lock);
+		kfree(new_name);
+		return -ENXIO;
+	}
+
+	/*
+	 * rename and move the name cell.
+	 */
+	unregister_with_devfs(hc);
+
+	list_del(&hc->name_list);
+	old_name = hc->name;
+	hc->name = new_name;
+	list_add(&hc->name_list, _name_buckets + hash_str(new_name));
+
+	/* rename the device node in devfs */
+	register_with_devfs(hc);
+
+	up_write(&_hash_lock);
+	kfree(old_name);
+	return 0;
+}
+
+/*-----------------------------------------------------------------
+ * Implementation of the ioctl commands
+ *---------------------------------------------------------------*/
+/*
+ * All the ioctl commands get dispatched to functions with this
+ * prototype.
+ */
+typedef int (*ioctl_fn)(struct dm_ioctl *param, size_t param_size);
+
+static int remove_all(struct dm_ioctl *param, size_t param_size)
+{
+	dm_hash_remove_all();
+	param->data_size = 0;
+	return 0;
+}
+
+/*
+ * Round up the ptr to an 8-byte boundary.
+ */
+#define ALIGN_MASK 7
+static inline void *align_ptr(void *ptr)
+{
+	return (void *) (((size_t) (ptr + ALIGN_MASK)) & ~ALIGN_MASK);
+}
+
+/*
+ * Retrieves the data payload buffer from an already allocated
+ * struct dm_ioctl.
+ */
+static void *get_result_buffer(struct dm_ioctl *param, size_t param_size,
+			       size_t *len)
+{
+	param->data_start = align_ptr(param + 1) - (void *) param;
+
+	if (param->data_start < param_size)
+		*len = param_size - param->data_start;
+	else
+		*len = 0;
+
+	return ((void *) param) + param->data_start;
+}
+
+static int list_devices(struct dm_ioctl *param, size_t param_size)
+{
+	unsigned int i;
+	struct hash_cell *hc;
+	size_t len, needed = 0;
+	struct gendisk *disk;
+	struct dm_name_list *nl, *old_nl = NULL;
+
+	down_write(&_hash_lock);
+
+	/*
+	 * Loop through all the devices working out how much
+	 * space we need.
+	 */
+	for (i = 0; i < NUM_BUCKETS; i++) {
+		list_for_each_entry (hc, _name_buckets + i, name_list) {
+			needed += sizeof(struct dm_name_list);
+			needed += strlen(hc->name);
+			needed += ALIGN_MASK;
+		}
+	}
+
+	/*
+	 * Grab our output buffer.
+	 */
+	nl = get_result_buffer(param, param_size, &len);
+	if (len < needed) {
+		param->flags |= DM_BUFFER_FULL_FLAG;
+		goto out;
+	}
+	param->data_size = param->data_start + needed;
+
+	nl->dev = 0;	/* Flags no data */
+
+	/*
+	 * Now loop through filling out the names.
+	 */
+	for (i = 0; i < NUM_BUCKETS; i++) {
+		list_for_each_entry (hc, _name_buckets + i, name_list) {
+			if (old_nl)
+				old_nl->next = (uint32_t) ((void *) nl -
+							   (void *) old_nl);
+			disk = dm_disk(hc->md);
+			nl->dev = MKDEV(disk->major, disk->first_minor);
+			nl->next = 0;
+			strcpy(nl->name, hc->name);
+
+			old_nl = nl;
+			nl = align_ptr(((void *) ++nl) + strlen(hc->name) + 1);
+		}
+	}
+
+ out:
+	up_write(&_hash_lock);
+	return 0;
+}
+
+static int check_name(const char *name)
+{
+	if (strchr(name, '/')) {
+		DMWARN("invalid device name");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Fills in a dm_ioctl structure, ready for sending back to
+ * userland.
+ */
+static int __dev_status(struct mapped_device *md, struct dm_ioctl *param)
+{
+	struct gendisk *disk = dm_disk(md);
+	struct dm_table *table;
+	struct block_device *bdev;
+
+	param->flags &= ~(DM_SUSPEND_FLAG | DM_READONLY_FLAG |
+			  DM_ACTIVE_PRESENT_FLAG);
+
+	if (dm_suspended(md))
+		param->flags |= DM_SUSPEND_FLAG;
+
+	bdev = bdget_disk(disk, 0);
+	if (!bdev)
+		return -ENXIO;
+
+	param->dev = MKDEV(disk->major, disk->first_minor);
+
+	/*
+	 * Yes, this will be out of date by the time it gets back
+	 * to userland, but it is still very useful ofr
+	 * debugging.
+	 */
+	param->open_count = bdev->bd_openers;
+	bdput(bdev);
+
+	if (disk->policy)
+		param->flags |= DM_READONLY_FLAG;
+
+	param->event_nr = dm_get_event_nr(md);
+
+	table = dm_get_table(md);
+	if (table) {
+		param->flags |= DM_ACTIVE_PRESENT_FLAG;
+		param->target_count = dm_table_get_num_targets(table);
+		dm_table_put(table);
+	} else
+		param->target_count = 0;
+
+	return 0;
+}
+
+static int dev_create(struct dm_ioctl *param, size_t param_size)
+{
+	int r;
+	struct mapped_device *md;
+
+	r = check_name(param->name);
+	if (r)
+		return r;
+
+	if (param->flags & DM_PERSISTENT_DEV_FLAG)
+		r = dm_create_with_minor(minor(to_kdev_t(param->dev)), &md);
+	else
+		r = dm_create(&md);
+
+	if (r)
+		return r;
+
+	r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md);
+	if (r) {
+		dm_put(md);
+		return r;
+	}
+
+	param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
+
+	r = __dev_status(md, param);
+	dm_put(md);
+
+	return r;
+}
+
+/*
+ * Always use UUID for lookups if it's present, otherwise use name.
+ */
+static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param)
+{
+	return *param->uuid ?
+	    __get_uuid_cell(param->uuid) : __get_name_cell(param->name);
+}
+
+static inline struct mapped_device *find_device(struct dm_ioctl *param)
+{
+	struct hash_cell *hc;
+	struct mapped_device *md = NULL;
+
+	down_read(&_hash_lock);
+	hc = __find_device_hash_cell(param);
+	if (hc) {
+		md = hc->md;
+
+		/*
+		 * Sneakily write in both the name and the uuid
+		 * while we have the cell.
+		 */
+		strncpy(param->name, hc->name, sizeof(param->name));
+		if (hc->uuid)
+			strncpy(param->uuid, hc->uuid, sizeof(param->uuid)-1);
+		else
+			param->uuid[0] = '\0';
+
+		if (hc->new_map)
+			param->flags |= DM_INACTIVE_PRESENT_FLAG;
+		else
+			param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
+
+		dm_get(md);
+	}
+	up_read(&_hash_lock);
+
+	return md;
+}
+
+static int dev_remove(struct dm_ioctl *param, size_t param_size)
+{
+	struct hash_cell *hc;
+
+	down_write(&_hash_lock);
+	hc = __find_device_hash_cell(param);
+
+	if (!hc) {
+		DMWARN("device doesn't appear to be in the dev hash table.");
+		up_write(&_hash_lock);
+		return -ENXIO;
+	}
+
+	__hash_remove(hc);
+	up_write(&_hash_lock);
+	param->data_size = 0;
+	return 0;
+}
+
+/*
+ * Check a string doesn't overrun the chunk of
+ * memory we copied from userland.
+ */
+static int invalid_str(char *str, void *end)
+{
+	while ((void *) str < end)
+		if (!*str++)
+			return 0;
+
+	return -EINVAL;
+}
+
+static int dev_rename(struct dm_ioctl *param, size_t param_size)
+{
+	int r;
+	char *new_name = (char *) param + param->data_start;
+
+	if (new_name < (char *) (param + 1) ||
+	    invalid_str(new_name, (void *) param + param_size)) {
+		DMWARN("Invalid new logical volume name supplied.");
+		return -EINVAL;
+	}
+
+	r = check_name(new_name);
+	if (r)
+		return r;
+
+	param->data_size = 0;
+	return dm_hash_rename(param->name, new_name);
+}
+
+static int suspend(struct dm_ioctl *param)
+{
+	int r = 0;
+	struct mapped_device *md;
+
+	md = find_device(param);
+	if (!md)
+		return -ENXIO;
+
+	if (!dm_suspended(md))
+		r = dm_suspend(md);
+
+	if (!r)
+		r = __dev_status(md, param);
+
+	dm_put(md);
+	return r;
+}
+
+static int resume(struct dm_ioctl *param)
+{
+	int r = 0;
+	struct hash_cell *hc;
+	struct mapped_device *md;
+	struct dm_table *new_map;
+
+	down_write(&_hash_lock);
+
+	hc = __find_device_hash_cell(param);
+	if (!hc) {
+		DMWARN("device doesn't appear to be in the dev hash table.");
+		up_write(&_hash_lock);
+		return -ENXIO;
+	}
+
+	md = hc->md;
+	dm_get(md);
+
+	new_map = hc->new_map;
+	hc->new_map = NULL;
+	param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
+
+	up_write(&_hash_lock);
+
+	/* Do we need to load a new map ? */
+	if (new_map) {
+		/* Suspend if it isn't already suspended */
+		if (!dm_suspended(md))
+			dm_suspend(md);
+
+		r = dm_swap_table(md, new_map);
+		if (r) {
+			dm_put(md);
+			dm_table_put(new_map);
+			return r;
+		}
+
+		if (dm_table_get_mode(new_map) & FMODE_WRITE)
+			set_disk_ro(dm_disk(md), 0);
+		else
+			set_disk_ro(dm_disk(md), 1);
+
+		dm_table_put(new_map);
+	}
+
+	if (dm_suspended(md))
+		r = dm_resume(md);
+
+	if (!r)
+		r = __dev_status(md, param);
+
+	dm_put(md);
+	return r;
+}
+
+/*
+ * Set or unset the suspension state of a device.
+ * If the device already is in the requested state we just return its status.
+ */
+static int dev_suspend(struct dm_ioctl *param, size_t param_size)
+{
+	if (param->flags & DM_SUSPEND_FLAG)
+		return suspend(param);
+
+	return resume(param);
+}
+
+/*
+ * Copies device info back to user space, used by
+ * the create and info ioctls.
+ */
+static int dev_status(struct dm_ioctl *param, size_t param_size)
+{
+	int r;
+	struct mapped_device *md;
+
+	md = find_device(param);
+	if (!md)
+		return -ENXIO;
+
+	r = __dev_status(md, param);
+	dm_put(md);
+	return r;
+}
+
+/*
+ * Wait for a device to report an event
+ */
+static int dev_wait(struct dm_ioctl *param, size_t param_size)
+{
+	int r;
+	struct mapped_device *md;
+	DECLARE_WAITQUEUE(wq, current);
+
+	md = find_device(param);
+	if (!md)
+		return -ENXIO;
+
+	/*
+	 * Wait for a notification event
+	 */
+	set_current_state(TASK_INTERRUPTIBLE);
+	if (!dm_add_wait_queue(md, &wq, param->event_nr)) {
+		schedule();
+		dm_remove_wait_queue(md, &wq);
+	}
+ 	set_current_state(TASK_RUNNING);
+
+	/*
+	 * The userland program is going to want to know what
+	 * changed to trigger the event, so we may as well tell
+	 * him and save an ioctl.
+	 */
+	r = __dev_status(md, param);
+
+	dm_put(md);
+	return r;
+}
+
+static inline int get_mode(struct dm_ioctl *param)
+{
+	int mode = FMODE_READ | FMODE_WRITE;
+
+	if (param->flags & DM_READONLY_FLAG)
+		mode = FMODE_READ;
+
+	return mode;
+}
+
+static int next_target(struct dm_target_spec *last, uint32_t next, void *end,
+		       struct dm_target_spec **spec, char **target_params)
+{
+	*spec = (struct dm_target_spec *) ((unsigned char *) last + next);
+	*target_params = (char *) (*spec + 1);
+
+	if (*spec < (last + 1))
+		return -EINVAL;
+
+	return invalid_str(*target_params, end);
+}
+
+static int populate_table(struct dm_table *table,
+			  struct dm_ioctl *param, size_t param_size)
+{
+	int r;
+	unsigned int i = 0;
+	struct dm_target_spec *spec = (struct dm_target_spec *) param;
+	uint32_t next = param->data_start;
+	void *end = (void *) param + param_size;
+	char *target_params;
+
+	if (!param->target_count) {
+		DMWARN("populate_table: no targets specified");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < param->target_count; i++) {
+
+		r = next_target(spec, next, end, &spec, &target_params);
+		if (r) {
+			DMWARN("unable to find target");
+			return r;
+		}
+
+		r = dm_table_add_target(table, spec->target_type,
+					(sector_t) spec->sector_start,
+					(sector_t) spec->length,
+					target_params);
+		if (r) {
+			DMWARN("error adding target to table");
+			return r;
+		}
+
+		next = spec->next;
+	}
+
+	return dm_table_complete(table);
+}
+
+static int table_load(struct dm_ioctl *param, size_t param_size)
+{
+	int r;
+	struct hash_cell *hc;
+	struct dm_table *t;
+
+	r = dm_table_create(&t, get_mode(param));
+	if (r)
+		return r;
+
+	r = populate_table(t, param, param_size);
+	if (r) {
+		dm_table_put(t);
+		return r;
+	}
+
+	down_write(&_hash_lock);
+	hc = __find_device_hash_cell(param);
+	if (!hc) {
+		DMWARN("device doesn't appear to be in the dev hash table.");
+		up_write(&_hash_lock);
+		return -ENXIO;
+	}
+
+	hc->new_map = t;
+	param->flags |= DM_INACTIVE_PRESENT_FLAG;
+
+	r = __dev_status(hc->md, param);
+	up_write(&_hash_lock);
+	return r;
+}
+
+static int table_clear(struct dm_ioctl *param, size_t param_size)
+{
+	int r;
+	struct hash_cell *hc;
+
+	down_write(&_hash_lock);
+
+	hc = __find_device_hash_cell(param);
+	if (!hc) {
+		DMWARN("device doesn't appear to be in the dev hash table.");
+		up_write(&_hash_lock);
+		return -ENXIO;
+	}
+
+	if (hc->new_map) {
+		dm_table_put(hc->new_map);
+		hc->new_map = NULL;
+	}
+
+	param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
+
+	r = __dev_status(hc->md, param);
+	up_write(&_hash_lock);
+	return r;
+}
+
+/*
+ * Retrieves a list of devices used by a particular dm device.
+ */
+static void retrieve_deps(struct dm_table *table,
+			  struct dm_ioctl *param, size_t param_size)
+{
+	unsigned int count = 0;
+	struct list_head *tmp;
+	size_t len, needed;
+	struct dm_target_deps *deps;
+
+	deps = get_result_buffer(param, param_size, &len);
+
+	/*
+	 * Count the devices.
+	 */
+	list_for_each(tmp, dm_table_get_devices(table))
+		count++;
+
+	/*
+	 * Check we have enough space.
+	 */
+	needed = sizeof(*deps) + (sizeof(*deps->dev) * count);
+	if (len < needed) {
+		param->flags |= DM_BUFFER_FULL_FLAG;
+		return;
+	}
+
+	/*
+	 * Fill in the devices.
+	 */
+	deps->count = count;
+	count = 0;
+	list_for_each(tmp, dm_table_get_devices(table)) {
+		struct dm_dev *dd = list_entry(tmp, struct dm_dev, list);
+		deps->dev[count++] = dd->bdev->bd_dev;
+	}
+
+	param->data_size = param->data_start + needed;
+}
+
+static int table_deps(struct dm_ioctl *param, size_t param_size)
+{
+	int r = 0;
+	struct mapped_device *md;
+	struct dm_table *table;
+
+	md = find_device(param);
+	if (!md)
+		return -ENXIO;
+
+	r = __dev_status(md, param);
+	if (r)
+		goto out;
+
+	table = dm_get_table(md);
+	if (table) {
+		retrieve_deps(table, param, param_size);
+		dm_table_put(table);
+	}
+
+ out:
+	dm_put(md);
+	return r;
+}
+
+/*
+ * Build up the status struct for each target
+ */
+static void retrieve_status(struct dm_table *table,
+			    struct dm_ioctl *param, size_t param_size)
+{
+	unsigned int i, num_targets;
+	struct dm_target_spec *spec;
+	char *outbuf, *outptr;
+	status_type_t type;
+	size_t remaining, len, used = 0;
+
+	outptr = outbuf = get_result_buffer(param, param_size, &len);
+
+	if (param->flags & DM_STATUS_TABLE_FLAG)
+		type = STATUSTYPE_TABLE;
+	else
+		type = STATUSTYPE_INFO;
+
+	/* Get all the target info */
+	num_targets = dm_table_get_num_targets(table);
+	for (i = 0; i < num_targets; i++) {
+		struct dm_target *ti = dm_table_get_target(table, i);
+
+		remaining = len - (outptr - outbuf);
+		if (remaining < sizeof(struct dm_target_spec)) {
+			param->flags |= DM_BUFFER_FULL_FLAG;
+			break;
+		}
+
+		spec = (struct dm_target_spec *) outptr;
+
+		spec->status = 0;
+		spec->sector_start = ti->begin;
+		spec->length = ti->len;
+		strncpy(spec->target_type, ti->type->name,
+			sizeof(spec->target_type));
+
+		outptr += sizeof(struct dm_target_spec);
+		remaining = len - (outptr - outbuf);
+
+		/* Get the status/table string from the target driver */
+		if (ti->type->status) {
+			if (ti->type->status(ti, type, outptr, remaining)) {
+				param->flags |= DM_BUFFER_FULL_FLAG;
+				break;
+			}
+		} else
+			outptr[0] = '\0';
+
+		outptr += strlen(outptr) + 1;
+		used = param->data_start + (outptr - outbuf);
+
+		align_ptr(outptr);
+		spec->next = outptr - outbuf;
+	}
+
+	if (used)
+		param->data_size = used;
+
+	param->target_count = num_targets;
+}
+
+/*
+ * Return the status of a device as a text string for each
+ * target.
+ */
+static int table_status(struct dm_ioctl *param, size_t param_size)
+{
+	int r;
+	struct mapped_device *md;
+	struct dm_table *table;
+
+	md = find_device(param);
+	if (!md)
+		return -ENXIO;
+
+	r = __dev_status(md, param);
+	if (r)
+		goto out;
+
+	table = dm_get_table(md);
+	if (table) {
+		retrieve_status(table, param, param_size);
+		dm_table_put(table);
+	}
+
+ out:
+	dm_put(md);
+	return r;
+}
+
+/*-----------------------------------------------------------------
+ * Implementation of open/close/ioctl on the special char
+ * device.
+ *---------------------------------------------------------------*/
+static ioctl_fn lookup_ioctl(unsigned int cmd)
+{
+	static struct {
+		int cmd;
+		ioctl_fn fn;
+	} _ioctls[] = {
+		{DM_VERSION_CMD, NULL},	/* version is dealt with elsewhere */
+		{DM_REMOVE_ALL_CMD, remove_all},
+		{DM_LIST_DEVICES_CMD, list_devices},
+
+		{DM_DEV_CREATE_CMD, dev_create},
+		{DM_DEV_REMOVE_CMD, dev_remove},
+		{DM_DEV_RENAME_CMD, dev_rename},
+		{DM_DEV_SUSPEND_CMD, dev_suspend},
+		{DM_DEV_STATUS_CMD, dev_status},
+		{DM_DEV_WAIT_CMD, dev_wait},
+
+		{DM_TABLE_LOAD_CMD, table_load},
+		{DM_TABLE_CLEAR_CMD, table_clear},
+		{DM_TABLE_DEPS_CMD, table_deps},
+		{DM_TABLE_STATUS_CMD, table_status}
+	};
+
+	return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn;
+}
+
+/*
+ * As well as checking the version compatibility this always
+ * copies the kernel interface version out.
+ */
+static int check_version(unsigned int cmd, struct dm_ioctl *user)
+{
+	uint32_t version[3];
+	int r = 0;
+
+	if (copy_from_user(version, user->version, sizeof(version)))
+		return -EFAULT;
+
+	if ((DM_VERSION_MAJOR != version[0]) ||
+	    (DM_VERSION_MINOR < version[1])) {
+		DMWARN("ioctl interface mismatch: "
+		       "kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)",
+		       DM_VERSION_MAJOR, DM_VERSION_MINOR,
+		       DM_VERSION_PATCHLEVEL,
+		       version[0], version[1], version[2], cmd);
+		r = -EINVAL;
+	}
+
+	/*
+	 * Fill in the kernel version.
+	 */
+	version[0] = DM_VERSION_MAJOR;
+	version[1] = DM_VERSION_MINOR;
+	version[2] = DM_VERSION_PATCHLEVEL;
+	if (copy_to_user(user->version, version, sizeof(version)))
+		return -EFAULT;
+
+	return r;
+}
+
+static void free_params(struct dm_ioctl *param)
+{
+	vfree(param);
+}
+
+static int copy_params(struct dm_ioctl *user, struct dm_ioctl **param)
+{
+	struct dm_ioctl tmp, *dmi;
+
+	if (copy_from_user(&tmp, user, sizeof(tmp)))
+		return -EFAULT;
+
+	if (tmp.data_size < sizeof(tmp))
+		return -EINVAL;
+
+	dmi = (struct dm_ioctl *) vmalloc(tmp.data_size);
+	if (!dmi)
+		return -ENOMEM;
+
+	if (copy_from_user(dmi, user, tmp.data_size)) {
+		vfree(dmi);
+		return -EFAULT;
+	}
+
+	*param = dmi;
+	return 0;
+}
+
+static int validate_params(uint cmd, struct dm_ioctl *param)
+{
+	/* Always clear this flag */
+	param->flags &= ~DM_BUFFER_FULL_FLAG;
+
+	/* Ignores parameters */
+	if (cmd == DM_REMOVE_ALL_CMD || cmd == DM_LIST_DEVICES_CMD)
+		return 0;
+
+	/* Unless creating, either name or uuid but not both */
+	if (cmd != DM_DEV_CREATE_CMD) {
+		if ((!*param->uuid && !*param->name) ||
+		    (*param->uuid && *param->name)) {
+			DMWARN("one of name or uuid must be supplied, cmd(%u)",
+			       cmd);
+			return -EINVAL;
+		}
+	}
+
+	/* Ensure strings are terminated */
+	param->name[DM_NAME_LEN - 1] = '\0';
+	param->uuid[DM_UUID_LEN - 1] = '\0';
+
+	return 0;
+}
+
+static int ctl_ioctl(struct inode *inode, struct file *file,
+		     uint command, ulong u)
+{
+	int r = 0;
+	unsigned int cmd;
+	struct dm_ioctl *param;
+	struct dm_ioctl *user = (struct dm_ioctl *) u;
+	ioctl_fn fn = NULL;
+	size_t param_size;
+
+	/* only root can play with this */
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	if (_IOC_TYPE(command) != DM_IOCTL)
+		return -ENOTTY;
+
+	cmd = _IOC_NR(command);
+
+	/*
+	 * Check the interface version passed in.  This also
+	 * writes out the kernel's interface version.
+	 */
+	r = check_version(cmd, user);
+	if (r)
+		return r;
+
+	/*
+	 * Nothing more to do for the version command.
+	 */
+	if (cmd == DM_VERSION_CMD)
+		return 0;
+
+	fn = lookup_ioctl(cmd);
+	if (!fn) {
+		DMWARN("dm_ctl_ioctl: unknown command 0x%x", command);
+		return -ENOTTY;
+	}
+
+	/*
+	 * Trying to avoid low memory issues when a device is
+	 * suspended.
+	 */
+	current->flags |= PF_MEMALLOC;
+
+	/*
+	 * Copy the parameters into kernel space.
+	 */
+	r = copy_params(user, &param);
+	if (r) {
+		current->flags &= ~PF_MEMALLOC;
+		return r;
+	}
+
+	/*
+	 * FIXME: eventually we will remove the PF_MEMALLOC flag
+	 * here.  However the tools still do nasty things like
+	 * 'load' while a device is suspended.
+	 */
+
+	r = validate_params(cmd, param);
+	if (r)
+		goto out;
+
+	param_size = param->data_size;
+	param->data_size = sizeof(*param);
+	r = fn(param, param_size);
+
+	/*
+	 * Copy the results back to userland.
+	 */
+	if (!r && copy_to_user(user, param, param->data_size))
+		r = -EFAULT;
+
+ out:
+	free_params(param);
+	current->flags &= ~PF_MEMALLOC;
+	return r;
+}
+
+static struct file_operations _ctl_fops = {
+	.ioctl	 = ctl_ioctl,
+	.owner	 = THIS_MODULE,
+};
+
+static struct miscdevice _dm_misc = {
+	.minor 		= MISC_DYNAMIC_MINOR,
+	.name  		= DM_NAME,
+	.devfs_name 	= "mapper/control",
+	.fops  		= &_ctl_fops
+};
+
+/*
+ * Create misc character device and link to DM_DIR/control.
+ */
+int __init dm_interface_init(void)
+{
+	int r;
+
+	r = dm_hash_init();
+	if (r)
+		return r;
+
+	r = misc_register(&_dm_misc);
+	if (r) {
+		DMERR("misc_register failed for control device");
+		dm_hash_exit();
+		return r;
+	}
+
+	DMINFO("%d.%d.%d%s initialised: %s", DM_VERSION_MAJOR,
+	       DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, DM_VERSION_EXTRA,
+	       DM_DRIVER_EMAIL);
+	return 0;
+}
+
+void dm_interface_exit(void)
+{
+	if (misc_deregister(&_dm_misc) < 0)
+		DMERR("misc_deregister failed for control device");
+
+	dm_hash_exit();
+}
diff -Nru a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
--- a/drivers/md/dm-ioctl.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/md/dm-ioctl.c	Sat Jul 19 12:54:24 2003
@@ -1,1134 +1,13 @@
 /*
- * Copyright (C) 2001, 2002 Sistina Software (UK) Limited.
+ * Copyright (C) 2003 Sistina Software (UK) Limited.
  *
  * This file is released under the GPL.
  */
 
-#include "dm.h"
-
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-#include <linux/miscdevice.h>
 #include <linux/dm-ioctl.h>
-#include <linux/init.h>
-#include <linux/wait.h>
-#include <linux/blk.h>
-#include <linux/slab.h>
-#include <linux/devfs_fs_kernel.h>
-
-#include <asm/uaccess.h>
-
-#define DM_DRIVER_EMAIL "dm@uk.sistina.com"
-
-/*-----------------------------------------------------------------
- * The ioctl interface needs to be able to look up devices by
- * name or uuid.
- *---------------------------------------------------------------*/
-struct hash_cell {
-	struct list_head name_list;
-	struct list_head uuid_list;
-
-	char *name;
-	char *uuid;
-	struct mapped_device *md;
-};
-
-#define NUM_BUCKETS 64
-#define MASK_BUCKETS (NUM_BUCKETS - 1)
-static struct list_head _name_buckets[NUM_BUCKETS];
-static struct list_head _uuid_buckets[NUM_BUCKETS];
-
-void dm_hash_remove_all(void);
-
-/*
- * Guards access to all three tables.
- */
-static DECLARE_RWSEM(_hash_lock);
-
-static void init_buckets(struct list_head *buckets)
-{
-	unsigned int i;
-
-	for (i = 0; i < NUM_BUCKETS; i++)
-		INIT_LIST_HEAD(buckets + i);
-}
-
-int dm_hash_init(void)
-{
-	init_buckets(_name_buckets);
-	init_buckets(_uuid_buckets);
-	devfs_mk_dir(DM_DIR);
-	return 0;
-}
-
-void dm_hash_exit(void)
-{
-	dm_hash_remove_all();
-	devfs_remove(DM_DIR);
-}
-
-/*-----------------------------------------------------------------
- * Hash function:
- * We're not really concerned with the str hash function being
- * fast since it's only used by the ioctl interface.
- *---------------------------------------------------------------*/
-static unsigned int hash_str(const char *str)
-{
-	const unsigned int hash_mult = 2654435387U;
-	unsigned int h = 0;
-
-	while (*str)
-		h = (h + (unsigned int) *str++) * hash_mult;
-
-	return h & MASK_BUCKETS;
-}
-
-/*-----------------------------------------------------------------
- * Code for looking up a device by name
- *---------------------------------------------------------------*/
-static struct hash_cell *__get_name_cell(const char *str)
-{
-	struct list_head *tmp;
-	struct hash_cell *hc;
-	unsigned int h = hash_str(str);
-
-	list_for_each (tmp, _name_buckets + h) {
-		hc = list_entry(tmp, struct hash_cell, name_list);
-		if (!strcmp(hc->name, str))
-			return hc;
-	}
-
-	return NULL;
-}
-
-static struct hash_cell *__get_uuid_cell(const char *str)
-{
-	struct list_head *tmp;
-	struct hash_cell *hc;
-	unsigned int h = hash_str(str);
-
-	list_for_each (tmp, _uuid_buckets + h) {
-		hc = list_entry(tmp, struct hash_cell, uuid_list);
-		if (!strcmp(hc->uuid, str))
-			return hc;
-	}
-
-	return NULL;
-}
-
-/*-----------------------------------------------------------------
- * Inserting, removing and renaming a device.
- *---------------------------------------------------------------*/
-static inline char *kstrdup(const char *str)
-{
-	char *r = kmalloc(strlen(str) + 1, GFP_KERNEL);
-	if (r)
-		strcpy(r, str);
-	return r;
-}
-
-static struct hash_cell *alloc_cell(const char *name, const char *uuid,
-				    struct mapped_device *md)
-{
-	struct hash_cell *hc;
-
-	hc = kmalloc(sizeof(*hc), GFP_KERNEL);
-	if (!hc)
-		return NULL;
-
-	hc->name = kstrdup(name);
-	if (!hc->name) {
-		kfree(hc);
-		return NULL;
-	}
-
-	if (!uuid)
-		hc->uuid = NULL;
-
-	else {
-		hc->uuid = kstrdup(uuid);
-		if (!hc->uuid) {
-			kfree(hc->name);
-			kfree(hc);
-			return NULL;
-		}
-	}
-
-	INIT_LIST_HEAD(&hc->name_list);
-	INIT_LIST_HEAD(&hc->uuid_list);
-	hc->md = md;
-	return hc;
-}
-
-static void free_cell(struct hash_cell *hc)
-{
-	if (hc) {
-		kfree(hc->name);
-		kfree(hc->uuid);
-		kfree(hc);
-	}
-}
-
-/*
- * devfs stuff.
- */
-static int register_with_devfs(struct hash_cell *hc)
-{
-	struct gendisk *disk = dm_disk(hc->md);
-
-	devfs_mk_bdev(MKDEV(disk->major, disk->first_minor),
-		       S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP,
-		       DM_DIR "/%s", hc->name);
-	return 0;
-}
-
-static int unregister_with_devfs(struct hash_cell *hc)
-{
-	devfs_remove(DM_DIR"/%s", hc->name);
-	return 0;
-}
-
-/*
- * The kdev_t and uuid of a device can never change once it is
- * initially inserted.
- */
-int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md)
-{
-	struct hash_cell *cell;
-
-	/*
-	 * Allocate the new cells.
-	 */
-	cell = alloc_cell(name, uuid, md);
-	if (!cell)
-		return -ENOMEM;
-
-	/*
-	 * Insert the cell into all three hash tables.
-	 */
-	down_write(&_hash_lock);
-	if (__get_name_cell(name))
-		goto bad;
-
-	list_add(&cell->name_list, _name_buckets + hash_str(name));
-
-	if (uuid) {
-		if (__get_uuid_cell(uuid)) {
-			list_del(&cell->name_list);
-			goto bad;
-		}
-		list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid));
-	}
-	register_with_devfs(cell);
-	dm_get(md);
-	up_write(&_hash_lock);
-
-	return 0;
-
- bad:
-	up_write(&_hash_lock);
-	free_cell(cell);
-	return -EBUSY;
-}
-
-void __hash_remove(struct hash_cell *hc)
-{
-	/* remove from the dev hash */
-	list_del(&hc->uuid_list);
-	list_del(&hc->name_list);
-	unregister_with_devfs(hc);
-	dm_put(hc->md);
-	free_cell(hc);
-}
-
-void dm_hash_remove_all(void)
-{
-	int i;
-	struct hash_cell *hc;
-	struct list_head *tmp, *n;
-
-	down_write(&_hash_lock);
-	for (i = 0; i < NUM_BUCKETS; i++) {
-		list_for_each_safe (tmp, n, _name_buckets + i) {
-			hc = list_entry(tmp, struct hash_cell, name_list);
-			__hash_remove(hc);
-		}
-	}
-	up_write(&_hash_lock);
-}
-
-int dm_hash_rename(const char *old, const char *new)
-{
-	char *new_name, *old_name;
-	struct hash_cell *hc;
-
-	/*
-	 * duplicate new.
-	 */
-	new_name = kstrdup(new);
-	if (!new_name)
-		return -ENOMEM;
-
-	down_write(&_hash_lock);
-
-	/*
-	 * Is new free ?
-	 */
-	hc = __get_name_cell(new);
-	if (hc) {
-		DMWARN("asked to rename to an already existing name %s -> %s",
-		       old, new);
-		up_write(&_hash_lock);
-		kfree(new_name);
-		return -EBUSY;
-	}
-
-	/*
-	 * Is there such a device as 'old' ?
-	 */
-	hc = __get_name_cell(old);
-	if (!hc) {
-		DMWARN("asked to rename a non existent device %s -> %s",
-		       old, new);
-		up_write(&_hash_lock);
-		kfree(new_name);
-		return -ENXIO;
-	}
-
-	/*
-	 * rename and move the name cell.
-	 */
-	unregister_with_devfs(hc);
-
-	list_del(&hc->name_list);
-	old_name = hc->name;
-	hc->name = new_name;
-	list_add(&hc->name_list, _name_buckets + hash_str(new_name));
-
-	/* rename the device node in devfs */
-	register_with_devfs(hc);
-
-	up_write(&_hash_lock);
-	kfree(old_name);
-	return 0;
-}
-
-
-/*-----------------------------------------------------------------
- * Implementation of the ioctl commands
- *---------------------------------------------------------------*/
-
-/*
- * All the ioctl commands get dispatched to functions with this
- * prototype.
- */
-typedef int (*ioctl_fn)(struct dm_ioctl *param, struct dm_ioctl *user);
-
-/*
- * Check a string doesn't overrun the chunk of
- * memory we copied from userland.
- */
-static int valid_str(char *str, void *begin, void *end)
-{
-	while (((void *) str >= begin) && ((void *) str < end))
-		if (!*str++)
-			return 0;
-
-	return -EINVAL;
-}
-
-static int next_target(struct dm_target_spec *last, uint32_t next,
-		       void *begin, void *end,
-		       struct dm_target_spec **spec, char **params)
-{
-	*spec = (struct dm_target_spec *)
-	    ((unsigned char *) last + next);
-	*params = (char *) (*spec + 1);
-
-	if (*spec < (last + 1) || ((void *) *spec > end))
-		return -EINVAL;
-
-	return valid_str(*params, begin, end);
-}
-
-static int populate_table(struct dm_table *table, struct dm_ioctl *args)
-{
-	int r, first = 1;
-	unsigned int i = 0;
-	struct dm_target_spec *spec;
-	char *params;
-	void *begin, *end;
-
-	if (!args->target_count) {
-		DMWARN("populate_table: no targets specified");
-		return -EINVAL;
-	}
-
-	begin = (void *) args;
-	end = begin + args->data_size;
-
-	for (i = 0; i < args->target_count; i++) {
-
-		if (first)
-			r = next_target((struct dm_target_spec *) args,
-					args->data_start,
-					begin, end, &spec, &params);
-		else
-			r = next_target(spec, spec->next, begin, end,
-					&spec, &params);
-
-		if (r) {
-			DMWARN("unable to find target");
-			return -EINVAL;
-		}
-
-		r = dm_table_add_target(table, spec->target_type,
-					(sector_t) spec->sector_start,
-					(sector_t) spec->length,
-					params);
-		if (r) {
-			DMWARN("internal error adding target to table");
-			return -EINVAL;
-		}
-
-		first = 0;
-	}
-
-	return dm_table_complete(table);
-}
-
-/*
- * Round up the ptr to the next 'align' boundary.  Obviously
- * 'align' must be a power of 2.
- */
-static inline void *align_ptr(void *ptr, unsigned int align)
-{
-	align--;
-	return (void *) (((unsigned long) (ptr + align)) & ~align);
-}
-
-/*
- * Copies a dm_ioctl and an optional additional payload to
- * userland.
- */
-static int results_to_user(struct dm_ioctl *user, struct dm_ioctl *param,
-			   void *data, uint32_t len)
-{
-	int r;
-	void *ptr = NULL;
-
-	if (data) {
-		ptr = align_ptr(user + 1, sizeof(unsigned long));
-		param->data_start = ptr - (void *) user;
-	}
-
-	/*
-	 * The version number has already been filled in, so we
-	 * just copy later fields.
-	 */
-	r = copy_to_user(&user->data_size, &param->data_size,
-			 sizeof(*param) - sizeof(param->version));
-	if (r)
-		return -EFAULT;
-
-	if (data) {
-		if (param->data_start + len > param->data_size)
-			return -ENOSPC;
-
-		if (copy_to_user(ptr, data, len))
-			r = -EFAULT;
-	}
-
-	return r;
-}
-
-/*
- * Fills in a dm_ioctl structure, ready for sending back to
- * userland.
- */
-static int __info(struct mapped_device *md, struct dm_ioctl *param)
-{
-	struct dm_table *table;
-	struct block_device *bdev;
-	struct gendisk *disk = dm_disk(md);
-
-	param->flags = DM_EXISTS_FLAG;
-	if (dm_suspended(md))
-		param->flags |= DM_SUSPEND_FLAG;
-
-	bdev = bdget_disk(disk, 0);
-	if (!bdev)
-		return -ENXIO;
-
-	param->dev = bdev->bd_dev;
-	param->open_count = bdev->bd_openers;
-	bdput(bdev);
-
-	if (disk->policy)
-		param->flags |= DM_READONLY_FLAG;
-
-	table = dm_get_table(md);
-	param->target_count = dm_table_get_num_targets(table);
-	dm_table_put(table);
-
-	return 0;
-}
-
-/*
- * Always use UUID for lookups if it's present, otherwise use name.
- */
-static inline struct mapped_device *find_device(struct dm_ioctl *param)
-{
-	struct hash_cell *hc;
-	struct mapped_device *md = NULL;
-
-	down_read(&_hash_lock);
-	hc = *param->uuid ? __get_uuid_cell(param->uuid) :
-		__get_name_cell(param->name);
-	if (hc) {
-		md = hc->md;
-
-		/*
-		 * Sneakily write in both the name and the uuid
-		 * while we have the cell.
-		 */
-		strlcpy(param->name, hc->name, sizeof(param->name));
-		if (hc->uuid)
-			strlcpy(param->uuid, hc->uuid, sizeof(param->uuid));
-		else
-			param->uuid[0] = '\0';
-
-		dm_get(md);
-	}
-	up_read(&_hash_lock);
-
-	return md;
-}
-
-#define ALIGNMENT sizeof(int)
-static void *_align(void *ptr, unsigned int a)
-{
-	register unsigned long align = --a;
-
-	return (void *) (((unsigned long) ptr + align) & ~align);
-}
-
-/*
- * Copies device info back to user space, used by
- * the create and info ioctls.
- */
-static int info(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	struct mapped_device *md;
-
-	param->flags = 0;
-
-	md = find_device(param);
-	if (!md)
-		/*
-		 * Device not found - returns cleared exists flag.
-		 */
-		goto out;
-
-	__info(md, param);
-	dm_put(md);
-
-      out:
-	return results_to_user(user, param, NULL, 0);
-}
-
-static inline int get_mode(struct dm_ioctl *param)
-{
-	int mode = FMODE_READ | FMODE_WRITE;
-
-	if (param->flags & DM_READONLY_FLAG)
-		mode = FMODE_READ;
-
-	return mode;
-}
-
-static int check_name(const char *name)
-{
-	if (name[0] == '/') {
-		DMWARN("invalid device name");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int create(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	int r;
-	struct dm_table *t;
-	struct mapped_device *md;
-
-	r = check_name(param->name);
-	if (r)
-		return r;
-
-	r = dm_table_create(&t, get_mode(param));
-	if (r)
-		return r;
-
-	r = populate_table(t, param);
-	if (r) {
-		dm_table_put(t);
-		return r;
-	}
-
-	if (param->flags & DM_PERSISTENT_DEV_FLAG)
-		r = dm_create_with_minor(minor(to_kdev_t(param->dev)), t, &md);
-	else
-		r = dm_create(t, &md);
-
-	if (r) {
-		dm_table_put(t);
-		return r;
-	}
-	dm_table_put(t);	/* md will have grabbed its own reference */
-
-	set_disk_ro(dm_disk(md), (param->flags & DM_READONLY_FLAG) ? 1 : 0);
-	r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md);
-	dm_put(md);
-
-	return r ? r : info(param, user);
-}
-
-/*
- * Build up the status struct for each target
- */
-static int __status(struct mapped_device *md, struct dm_ioctl *param,
-		    char *outbuf, size_t *len)
-{
-	unsigned int i, num_targets;
-	struct dm_target_spec *spec;
-	char *outptr;
-	status_type_t type;
-	struct dm_table *table = dm_get_table(md);
-
-	if (param->flags & DM_STATUS_TABLE_FLAG)
-		type = STATUSTYPE_TABLE;
-	else
-		type = STATUSTYPE_INFO;
-
-	outptr = outbuf;
-
-	/* Get all the target info */
-	num_targets = dm_table_get_num_targets(table);
-	for (i = 0; i < num_targets; i++) {
-		struct dm_target *ti = dm_table_get_target(table, i);
-
-		if (outptr - outbuf +
-		    sizeof(struct dm_target_spec) > param->data_size) {
-			dm_table_put(table);
-			return -ENOMEM;
-		}
-
-		spec = (struct dm_target_spec *) outptr;
-
-		spec->status = 0;
-		spec->sector_start = ti->begin;
-		spec->length = ti->len;
-		strlcpy(spec->target_type, ti->type->name,
-			sizeof(spec->target_type));
-
-		outptr += sizeof(struct dm_target_spec);
-
-		/* Get the status/table string from the target driver */
-		if (ti->type->status)
-			ti->type->status(ti, type, outptr,
-					 outbuf + param->data_size - outptr);
-		else
-			outptr[0] = '\0';
-
-		outptr += strlen(outptr) + 1;
-		_align(outptr, ALIGNMENT);
-		spec->next = outptr - outbuf;
-	}
-
-	param->target_count = num_targets;
-	*len = outptr - outbuf;
-	dm_table_put(table);
-
-	return 0;
-}
-
-/*
- * Return the status of a device as a text string for each
- * target.
- */
-static int get_status(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	struct mapped_device *md;
-	size_t len = 0;
-	int ret;
-	char *outbuf = NULL;
-
-	md = find_device(param);
-	if (!md)
-		/*
-		 * Device not found - returns cleared exists flag.
-		 */
-		goto out;
-
-	/* We haven't a clue how long the resultant data will be so
-	   just allocate as much as userland has allowed us and make sure
-	   we don't overun it */
-	outbuf = kmalloc(param->data_size, GFP_KERNEL);
-	if (!outbuf)
-		goto out;
-	/*
-	 * Get the status of all targets
-	 */
-	__status(md, param, outbuf, &len);
-
-	/*
-	 * Setup the basic dm_ioctl structure.
-	 */
-	__info(md, param);
-
-      out:
-	if (md)
-		dm_put(md);
-
-	ret = results_to_user(user, param, outbuf, len);
-
-	if (outbuf)
-		kfree(outbuf);
-
-	return ret;
-}
-
-/*
- * Wait for a device to report an event
- */
-static int wait_device_event(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	struct mapped_device *md;
-	struct dm_table *table;
-	DECLARE_WAITQUEUE(wq, current);
-
-	md = find_device(param);
-	if (!md)
-		/*
-		 * Device not found - returns cleared exists flag.
-		 */
-		goto out;
-
-	/*
-	 * Setup the basic dm_ioctl structure.
-	 */
-	__info(md, param);
-
-	/*
-	 * Wait for a notification event
-	 */
-	set_current_state(TASK_INTERRUPTIBLE);
-	table = dm_get_table(md);
-	dm_table_add_wait_queue(table, &wq);
-	dm_table_put(table);
-	dm_put(md);
-
-	schedule();
-
-      out:
-	return results_to_user(user, param, NULL, 0);
-}
-
-/*
- * Retrieves a list of devices used by a particular dm device.
- */
-static int dep(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	int r;
-	unsigned int count;
-	struct mapped_device *md;
-	struct list_head *tmp;
-	size_t len = 0;
-	struct dm_target_deps *deps = NULL;
-	struct dm_table *table;
-
-	md = find_device(param);
-	if (!md)
-		goto out;
-	table = dm_get_table(md);
-
-	/*
-	 * Setup the basic dm_ioctl structure.
-	 */
-	__info(md, param);
-
-	/*
-	 * Count the devices.
-	 */
-	count = 0;
-	list_for_each(tmp, dm_table_get_devices(table))
-	    count++;
-
-	/*
-	 * Allocate a kernel space version of the dm_target_status
-	 * struct.
-	 */
-	if (array_too_big(sizeof(*deps), sizeof(*deps->dev), count)) {
-		dm_table_put(table);
-		dm_put(md);
-		return -ENOMEM;
-	}
-
-	len = sizeof(*deps) + (sizeof(*deps->dev) * count);
-	deps = kmalloc(len, GFP_KERNEL);
-	if (!deps) {
-		dm_table_put(table);
-		dm_put(md);
-		return -ENOMEM;
-	}
-
-	/*
-	 * Fill in the devices.
-	 */
-	deps->count = count;
-	count = 0;
-	list_for_each(tmp, dm_table_get_devices(table)) {
-		struct dm_dev *dd = list_entry(tmp, struct dm_dev, list);
-		deps->dev[count++] = dd->bdev->bd_dev;
-	}
-	dm_table_put(table);
-	dm_put(md);
-
-      out:
-	r = results_to_user(user, param, deps, len);
-
-	kfree(deps);
-	return r;
-}
-
-static int remove(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	struct hash_cell *hc;
-
-	down_write(&_hash_lock);
-	hc = *param->uuid ? __get_uuid_cell(param->uuid) :
-		__get_name_cell(param->name);
-	if (!hc) {
-		DMWARN("device doesn't appear to be in the dev hash table.");
-		up_write(&_hash_lock);
-		return -EINVAL;
-	}
-
-	/*
-	 * You may ask the interface to drop its reference to an
-	 * in use device.  This is no different to unlinking a
-	 * file that someone still has open.  The device will not
-	 * actually be destroyed until the last opener closes it.
-	 * The name and uuid of the device (both are interface
-	 * properties) will be available for reuse immediately.
-	 *
-	 * You don't want to drop a _suspended_ device from the
-	 * interface, since that will leave you with no way of
-	 * resuming it.
-	 */
-	if (dm_suspended(hc->md)) {
-		DMWARN("refusing to remove a suspended device.");
-		up_write(&_hash_lock);
-		return -EPERM;
-	}
-
-	__hash_remove(hc);
-	up_write(&_hash_lock);
-	return 0;
-}
-
-static int remove_all(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	dm_hash_remove_all();
-	return 0;
-}
-
-static int suspend(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	int r;
-	struct mapped_device *md;
-
-	md = find_device(param);
-	if (!md)
-		return -ENXIO;
-
-	if (param->flags & DM_SUSPEND_FLAG)
-		r = dm_suspend(md);
-	else
-		r = dm_resume(md);
-
-	dm_put(md);
-	return r;
-}
-
-static int reload(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	int r;
-	struct mapped_device *md;
-	struct dm_table *t;
-
-	r = dm_table_create(&t, get_mode(param));
-	if (r)
-		return r;
-
-	r = populate_table(t, param);
-	if (r) {
-		dm_table_put(t);
-		return r;
-	}
-
-	md = find_device(param);
-	if (!md) {
-		dm_table_put(t);
-		return -ENXIO;
-	}
-
-	r = dm_swap_table(md, t);
-	if (r) {
-		dm_put(md);
-		dm_table_put(t);
-		return r;
-	}
-	dm_table_put(t);	/* md will have taken its own reference */
-
-	set_disk_ro(dm_disk(md), (param->flags & DM_READONLY_FLAG) ? 1 : 0);
-	dm_put(md);
-
-	r = info(param, user);
-	return r;
-}
-
-static int rename(struct dm_ioctl *param, struct dm_ioctl *user)
-{
-	int r;
-	char *new_name = (char *) param + param->data_start;
-
-	if (valid_str(new_name, (void *) param,
-		      (void *) param + param->data_size)) {
-		DMWARN("Invalid new logical volume name supplied.");
-		return -EINVAL;
-	}
-
-	r = check_name(new_name);
-	if (r)
-		return r;
-
-	return dm_hash_rename(param->name, new_name);
-}
-
-
-/*-----------------------------------------------------------------
- * Implementation of open/close/ioctl on the special char
- * device.
- *---------------------------------------------------------------*/
-static ioctl_fn lookup_ioctl(unsigned int cmd)
-{
-	static struct {
-		int cmd;
-		ioctl_fn fn;
-	} _ioctls[] = {
-		{DM_VERSION_CMD, NULL},	/* version is dealt with elsewhere */
-		{DM_REMOVE_ALL_CMD, remove_all},
-		{DM_DEV_CREATE_CMD, create},
-		{DM_DEV_REMOVE_CMD, remove},
-		{DM_DEV_RELOAD_CMD, reload},
-		{DM_DEV_RENAME_CMD, rename},
-		{DM_DEV_SUSPEND_CMD, suspend},
-		{DM_DEV_DEPS_CMD, dep},
-		{DM_DEV_STATUS_CMD, info},
-		{DM_TARGET_STATUS_CMD, get_status},
-		{DM_TARGET_WAIT_CMD, wait_device_event},
-	};
-
-	return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn;
-}
-
-/*
- * As well as checking the version compatibility this always
- * copies the kernel interface version out.
- */
-static int check_version(unsigned int cmd, struct dm_ioctl *user)
-{
-	uint32_t version[3];
-	int r = 0;
-
-	if (copy_from_user(version, user->version, sizeof(version)))
-		return -EFAULT;
-
-	if ((DM_VERSION_MAJOR != version[0]) ||
-	    (DM_VERSION_MINOR < version[1])) {
-		DMWARN("ioctl interface mismatch: "
-		       "kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)",
-		       DM_VERSION_MAJOR, DM_VERSION_MINOR,
-		       DM_VERSION_PATCHLEVEL,
-		       version[0], version[1], version[2], cmd);
-		r = -EINVAL;
-	}
-
-	/*
-	 * Fill in the kernel version.
-	 */
-	version[0] = DM_VERSION_MAJOR;
-	version[1] = DM_VERSION_MINOR;
-	version[2] = DM_VERSION_PATCHLEVEL;
-	if (copy_to_user(user->version, version, sizeof(version)))
-		return -EFAULT;
-
-	return r;
-}
-
-static void free_params(struct dm_ioctl *param)
-{
-	vfree(param);
-}
-
-static int copy_params(struct dm_ioctl *user, struct dm_ioctl **param)
-{
-	struct dm_ioctl tmp, *dmi;
-
-	if (copy_from_user(&tmp, user, sizeof(tmp)))
-		return -EFAULT;
-
-	if (tmp.data_size < sizeof(tmp))
-		return -EINVAL;
-
-	dmi = (struct dm_ioctl *) vmalloc(tmp.data_size);
-	if (!dmi)
-		return -ENOMEM;
-
-	if (copy_from_user(dmi, user, tmp.data_size)) {
-		vfree(dmi);
-		return -EFAULT;
-	}
-
-	*param = dmi;
-	return 0;
-}
-
-static int validate_params(uint cmd, struct dm_ioctl *param)
-{
-	/* Ignores parameters */
-	if (cmd == DM_REMOVE_ALL_CMD)
-		return 0;
-
-	/* Unless creating, either name of uuid but not both */
-	if (cmd != DM_DEV_CREATE_CMD) {
-		if ((!*param->uuid && !*param->name) ||
-		    (*param->uuid && *param->name)) {
-			DMWARN("one of name or uuid must be supplied");
-			return -EINVAL;
-		}
-	}
-
-	/* Ensure strings are terminated */
-	param->name[DM_NAME_LEN - 1] = '\0';
-	param->uuid[DM_UUID_LEN - 1] = '\0';
-
-	return 0;
-}
-
-static int ctl_ioctl(struct inode *inode, struct file *file,
-		     uint command, ulong u)
-{
-	int r = 0;
-	unsigned int cmd;
-	struct dm_ioctl *param;
-	struct dm_ioctl *user = (struct dm_ioctl *) u;
-	ioctl_fn fn = NULL;
-
-	/* only root can play with this */
-	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
-
-	if (_IOC_TYPE(command) != DM_IOCTL)
-		return -ENOTTY;
-
-	cmd = _IOC_NR(command);
-
-	/*
-	 * Check the interface version passed in.  This also
-	 * writes out the kernels interface version.
-	 */
-	r = check_version(cmd, user);
-	if (r)
-		return r;
-
-	/*
-	 * Nothing more to do for the version command.
-	 */
-	if (cmd == DM_VERSION_CMD)
-		return 0;
-
-	fn = lookup_ioctl(cmd);
-	if (!fn) {
-		DMWARN("dm_ctl_ioctl: unknown command 0x%x", command);
-		return -ENOTTY;
-	}
-
-	/*
-	 * Copy the parameters into kernel space.
-	 */
-	r = copy_params(user, &param);
-	if (r)
-		return r;
-
-	r = validate_params(cmd, param);
-	if (r) {
-		free_params(param);
-		return r;
-	}
-
-	r = fn(param, user);
-	free_params(param);
-	return r;
-}
-
-static struct file_operations _ctl_fops = {
-	.ioctl	 = ctl_ioctl,
-	.owner	 = THIS_MODULE,
-};
-
-static struct miscdevice _dm_misc = {
-	.minor		= MISC_DYNAMIC_MINOR,
-	.name		= DM_NAME,
-	.devfs_name	= "mapper/control",
-	.fops		= &_ctl_fops
-};
-
-/*
- * Create misc character device and link to DM_DIR/control.
- */
-int __init dm_interface_init(void)
-{
-	int r;
-
-	r = dm_hash_init();
-	if (r)
-		return r;
-
-	r = misc_register(&_dm_misc);
-	if (r) {
-		DMERR("misc_register failed for control device");
-		dm_hash_exit();
-		return r;
-	}
-
-	DMINFO("%d.%d.%d%s initialised: %s", DM_VERSION_MAJOR,
-	       DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, DM_VERSION_EXTRA,
-	       DM_DRIVER_EMAIL);
-	return 0;
-
-	if (misc_deregister(&_dm_misc) < 0)
-		DMERR("misc_deregister failed for control device");
-	dm_hash_exit();
-	return r;
-}
 
-void dm_interface_exit(void)
-{
-	if (misc_deregister(&_dm_misc) < 0)
-		DMERR("misc_deregister failed for control device");
-	dm_hash_exit();
-}
+#ifdef CONFIG_DM_IOCTL_V4
+#include "dm-ioctl-v4.c"
+#else
+#include "dm-ioctl-v1.c"
+#endif
diff -Nru a/drivers/md/dm-table.c b/drivers/md/dm-table.c
--- a/drivers/md/dm-table.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/md/dm-table.c	Sat Jul 19 12:54:30 2003
@@ -48,11 +48,9 @@
 	 */
 	struct io_restrictions limits;
 
-	/*
-	 * A waitqueue for processes waiting for something
-	 * interesting to happen to this table.
-	 */
-	wait_queue_head_t eventq;
+	/* events get handed up using this callback */
+	void (*event_fn)(void *);
+	void *event_context;
 };
 
 /*
@@ -222,7 +220,6 @@
 		return -ENOMEM;
 	}
 
-	init_waitqueue_head(&t->eventq);
 	t->mode = mode;
 	*result = t;
 	return 0;
@@ -243,9 +240,6 @@
 {
 	unsigned int i;
 
-	/* destroying the table counts as an event */
-	dm_table_event(t);
-
 	/* free the indexes (see dm_table_complete) */
 	if (t->depth >= 2)
 		vfree(t->index[t->depth - 2]);
@@ -694,9 +688,22 @@
 	return r;
 }
 
+static spinlock_t _event_lock = SPIN_LOCK_UNLOCKED;
+void dm_table_event_callback(struct dm_table *t,
+			     void (*fn)(void *), void *context)
+{
+	spin_lock_irq(&_event_lock);
+	t->event_fn = fn;
+	t->event_context = context;
+	spin_unlock_irq(&_event_lock);
+}
+
 void dm_table_event(struct dm_table *t)
 {
-	wake_up_interruptible(&t->eventq);
+	spin_lock(&_event_lock);
+	if (t->event_fn)
+		t->event_fn(t->event_context);
+	spin_unlock(&_event_lock);
 }
 
 sector_t dm_table_get_size(struct dm_table *t)
@@ -759,11 +766,6 @@
 int dm_table_get_mode(struct dm_table *t)
 {
 	return t->mode;
-}
-
-void dm_table_add_wait_queue(struct dm_table *t, wait_queue_t *wq)
-{
-	add_wait_queue(&t->eventq, wq);
 }
 
 void dm_table_suspend_targets(struct dm_table *t)
diff -Nru a/drivers/md/dm.c b/drivers/md/dm.c
--- a/drivers/md/dm.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/md/dm.c	Sat Jul 19 12:54:26 2003
@@ -8,7 +8,6 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/blk.h>
 #include <linux/blkpg.h>
 #include <linux/bio.h>
 #include <linux/mempool.h>
@@ -63,6 +62,12 @@
 	 * io objects are allocated from here.
 	 */
 	mempool_t *io_pool;
+
+	/*
+	 * Event handling.
+	 */
+	uint32_t event_nr;
+	wait_queue_head_t eventq;
 };
 
 #define MIN_IOS 256
@@ -510,6 +515,11 @@
 		down_read(&md->lock);
 	}
 
+	if (!md->map) {
+		bio_io_error(bio, bio->bi_size);
+		return 0;
+	}
+
 	__split_bio(md, bio);
 	up_read(&md->lock);
 	return 0;
@@ -619,6 +629,8 @@
 
 	atomic_set(&md->pending, 0);
 	init_waitqueue_head(&md->wait);
+	init_waitqueue_head(&md->eventq);
+
 	return md;
 }
 
@@ -634,6 +646,16 @@
 /*
  * Bind a table to the device.
  */
+static void event_callback(void *context)
+{
+	struct mapped_device *md = (struct mapped_device *) context;
+
+	down_write(&md->lock);
+	md->event_nr++;
+	wake_up_interruptible(&md->eventq);
+	up_write(&md->lock);
+}
+
 static int __bind(struct mapped_device *md, struct dm_table *t)
 {
 	request_queue_t *q = &md->queue;
@@ -645,6 +667,8 @@
 	if (size == 0)
 		return 0;
 
+	dm_table_event_callback(md->map, event_callback, md);
+
 	dm_table_get(t);
 	dm_table_set_restrictions(t, q);
 	return 0;
@@ -652,6 +676,10 @@
 
 static void __unbind(struct mapped_device *md)
 {
+	if (!md->map)
+		return;
+
+	dm_table_event_callback(md->map, NULL, NULL);
 	dm_table_put(md->map);
 	md->map = NULL;
 	set_capacity(md->disk, 0);
@@ -661,35 +689,26 @@
  * Constructor for a new device.
  */
 static int create_aux(unsigned int minor, int persistent,
-		      struct dm_table *table, struct mapped_device **result)
+		      struct mapped_device **result)
 {
-	int r;
 	struct mapped_device *md;
 
 	md = alloc_dev(minor, persistent);
 	if (!md)
 		return -ENXIO;
 
-	r = __bind(md, table);
-	if (r) {
-		free_dev(md);
-		return r;
-	}
-	dm_table_resume_targets(md->map);
-
 	*result = md;
 	return 0;
 }
 
-int dm_create(struct dm_table *table, struct mapped_device **result)
+int dm_create(struct mapped_device **result)
 {
-	return create_aux(0, 0, table, result);
+	return create_aux(0, 0, result);
 }
 
-int dm_create_with_minor(unsigned int minor,
-			 struct dm_table *table, struct mapped_device **result)
+int dm_create_with_minor(unsigned int minor, struct mapped_device **result)
 {
-	return create_aux(minor, 1, table, result);
+	return create_aux(minor, 1, result);
 }
 
 void dm_get(struct mapped_device *md)
@@ -700,7 +719,7 @@
 void dm_put(struct mapped_device *md)
 {
 	if (atomic_dec_and_test(&md->holders)) {
-		if (!test_bit(DMF_SUSPENDED, &md->flags))
+		if (!test_bit(DMF_SUSPENDED, &md->flags) && md->map)
 			dm_table_suspend_targets(md->map);
 		__unbind(md);
 		free_dev(md);
@@ -790,7 +809,8 @@
 	down_write(&md->lock);
 	remove_wait_queue(&md->wait, &wait);
 	set_bit(DMF_SUSPENDED, &md->flags);
-	dm_table_suspend_targets(md->map);
+	if (md->map)
+		dm_table_suspend_targets(md->map);
 	up_write(&md->lock);
 
 	return 0;
@@ -801,7 +821,8 @@
 	struct deferred_io *def;
 
 	down_write(&md->lock);
-	if (!test_bit(DMF_SUSPENDED, &md->flags) ||
+	if (!md->map ||
+	    !test_bit(DMF_SUSPENDED, &md->flags) ||
 	    !dm_table_get_size(md->map)) {
 		up_write(&md->lock);
 		return -EINVAL;
@@ -820,6 +841,42 @@
 	return 0;
 }
 
+/*-----------------------------------------------------------------
+ * Event notification.
+ *---------------------------------------------------------------*/
+uint32_t dm_get_event_nr(struct mapped_device *md)
+{
+	uint32_t r;
+
+	down_read(&md->lock);
+	r = md->event_nr;
+	up_read(&md->lock);
+
+	return r;
+}
+
+int dm_add_wait_queue(struct mapped_device *md, wait_queue_t *wq,
+		      uint32_t event_nr)
+{
+	down_write(&md->lock);
+	if (event_nr != md->event_nr) {
+		up_write(&md->lock);
+		return 1;
+	}
+
+	add_wait_queue(&md->eventq, wq);
+	up_write(&md->lock);
+
+	return 0;
+}
+
+void dm_remove_wait_queue(struct mapped_device *md, wait_queue_t *wq)
+{
+	down_write(&md->lock);
+	remove_wait_queue(&md->eventq, wq);
+	up_write(&md->lock);
+}
+
 /*
  * The gendisk is only valid as long as you have a reference
  * count on 'md'.
@@ -835,7 +892,8 @@
 
 	down_read(&md->lock);
 	t = md->map;
-	dm_table_get(t);
+	if (t)
+		dm_table_get(t);
 	up_read(&md->lock);
 
 	return t;
diff -Nru a/drivers/md/dm.h b/drivers/md/dm.h
--- a/drivers/md/dm.h	Sat Jul 19 12:54:25 2003
+++ b/drivers/md/dm.h	Sat Jul 19 12:54:25 2003
@@ -51,9 +51,8 @@
  * Functions for manipulating a struct mapped_device.
  * Drop the reference with dm_put when you finish with the object.
  *---------------------------------------------------------------*/
-int dm_create(struct dm_table *table, struct mapped_device **md);
-int dm_create_with_minor(unsigned int minor, struct dm_table *table,
-			 struct mapped_device **md);
+int dm_create(struct mapped_device **md);
+int dm_create_with_minor(unsigned int minor, struct mapped_device **md);
 
 /*
  * Reference counting for md.
@@ -79,6 +78,14 @@
 struct dm_table *dm_get_table(struct mapped_device *md);
 
 /*
+ * Event functions.
+ */
+uint32_t dm_get_event_nr(struct mapped_device *md);
+int dm_add_wait_queue(struct mapped_device *md, wait_queue_t *wq,
+		      uint32_t event_nr);
+void dm_remove_wait_queue(struct mapped_device *md, wait_queue_t *wq);
+
+/*
  * Info functions.
  */
 struct gendisk *dm_disk(struct mapped_device *md);
@@ -96,6 +103,8 @@
 int dm_table_add_target(struct dm_table *t, const char *type,
 			sector_t start,	sector_t len, char *params);
 int dm_table_complete(struct dm_table *t);
+void dm_table_event_callback(struct dm_table *t,
+			     void (*fn)(void *), void *context);
 void dm_table_event(struct dm_table *t);
 sector_t dm_table_get_size(struct dm_table *t);
 struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index);
@@ -104,7 +113,6 @@
 unsigned int dm_table_get_num_targets(struct dm_table *t);
 struct list_head *dm_table_get_devices(struct dm_table *t);
 int dm_table_get_mode(struct dm_table *t);
-void dm_table_add_wait_queue(struct dm_table *t, wait_queue_t *wq);
 void dm_table_suspend_targets(struct dm_table *t);
 void dm_table_resume_targets(struct dm_table *t);
 
diff -Nru a/drivers/md/md.c b/drivers/md/md.c
--- a/drivers/md/md.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/md/md.c	Sat Jul 19 12:54:24 2003
@@ -52,8 +52,6 @@
 #define MD_DRIVER
 #define DEVICE_NR(device) (minor(device))
 
-#include <linux/blk.h>
-
 #define DEBUG 0
 #define dprintk(x...) ((void)(DEBUG && printk(x)))
 
diff -Nru a/drivers/media/common/Makefile b/drivers/media/common/Makefile
--- a/drivers/media/common/Makefile	Sat Jul 19 12:54:27 2003
+++ b/drivers/media/common/Makefile	Sat Jul 19 12:54:27 2003
@@ -1,5 +1,5 @@
 saa7146-objs    := saa7146_i2c.o saa7146_core.o 
-saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o  
+saa7146_vv-objs := saa7146_vv_ksyms.o saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o  
 
 obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o saa7146_vv.o
 
diff -Nru a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
--- a/drivers/media/common/saa7146_core.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/media/common/saa7146_core.c	Sat Jul 19 12:54:26 2003
@@ -373,6 +373,9 @@
 	dev->module = THIS_MODULE;
 	init_waitqueue_head(&dev->i2c_wq);
 
+	/* set some default values */
+	saa7146_write(dev, BCS_CTRL, 0x80400040);
+
 	if( 0 != ext->probe) {
 		if( 0 != ext->probe(dev) ) {
 			DEB_D(("ext->probe() failed for %p. skipping device.\n",dev));
@@ -390,9 +393,6 @@
 	INIT_LIST_HEAD(&dev->item);
 	list_add_tail(&dev->item,&saa7146_devices);
 	saa7146_num++;
-
-	/* set some default values */
-	saa7146_write(dev, BCS_CTRL, 0x80400040);
 
 	err = 0;
 	goto out;
diff -Nru a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
--- a/drivers/media/common/saa7146_fops.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/media/common/saa7146_fops.c	Sat Jul 19 12:54:25 2003
@@ -106,10 +106,21 @@
 			// fixme: fix this for vflip != 0
 
 			saa7146_write(dev, PROT_ADDR1, 0);
+			saa7146_write(dev, MC2, (MASK_02|MASK_18));		
+
 			/* write the address of the rps-program */
 			saa7146_write(dev, RPS_ADDR0, dev->d_rps0.dma_handle);
 			/* turn on rps */
 			saa7146_write(dev, MC1, (MASK_12 | MASK_28));
+				
+/*
+			printk("vdma%d.base_even:     0x%08x\n", 1,saa7146_read(dev,BASE_EVEN1));
+			printk("vdma%d.base_odd:      0x%08x\n", 1,saa7146_read(dev,BASE_ODD1));
+			printk("vdma%d.prot_addr:     0x%08x\n", 1,saa7146_read(dev,PROT_ADDR1));
+			printk("vdma%d.base_page:     0x%08x\n", 1,saa7146_read(dev,BASE_PAGE1));
+			printk("vdma%d.pitch:         0x%08x\n", 1,saa7146_read(dev,PITCH1));
+			printk("vdma%d.num_line_byte: 0x%08x\n", 1,saa7146_read(dev,NUM_LINE_BYTE1));
+*/
 		}
 		del_timer(&q->timeout);
 	}
@@ -374,7 +385,7 @@
 	.minor		= -1,
 };
 
-int saa7146_vv_init(struct saa7146_dev* dev)
+int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
 {
 	struct saa7146_vv *vv = kmalloc (sizeof(struct saa7146_vv),GFP_KERNEL);
 	if( NULL == vv ) {
@@ -385,6 +396,11 @@
 
 	DEB_EE(("dev:%p\n",dev));
 	
+	/* save per-device extension data (one extension can
+	   handle different devices that might need different
+	   configuration data) */
+	dev->ext_vv_data = ext_vv;
+	
 	vv->video_minor = -1;
 	vv->vbi_minor = -1;
 
@@ -474,13 +490,6 @@
 
 module_init(saa7146_vv_init_module);
 module_exit(saa7146_vv_cleanup_module);
-
-EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync);
-EXPORT_SYMBOL_GPL(saa7146_register_device);
-EXPORT_SYMBOL_GPL(saa7146_unregister_device);
-
-EXPORT_SYMBOL_GPL(saa7146_vv_init);
-EXPORT_SYMBOL_GPL(saa7146_vv_release);
 
 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
 MODULE_DESCRIPTION("video4linux driver for saa7146-based hardware");
diff -Nru a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c
--- a/drivers/media/common/saa7146_hlp.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/media/common/saa7146_hlp.c	Sat Jul 19 12:54:25 2003
@@ -242,7 +242,9 @@
 		if( 2*out_y >= in_y) {
 			lpi = 1;
 		}
-	} else if (field == V4L2_FIELD_TOP || field == V4L2_FIELD_BOTTOM) {
+	} else if (field == V4L2_FIELD_TOP
+		|| field == V4L2_FIELD_ALTERNATE
+		|| field == V4L2_FIELD_BOTTOM) {
 		if( 4*out_y >= in_y ) {
 			lpi = 1;
 		}
@@ -468,9 +470,7 @@
 	*clip_format &= 0xfffffff7;
 	if (V4L2_FIELD_HAS_BOTH(field)) {
 		*clip_format |= 0x00000008;
-	} else if (field == V4L2_FIELD_TOP) {
-		*clip_format |= 0x00000000;
-	} else if (field == V4L2_FIELD_BOTTOM) {
+	} else {
 		*clip_format |= 0x00000000;
 	}
 }
@@ -593,6 +593,10 @@
 	}
 	
 	if (V4L2_FIELD_HAS_BOTH(field)) {
+	} else if (field == V4L2_FIELD_ALTERNATE) {
+		/* fixme */
+		vdma1.base_odd = vdma1.prot_addr;
+		vdma1.pitch /= 2;
 	} else if (field == V4L2_FIELD_TOP) {
 		vdma1.base_odd = vdma1.prot_addr;
 		vdma1.pitch /= 2;
@@ -706,7 +710,7 @@
 	/* calculate starting address */
 	where  = (which-1)*0x18;
 
-	if( 0 != (dev->ext->ext_vv_data->flags & SAA7146_EXT_SWAP_ODD_EVEN)) {
+	if( 0 != (dev->ext_vv_data->flags & SAA7146_EXT_SWAP_ODD_EVEN)) {
 		saa7146_write(dev, where, 	vdma->base_even);
 		saa7146_write(dev, where+0x04, 	vdma->base_odd);
 	} else {
@@ -760,6 +764,16 @@
 	}
 
 	if (V4L2_FIELD_HAS_BOTH(field)) {
+	} else if (field == V4L2_FIELD_ALTERNATE) {
+		/* fixme */
+		if ( vv->last_field == V4L2_FIELD_TOP ) {
+			vdma1.base_odd	= vdma1.prot_addr;
+			vdma1.pitch /= 2;
+		} else if ( vv->last_field == V4L2_FIELD_BOTTOM ) {
+			vdma1.base_odd	= vdma1.base_even;
+			vdma1.base_even = vdma1.prot_addr;
+			vdma1.pitch /= 2;
+		}
 	} else if (field == V4L2_FIELD_TOP) {
 		vdma1.base_odd	= vdma1.prot_addr;
 		vdma1.pitch /= 2;
@@ -896,6 +910,14 @@
 	}
 
 	if (V4L2_FIELD_HAS_BOTH(field)) {
+	} else if (field == V4L2_FIELD_ALTERNATE) {
+		/* fixme */
+		vdma1.base_odd	= vdma1.prot_addr;
+		vdma1.pitch /= 2;
+		vdma2.base_odd	= vdma2.prot_addr;
+		vdma2.pitch /= 2;
+		vdma3.base_odd	= vdma3.prot_addr;
+		vdma3.pitch /= 2;
 	} else if (field == V4L2_FIELD_TOP) {
 		vdma1.base_odd	= vdma1.prot_addr;
 		vdma1.pitch /= 2;
@@ -935,21 +957,22 @@
 static void program_capture_engine(struct saa7146_dev *dev, int planar)
 {
 	struct saa7146_vv *vv = dev->vv_data;
+	int count = 0;
 
 	unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B;
 	unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B;
 
-	if( 0 != (dev->ext->ext_vv_data->flags & SAA7146_EXT_SWAP_ODD_EVEN)) {
+	if( 0 != (dev->ext_vv_data->flags & SAA7146_EXT_SWAP_ODD_EVEN)) {
 		unsigned long tmp = e_wait;
 		e_wait = o_wait;
 		o_wait = tmp;
 	}
 
-	/* wait for o_fid_a/b / e_fid_a/b toggle only if bit 0 is not set*/
-	WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | e_wait);
+	/* wait for o_fid_a/b / e_fid_a/b toggle only if rps register 0 is not set*/
 	WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | o_wait);
+	WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | e_wait);
 
-	/* set bit 0 */
+	/* set rps register 0 */
 	WRITE_RPS0(CMD_WR_REG | (1 << 8) | (MC2/4)); 	
 	WRITE_RPS0(MASK_27 | MASK_11);
 	
@@ -970,8 +993,14 @@
 	}
 	
 	/* wait for o_fid_a/b / e_fid_a/b toggle */
+	if ( vv->last_field == V4L2_FIELD_INTERLACED ) {
+		WRITE_RPS0(CMD_PAUSE | o_wait);
 	WRITE_RPS0(CMD_PAUSE | e_wait);
+	} else if ( vv->last_field == V4L2_FIELD_TOP ) {
 	WRITE_RPS0(CMD_PAUSE | o_wait);
+	} else if ( vv->last_field == V4L2_FIELD_BOTTOM ) {
+		WRITE_RPS0(CMD_PAUSE | e_wait);
+	}
 
 	/* turn off video-dma1 */
 	WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
@@ -999,12 +1028,38 @@
 void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
 {
 	struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+	struct saa7146_vv *vv = dev->vv_data;
+	u32 vdma1_prot_addr;
 
 	DEB_CAP(("buf:%p, next:%p\n",buf,next));
 
+/*
+	printk("vdma%d.base_even:     0x%08x\n", 1,saa7146_read(dev,BASE_EVEN1));
+	printk("vdma%d.base_odd:      0x%08x\n", 1,saa7146_read(dev,BASE_ODD1));
+	printk("vdma%d.prot_addr:     0x%08x\n", 1,saa7146_read(dev,PROT_ADDR1));
+	printk("vdma%d.base_page:     0x%08x\n", 1,saa7146_read(dev,BASE_PAGE1));
+	printk("vdma%d.pitch:         0x%08x\n", 1,saa7146_read(dev,PITCH1));
+	printk("vdma%d.num_line_byte: 0x%08x\n", 1,saa7146_read(dev,NUM_LINE_BYTE1));
+	printk("vdma%d => vptr      : 0x%08x\n", 1,saa7146_read(dev,PCI_VDP1));
+*/
+
+	vdma1_prot_addr = saa7146_read(dev, PROT_ADDR1);
+	if( 0 == vdma1_prot_addr ) {
+		/* clear out beginning of streaming bit (rps register 0)*/
+		DEB_CAP(("forcing sync to new frame\n"));
+		saa7146_write(dev, MC2, MASK_27 );
+	}
+
 	saa7146_set_window(dev, buf->fmt->width, buf->fmt->height, buf->fmt->field);
 	saa7146_set_output_format(dev, sfmt->trans);
 	saa7146_disable_clipping(dev);
+
+	if ( vv->last_field == V4L2_FIELD_INTERLACED ) {
+	} else if ( vv->last_field == V4L2_FIELD_TOP ) {
+		vv->last_field = V4L2_FIELD_BOTTOM;
+	} else if ( vv->last_field == V4L2_FIELD_BOTTOM ) {
+		vv->last_field = V4L2_FIELD_TOP;
+	}
 
 	if( 0 != IS_PLANAR(sfmt->trans)) {
 		calculate_video_dma_grab_planar(dev, buf);
diff -Nru a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
--- a/drivers/media/common/saa7146_i2c.c	Sat Jul 19 12:54:29 2003
+++ b/drivers/media/common/saa7146_i2c.c	Sat Jul 19 12:54:29 2003
@@ -181,9 +181,10 @@
 /* this functions writes out the data-byte 'dword' to the i2c-device.
    it returns 0 if ok, -1 if the transfer failed, -2 if the transfer
    failed badly (e.g. address error) */
-static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword)
+static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_delay)
 {
 	u32 status = 0, mc2 = 0;
+	int trial = 0;
 	int timeout;
 
 	/* write out i2c-command */
@@ -224,10 +225,13 @@
 		/* wait until we get a transfer done or error */
 		timeout = jiffies + HZ/100 + 1; /* 10ms */
 		while(1) {
+			/**
+			 *  first read usually delivers bogus results...
+			 */
+			saa7146_i2c_status(dev);
 			status = saa7146_i2c_status(dev);
-			if( (0x3 == (status & 0x3)) || (0 == (status & 0x1)) ) {
+			if ((status & 0x3) != 1)
 				break;
-			}
 			if (jiffies > timeout) {
 				/* this is normal when probing the bus
 				 * (no answer from nonexisistant device...)
@@ -235,6 +239,9 @@
 				DEB_I2C(("saa7146_i2c_writeout: timed out waiting for end of xfer\n"));
 				return -EIO;
 			}
+			if ((++trial < 20) && short_delay)
+				udelay(10);
+			else
 			my_wait(dev,1);
 		}
 	}
@@ -277,6 +284,7 @@
 	u32* buffer = dev->d_i2c.cpu_addr;
 	int err = 0;
         int address_err = 0;
+        int short_delay = 0;
 	
 	if (down_interruptible (&dev->i2c_lock))
 		return -ERESTARTSYS;
@@ -292,6 +300,8 @@
 		goto out;
 	}
 
+        if (count > 3) short_delay = 1;
+  
 	do {
 		/* reset the i2c-device if necessary */
 		err = saa7146_i2c_reset(dev);
@@ -302,7 +312,7 @@
 
 		/* write out the u32s one after another */
 		for(i = 0; i < count; i++) {
-			err = saa7146_i2c_writeout(dev, &buffer[i] );
+			err = saa7146_i2c_writeout(dev, &buffer[i], short_delay);
 			if ( 0 != err) {
 				/* this one is unsatisfying: some i2c slaves on some
 				   dvb cards don't acknowledge correctly, so the saa7146
@@ -357,7 +367,7 @@
 	if( 0 == dev->revision ) {
 		u32 zero = 0;
 		saa7146_i2c_reset(dev);
-		if( 0 != saa7146_i2c_writeout(dev, &zero)) {
+		if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) {
 			INFO(("revision 0 error. this should never happen.\n"));
 		}
 	}
@@ -397,8 +407,13 @@
 
 	if( NULL != i2c_adapter ) {
 		memset(i2c_adapter,0,sizeof(struct i2c_adapter));
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+		strcpy(i2c_adapter->name, dev->name);	
+		i2c_adapter->data = dev;
+#else
 		strcpy(i2c_adapter->dev.name, dev->name);	
 		i2c_set_adapdata(i2c_adapter,dev);
+#endif
 		i2c_adapter->algo	   = &saa7146_algo;
 		i2c_adapter->algo_data     = NULL;
 		i2c_adapter->id 	   = I2C_ALGO_SAA7146;
diff -Nru a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c
--- a/drivers/media/common/saa7146_vbi.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/media/common/saa7146_vbi.c	Sat Jul 19 12:54:21 2003
@@ -9,6 +9,7 @@
         u32          *cpu;
         dma_addr_t   dma_addr;
 	
+	int count = 0;
 	int i;
 
 	DECLARE_WAITQUEUE(wait, current);
@@ -443,5 +444,3 @@
 	.irq_done	= vbi_irq_done,
 	.read 		= vbi_read,
 };
-
-EXPORT_SYMBOL_GPL(saa7146_vbi_uops);
diff -Nru a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
--- a/drivers/media/common/saa7146_video.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/media/common/saa7146_video.c	Sat Jul 19 12:54:26 2003
@@ -137,6 +137,7 @@
         switch (field) {
         case V4L2_FIELD_TOP:
         case V4L2_FIELD_BOTTOM:
+        case V4L2_FIELD_ALTERNATE:
                 maxh = maxh / 2;
                 break;
         case V4L2_FIELD_INTERLACED:
@@ -186,11 +187,18 @@
 				: V4L2_FIELD_BOTTOM;
 		}
 		switch (field) {
+		case V4L2_FIELD_ALTERNATE: {
+			vv->last_field = V4L2_FIELD_TOP;
+			maxh = maxh / 2;
+			break;
+		}
 		case V4L2_FIELD_TOP:
 		case V4L2_FIELD_BOTTOM:
+			vv->last_field = V4L2_FIELD_INTERLACED;
 			maxh = maxh / 2;
 			break;
 		case V4L2_FIELD_INTERLACED:
+			vv->last_field = V4L2_FIELD_INTERLACED;
 			break;
 		default: {
 			DEB_D(("no known field mode '%d'.\n",field));
@@ -220,7 +228,7 @@
 	}
 }
 
-static int start_preview(struct saa7146_fh *fh)
+int saa7146_start_preview(struct saa7146_fh *fh)
 {
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
@@ -266,12 +274,12 @@
 	return 0;
 }
 
-static int stop_preview(struct saa7146_fh *fh)
+int saa7146_stop_preview(struct saa7146_fh *fh)
 {
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
 
-	DEB_EE(("saa7146.o: stop_preview()\n"));
+	DEB_EE(("saa7146.o: saa7146_stop_preview()\n"));
 
 	/* check if overlay is running */
 	if( 0 == vv->ov_data ) {
@@ -333,8 +341,8 @@
 		if( vv->ov_data != NULL ) {
 			if( fh == vv->ov_data->fh) {
 				spin_lock_irqsave(&dev->slock,flags);
-				stop_preview(fh);
-				start_preview(fh);
+				saa7146_stop_preview(fh);
+				saa7146_start_preview(fh);
 				spin_unlock_irqrestore(&dev->slock,flags);
 			}
 		}
@@ -522,8 +530,8 @@
 		if( 0 != vv->ov_data ) {
 			if( fh == vv->ov_data->fh ) {
 				spin_lock_irqsave(&dev->slock,flags);
-				stop_preview(fh);
-				start_preview(fh);
+				saa7146_stop_preview(fh);
+				saa7146_start_preview(fh);
 				spin_unlock_irqrestore(&dev->slock,flags);
 			}
 		}
@@ -561,7 +569,7 @@
 				m3 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;
 				o1 = size%PAGE_SIZE;
 				o2 = (size+(size/4))%PAGE_SIZE;
-				printk("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2);
+				DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2));
 				break;
 			}
 			case 16: {
@@ -571,7 +579,7 @@
 				m3 = ((2*size+PAGE_SIZE)/PAGE_SIZE)-1;
 				o1 = size%PAGE_SIZE;
 				o2 = (size+(size/2))%PAGE_SIZE;
-				printk("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2);
+				DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2));
 				break;
 			}
 			default: {
@@ -674,7 +682,7 @@
 
 	spin_lock_irqsave(&dev->slock,flags);
 
-	/* clear out beginning of streaming bit */
+	/* clear out beginning of streaming bit (rps register 0)*/
 	saa7146_write(dev, MC2, MASK_27 );
 
 	/* enable rps0 irqs */
@@ -740,19 +748,19 @@
 	struct videobuf_queue *q;
 
 	/* check if extension handles the command */
-	for(ee = 0; dev->ext->ext_vv_data->ioctls[ee].flags != 0; ee++) {
-		if( cmd == dev->ext->ext_vv_data->ioctls[ee].cmd )
+	for(ee = 0; dev->ext_vv_data->ioctls[ee].flags != 0; ee++) {
+		if( cmd == dev->ext_vv_data->ioctls[ee].cmd )
 			break;
 	}
 	
-	if( 0 != (dev->ext->ext_vv_data->ioctls[ee].flags & SAA7146_EXCLUSIVE) ) {
+	if( 0 != (dev->ext_vv_data->ioctls[ee].flags & SAA7146_EXCLUSIVE) ) {
 		DEB_D(("extension handles ioctl exclusive.\n"));
-		result = dev->ext->ext_vv_data->ioctl(dev, cmd, arg);
+		result = dev->ext_vv_data->ioctl(fh, cmd, arg);
 		return result;
 	}
-	if( 0 != (dev->ext->ext_vv_data->ioctls[ee].flags & SAA7146_BEFORE) ) {
+	if( 0 != (dev->ext_vv_data->ioctls[ee].flags & SAA7146_BEFORE) ) {
 		DEB_D(("extension handles ioctl before.\n"));
-		result = dev->ext->ext_vv_data->ioctl(dev, cmd, arg);
+		result = dev->ext_vv_data->ioctl(fh, cmd, arg);
 		if( -EAGAIN != result ) {
 			return result;
 		}
@@ -793,7 +801,7 @@
 			V4L2_CAP_VIDEO_OVERLAY |
 			V4L2_CAP_READWRITE | 
 			V4L2_CAP_STREAMING;
-		cap->capabilities |= dev->ext->ext_vv_data->capabilities;
+		cap->capabilities |= dev->ext_vv_data->capabilities;
 		return 0;
 	}
 	case VIDIOC_G_FBUF:
@@ -942,9 +950,10 @@
 		struct v4l2_standard *e = arg;
 		if (e->index < 0 )
 			return -EINVAL;
-		if( e->index < dev->ext->ext_vv_data->num_stds ) {
+		if( e->index < dev->ext_vv_data->num_stds ) {
 			DEB_EE(("VIDIOC_ENUMSTD: index:%d\n",e->index));
-			return v4l2_video_std_construct(e, dev->ext->ext_vv_data->stds[e->index].id, dev->ext->ext_vv_data->stds[e->index].name);
+			v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name);
+			return 0;
 		}
 		return -EINVAL;
 	}
@@ -968,22 +977,22 @@
 
 		if( vv->ov_data != NULL ) {
 			ov_fh = vv->ov_data->fh;
-			stop_preview(ov_fh);
+			saa7146_stop_preview(ov_fh);
 			restart_overlay = 1;
 		}
 
-		for(i = 0; i < dev->ext->ext_vv_data->num_stds; i++)
-			if (*id & dev->ext->ext_vv_data->stds[i].id)
+		for(i = 0; i < dev->ext_vv_data->num_stds; i++)
+			if (*id & dev->ext_vv_data->stds[i].id)
 				break;
-		if (i != dev->ext->ext_vv_data->num_stds) {
-			vv->standard = &dev->ext->ext_vv_data->stds[i];
-			if( NULL != dev->ext->ext_vv_data->std_callback )
-				dev->ext->ext_vv_data->std_callback(dev, vv->standard);
+		if (i != dev->ext_vv_data->num_stds) {
+			vv->standard = &dev->ext_vv_data->stds[i];
+			if( NULL != dev->ext_vv_data->std_callback )
+				dev->ext_vv_data->std_callback(dev, vv->standard);
 			found = 1;
 		}
 
 		if( 0 != restart_overlay ) {
-			start_preview(ov_fh);
+			saa7146_start_preview(ov_fh);
 		}
 		up(&dev->lock);
 
@@ -1000,7 +1009,7 @@
 		int on = *(int *)arg;
 		int err = 0;
 
-		if( NULL == vv->ov_fmt ) {
+		if( NULL == vv->ov_fmt && on != 0 ) {
 			DEB_D(("VIDIOC_OVERLAY: no framebuffer informations. call S_FBUF first!\n"));
 			return -EAGAIN;
 		}
@@ -1013,7 +1022,7 @@
 				}
 			}
 			spin_lock_irqsave(&dev->slock,flags);
-			err = start_preview(fh);
+			err = saa7146_start_preview(fh);
 			spin_unlock_irqrestore(&dev->slock,flags);
 		} else {
 			if( vv->ov_data != NULL ) {
@@ -1022,7 +1031,7 @@
 				}
 			}
 			spin_lock_irqsave(&dev->slock,flags);
-			err = stop_preview(fh);
+			err = saa7146_stop_preview(fh);
 			spin_unlock_irqrestore(&dev->slock,flags);
 		}
 		return err;
@@ -1036,12 +1045,18 @@
 		return videobuf_querybuf(q,arg);
 	}
 	case VIDIOC_QBUF: {
-		DEB_D(("VIDIOC_QBUF \n"));
-		return videobuf_qbuf(file,q,arg);
+		struct v4l2_buffer *b = arg;
+		int ret = 0;
+		ret = videobuf_qbuf(file,q,b);
+		DEB_D(("VIDIOC_QBUF: ret:%d, index:%d\n",ret,b->index));
+		return ret;
 	}
 	case VIDIOC_DQBUF: {
-		DEB_D(("VIDIOC_DQBUF \n"));
-		return videobuf_dqbuf(file,q,arg);
+		struct v4l2_buffer *b = arg;
+		int ret = 0;
+		ret = videobuf_dqbuf(file,q,b);
+		DEB_D(("VIDIOC_DQBUF: ret:%d, index:%d\n",ret,b->index));
+		return ret;
 	}
 	case VIDIOC_STREAMON: {
 		DEB_D(("VIDIOC_STREAMON \n"));
@@ -1075,7 +1090,7 @@
 
 		q = &fh->video_q;
 		down(&q->lock);
-		err = videobuf_mmap_setup(file,q,gbuffers,gbufsize);
+		err = videobuf_mmap_setup(file,q,gbuffers,gbufsize); // ,V4L2_MEMORY_MMAP);
 		if (err < 0) {
 			up(&q->lock);
 			return err;
@@ -1250,7 +1265,7 @@
 	vv->video_q.dev              = dev;
 
 	/* set some default values */
-	vv->standard = &dev->ext->ext_vv_data->stds[0];
+	vv->standard = &dev->ext_vv_data->stds[0];
 
 	/* FIXME: what's this? */
 	vv->current_hps_source = SAA7146_HPS_SOURCE_PORT_A;
@@ -1287,7 +1302,7 @@
 	if( 0 != vv->ov_data ) {
 		if( fh == vv->ov_data->fh ) {
 			spin_lock_irqsave(&dev->slock,flags);
-			stop_preview(fh);
+			saa7146_stop_preview(fh);
 			spin_unlock_irqrestore(&dev->slock,flags);
 		}
 	}
@@ -1331,7 +1346,7 @@
 
 	if( vv->ov_data != NULL ) {
 		ov_fh = vv->ov_data->fh;
-		stop_preview(ov_fh);
+		saa7146_stop_preview(ov_fh);
 		restart_overlay = 1;
 	}
 
@@ -1343,7 +1358,7 @@
 
 	/* restart overlay if it was active before */
 	if( 0 != restart_overlay ) {
-		start_preview(ov_fh);
+		saa7146_start_preview(ov_fh);
 	}
 	
 	return ret;
@@ -1358,5 +1373,3 @@
 	.capture_begin = video_begin,
 	.capture_end = video_end,
 };
-
-EXPORT_SYMBOL_GPL(saa7146_video_uops);
diff -Nru a/drivers/media/common/saa7146_vv_ksyms.c b/drivers/media/common/saa7146_vv_ksyms.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/common/saa7146_vv_ksyms.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,15 @@
+#include <linux/module.h>
+#include <media/saa7146_vv.h>
+
+EXPORT_SYMBOL_GPL(saa7146_vbi_uops);
+EXPORT_SYMBOL_GPL(saa7146_video_uops);
+
+EXPORT_SYMBOL_GPL(saa7146_start_preview);
+EXPORT_SYMBOL_GPL(saa7146_stop_preview);
+
+EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync);
+EXPORT_SYMBOL_GPL(saa7146_register_device);
+EXPORT_SYMBOL_GPL(saa7146_unregister_device);
+
+EXPORT_SYMBOL_GPL(saa7146_vv_init);
+EXPORT_SYMBOL_GPL(saa7146_vv_release);
diff -Nru a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
--- a/drivers/media/dvb/Kconfig	Sat Jul 19 12:54:24 2003
+++ b/drivers/media/dvb/Kconfig	Sat Jul 19 12:54:24 2003
@@ -33,9 +33,19 @@
 source "drivers/media/dvb/frontends/Kconfig"
 
 comment "Supported SAA7146 based PCI Adapters"
-	depends on DVB
+	depends on DVB && PCI
 
 source "drivers/media/dvb/ttpci/Kconfig"
+
+comment "Supported USB Adapters"
+	depends on DVB && USB
+
+source "drivers/media/dvb/ttusb-budget/Kconfig"
+source "drivers/media/dvb/ttusb-dec/Kconfig"
+
+comment "Supported FlexCopII (B2C2) Adapters"
+	depends on DVB && PCI
+source "drivers/media/dvb/b2c2/Kconfig"
 
 endmenu
 
diff -Nru a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile
--- a/drivers/media/dvb/Makefile	Sat Jul 19 12:54:25 2003
+++ b/drivers/media/dvb/Makefile	Sat Jul 19 12:54:25 2003
@@ -2,4 +2,5 @@
 # Makefile for the kernel multimedia device drivers.
 #
 
-obj-y        := dvb-core/ frontends/ ttpci/ # ttusb-budget/
+obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/
+
diff -Nru a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/b2c2/Kconfig	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,8 @@
+config DVB_B2C2_SKYSTAR
+	tristate "Technisat Skystar2 PCI"
+	depends on DVB_CORE
+	help
+	  Support for the Skystar2 PCI DVB card by Technisat, which
+	  is equipped with the FlexCopII chipset by B2C2.
+
+	  Say Y if you own such a device and want to use it.
diff -Nru a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/b2c2/Makefile	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,3 @@
+obj-$(CONFIG_DVB_B2C2_SKYSTAR) += skystar2.o
+
+EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
diff -Nru a/drivers/media/dvb/b2c2/skystar2.c b/drivers/media/dvb/b2c2/skystar2.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/b2c2/skystar2.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,2506 @@
+/*
+ * skystar2.c - driver for the Technisat SkyStar2 PCI DVB card
+ *              based on the FlexCopII by B2C2,Inc.
+ *
+ * Copyright (C) 2003  V.C. , skystar@moldova.cc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include "dvb_i2c.h"
+#include "dvb_frontend.h"
+#include "dvb_functions.h"
+
+#include <linux/dvb/frontend.h>
+#include <linux/dvb/dmx.h>
+#include "dvb_demux.h"
+#include "dmxdev.h"
+#include "dvb_filter.h"
+#include "dvbdev.h"
+#include "demux.h"
+#include "dvb_net.h"
+
+static int debug = 0;
+#define dprintk(x...) do { if (debug) printk(x); } while (0)
+
+#define SizeOfBufDMA1	0x3AC00
+#define SizeOfBufDMA2	0x758
+
+struct dmaq {
+
+	u32 bus_addr;
+	u32 head;
+	u32 tail;
+	u32 buffer_size;
+	u8 *buffer;
+};
+
+struct packet_header {
+
+	u32 sync_byte;
+	u32 transport_error_indicator;
+	u32 payload_unit_start_indicator;
+	u32 transport_priority;
+	u32 pid;
+	u32 transport_scrambling_control;
+	u32 adaptation_field_control;
+	u32 continuity_counter;
+};
+
+struct adapter {
+
+	struct pci_dev *pdev;
+
+	u8 card_revision;
+	u32 b2c2_revision;
+	u32 PidFilterMax;
+	u32 MacFilterMax;
+	u32 irq;
+	u32 io_mem;
+	u32 io_port;
+	u8 mac_addr[8];
+	u32 dwSramType;
+
+	struct dvb_adapter *dvb_adapter;
+	struct dvb_demux demux;
+	struct dmxdev dmxdev;
+	struct dmx_frontend hw_frontend;
+	struct dmx_frontend mem_frontend;
+	struct dvb_i2c_bus *i2c_bus;
+	struct dvb_net dvbnet;
+
+	struct semaphore i2c_sem;
+
+	struct dmaq dmaq1;
+	struct dmaq dmaq2;
+
+	u32 dma_ctrl;
+	u32 dma_status;
+
+	u32 capturing;
+
+	spinlock_t lock;
+
+	u16 pids[0x27];
+	u32 mac_filter;
+};
+
+#define WriteRegDW(adapter,reg,value) writel(value, adapter->io_mem + reg)
+#define ReadRegDW(adapter,reg) readl(adapter->io_mem + reg)
+
+static void WriteRegOp(struct adapter *adapter, u32 reg, u32 operation, u32 andvalue, u32 orvalue)
+{
+	u32 tmp;
+
+	tmp = ReadRegDW(adapter, reg);
+
+	if (operation == 1)
+		tmp = tmp | orvalue;
+	if (operation == 2)
+		tmp = tmp & andvalue;
+	if (operation == 3)
+		tmp = (tmp & andvalue) | orvalue;
+
+	WriteRegDW(adapter, reg, tmp);
+}
+
+/* i2c functions */
+static int i2cMainWriteForFlex2(struct adapter * adapter, u32 command, u8 * buf, u32 retries)
+{
+	u32 i;
+	u32 value;
+
+	WriteRegDW(adapter, 0x100, 0);
+	WriteRegDW(adapter, 0x100, command);
+
+	for (i = 0; i < retries; i++) {
+		value = ReadRegDW(adapter, 0x100);
+
+		if ((value & 0x40000000) == 0) {
+			if ((value & 0x81000000) == 0x80000000) {
+				if (buf != 0)
+					*buf = (value >> 0x10) & 0xff;
+
+				return 1;
+			}
+
+		} else {
+
+			WriteRegDW(adapter, 0x100, 0);
+			WriteRegDW(adapter, 0x100, command);
+		}
+	}
+
+	return 0;
+}
+
+/* device = 0x10000000 for tuner, 0x20000000 for eeprom */
+static void i2cMainSetup(u32 device, u32 chip_addr, u8 op, u8 addr, u32 value, u32 len, u32 *command)
+{
+	*command = device | ((len - 1) << 26) | (value << 16) | (addr << 8) | chip_addr;
+
+	if (op != 0)
+		*command = *command | 0x03000000;
+	else
+		*command = *command | 0x01000000;
+}
+
+static int FlexI2cRead4(struct adapter * adapter, u32 device, u32 chip_addr, u16 addr, u8 * buf, u8 len)
+{
+	u32 command;
+	u32 value;
+
+	int result, i;
+
+	i2cMainSetup(device, chip_addr, 1, addr, 0, len, &command);
+
+	result = i2cMainWriteForFlex2(adapter, command, buf, 100000);
+
+	if ((result & 0xff) != 0) {
+		if (len > 1) {
+			value = ReadRegDW(adapter, 0x104);
+
+			for (i = 1; i < len; i++) {
+				buf[i] = value & 0xff;
+				value = value >> 8;
+			}
+		}
+	}
+
+	return result;
+}
+
+static int FlexI2cWrite4(struct adapter * adapter, u32 device, u32 chip_addr, u32 addr, u8 * buf, u8 len)
+{
+	u32 command;
+	u32 value;
+	int i;
+
+	if (len > 1) {
+		value = 0;
+
+		for (i = len; i > 1; i--) {
+			value = value << 8;
+			value = value | buf[i - 1];
+		}
+
+		WriteRegDW(adapter, 0x104, value);
+	}
+
+	i2cMainSetup(device, chip_addr, 0, addr, buf[0], len, &command);
+
+	return i2cMainWriteForFlex2(adapter, command, 0, 100000);
+}
+
+static void fixchipaddr(u32 device, u32 bus, u32 addr, u32 *ret)
+{
+	if (device == 0x20000000)
+		*ret = bus | ((addr >> 8) & 3);
+
+	*ret = bus;
+}
+
+static u32 FLEXI2C_read(struct adapter * adapter, u32 device, u32 bus, u32 addr, u8 * buf, u32 len)
+{
+	u32 chipaddr;
+	u32 bytes_to_transfer;
+	u8 *start;
+
+//  dprintk("%s:\n", __FUNCTION__);
+
+	start = buf;
+
+	while (len != 0) {
+		bytes_to_transfer = len;
+
+		if (bytes_to_transfer > 4)
+			bytes_to_transfer = 4;
+
+		fixchipaddr(device, bus, addr, &chipaddr);
+
+		if (FlexI2cRead4(adapter, device, chipaddr, addr, buf, bytes_to_transfer) == 0)
+			return buf - start;
+
+		buf = buf + bytes_to_transfer;
+		addr = addr + bytes_to_transfer;
+		len = len - bytes_to_transfer;
+	};
+
+	return buf - start;
+}
+
+static u32 FLEXI2C_write(struct adapter * adapter, u32 device, u32 bus, u32 addr, u8 * buf, u32 len)
+{
+	u32 chipaddr;
+	u32 bytes_to_transfer;
+	u8 *start;
+
+//  dprintk("%s:\n", __FUNCTION__);
+
+	start = buf;
+
+	while (len != 0) {
+		bytes_to_transfer = len;
+
+		if (bytes_to_transfer > 4)
+			bytes_to_transfer = 4;
+
+		fixchipaddr(device, bus, addr, &chipaddr);
+
+		if (FlexI2cWrite4(adapter, device, chipaddr, addr, buf, bytes_to_transfer) == 0)
+			return buf - start;
+
+		buf = buf + bytes_to_transfer;
+		addr = addr + bytes_to_transfer;
+		len = len - bytes_to_transfer;
+	}
+
+	return buf - start;
+}
+
+static int master_xfer(struct dvb_i2c_bus *i2c, const struct i2c_msg *msgs, int num)
+{
+	struct adapter *tmp = i2c->data;
+	int i, ret = 0;
+
+	if (down_interruptible(&tmp->i2c_sem))
+		return -ERESTARTSYS;
+
+	if (0) {
+		dprintk("%s:\n", __FUNCTION__);
+
+		for (i = 0; i < num; i++) {
+			printk("message %d: flags=%x, addr=0x%04x, buf=%x, len=%d \n", i, msgs[i].flags, msgs[i].addr, (u32) msgs[i].buf, msgs[i].len);
+		}
+	}
+	
+	/* allow only the vp310 frontend to access the bus */
+	if ((msgs[0].addr != 0x0E) && (msgs[0].addr != 0x61)) {
+		up(&tmp->i2c_sem);
+
+		return -EREMOTEIO;
+	}
+
+	if ((num == 1) && (msgs[0].buf != NULL)) {
+		if (msgs[0].flags == I2C_M_RD) {
+			ret = -EINVAL;
+
+		} else {
+
+			// single writes do have the reg addr in buf[0] and data in buf[1] to buf[n]
+			ret = FLEXI2C_write(tmp, 0x10000000, msgs[0].addr, msgs[0].buf[0], &msgs[0].buf[1], msgs[0].len - 1);
+
+			if (ret != msgs[0].len - 1)
+				ret = -EREMOTEIO;
+			else
+				ret = num;
+		}
+
+	} else if ((num == 2) && (msgs[1].buf != NULL)) {
+
+		// i2c reads consist of a reg addr _write_ followed by a data read, so msg[1].flags has to be examined
+		if (msgs[1].flags == I2C_M_RD) {
+			ret = FLEXI2C_read(tmp, 0x10000000, msgs[0].addr, msgs[0].buf[0], msgs[1].buf, msgs[1].len);
+
+		} else {
+
+			ret = FLEXI2C_write(tmp, 0x10000000, msgs[0].addr, msgs[0].buf[0], msgs[1].buf, msgs[1].len);
+		}
+
+		if (ret != msgs[1].len)
+			ret = -EREMOTEIO;
+		else
+			ret = num;
+	}
+
+	up(&tmp->i2c_sem);
+
+	/* master xfer functions always return the number of successfully
+	   transmitted messages, not the number of transmitted bytes.
+	   return -EREMOTEIO in case of failure. */
+	return ret;
+}
+
+/* SRAM (Skystar2 rev2.3 has one "ISSI IS61LV256" chip on board,
+   but it seems that FlexCopII can work with more than one chip) */
+static void SRAMSetNetDest(struct adapter * adapter, u8 dest)
+{
+	u32 tmp;
+
+	udelay(1000);
+
+	tmp = (ReadRegDW(adapter, 0x714) & 0xFFFFFFFC) | (dest & 3);
+
+	udelay(1000);
+
+	WriteRegDW(adapter, 0x714, tmp);
+	WriteRegDW(adapter, 0x714, tmp);
+
+	udelay(1000);
+
+	/* return value is never used? */
+/*	return tmp; */
+}
+
+static void SRAMSetCaiDest(struct adapter * adapter, u8 dest)
+{
+	u32 tmp;
+
+	udelay(1000);
+
+	tmp = (ReadRegDW(adapter, 0x714) & 0xFFFFFFF3) | ((dest & 3) << 2);
+
+	udelay(1000);
+	udelay(1000);
+
+	WriteRegDW(adapter, 0x714, tmp);
+	WriteRegDW(adapter, 0x714, tmp);
+
+	udelay(1000);
+
+	/* return value is never used? */
+/*	return tmp; */
+}
+
+static void SRAMSetCaoDest(struct adapter * adapter, u8 dest)
+{
+	u32 tmp;
+
+	udelay(1000);
+
+	tmp = (ReadRegDW(adapter, 0x714) & 0xFFFFFFCF) | ((dest & 3) << 4);
+
+	udelay(1000);
+	udelay(1000);
+
+	WriteRegDW(adapter, 0x714, tmp);
+	WriteRegDW(adapter, 0x714, tmp);
+
+	udelay(1000);
+
+	/* return value is never used? */
+/*	return tmp; */
+}
+
+static void SRAMSetMediaDest(struct adapter * adapter, u8 dest)
+{
+	u32 tmp;
+
+	udelay(1000);
+
+	tmp = (ReadRegDW(adapter, 0x714) & 0xFFFFFF3F) | ((dest & 3) << 6);
+
+	udelay(1000);
+	udelay(1000);
+
+	WriteRegDW(adapter, 0x714, tmp);
+	WriteRegDW(adapter, 0x714, tmp);
+
+	udelay(1000);
+
+	/* return value is never used? */
+/*	return tmp; */
+}
+
+/* SRAM memory is accessed through a buffer register in the FlexCop
+   chip (0x700). This register has the following structure:
+    bits 0-14  : address
+    bit  15    : read/write flag
+    bits 16-23 : 8-bit word to write
+    bits 24-27 : = 4
+    bits 28-29 : memory bank selector
+    bit  31    : busy flag
+*/
+static void FlexSramWrite(struct adapter *adapter, u32 bank, u32 addr, u8 * buf, u32 len)
+{
+	u32 i, command, retries;
+
+	for (i = 0; i < len; i++) {
+		command = bank | addr | 0x04000000 | (*buf << 0x10);
+
+		retries = 2;
+
+		while (((ReadRegDW(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
+			mdelay(1);
+			retries--;
+		};
+
+		if (retries == 0)
+			printk("%s: SRAM timeout\n", __FUNCTION__);
+
+		WriteRegDW(adapter, 0x700, command);
+
+		buf++;
+		addr++;
+	}
+}
+
+static void FlexSramRead(struct adapter *adapter, u32 bank, u32 addr, u8 * buf, u32 len)
+{
+	u32 i, command, value, retries;
+
+	for (i = 0; i < len; i++) {
+		command = bank | addr | 0x04008000;
+
+		retries = 10000;
+
+		while (((ReadRegDW(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
+			mdelay(1);
+			retries--;
+		};
+
+		if (retries == 0)
+			printk("%s: SRAM timeout\n", __FUNCTION__);
+
+		WriteRegDW(adapter, 0x700, command);
+
+		retries = 10000;
+
+		while (((ReadRegDW(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
+			mdelay(1);
+			retries--;
+		};
+
+		if (retries == 0)
+			printk("%s: SRAM timeout\n", __FUNCTION__);
+
+		value = ReadRegDW(adapter, 0x700) >> 0x10;
+
+		*buf = (value & 0xff);
+
+		addr++;
+		buf++;
+	}
+}
+
+static void SRAM_writeChunk(struct adapter *adapter, u32 addr, u8 * buf, u16 len)
+{
+	u32 bank;
+
+	bank = 0;
+
+	if (adapter->dwSramType == 0x20000) {
+		bank = (addr & 0x18000) << 0x0D;
+	}
+
+	if (adapter->dwSramType == 0x00000) {
+		if ((addr >> 0x0F) == 0)
+			bank = 0x20000000;
+		else
+			bank = 0x10000000;
+	}
+
+	FlexSramWrite(adapter, bank, addr & 0x7FFF, buf, len);
+}
+
+static void SRAM_readChunk(struct adapter *adapter, u32 addr, u8 * buf, u16 len)
+{
+	u32 bank;
+
+	bank = 0;
+
+	if (adapter->dwSramType == 0x20000) {
+		bank = (addr & 0x18000) << 0x0D;
+	}
+
+	if (adapter->dwSramType == 0x00000) {
+		if ((addr >> 0x0F) == 0)
+			bank = 0x20000000;
+		else
+			bank = 0x10000000;
+	}
+
+	FlexSramRead(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_readChunk(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_writeChunk(adapter, addr, buf, length);
+
+		addr = addr + length;
+		buf = buf + length;
+		len = len - length;
+	}
+}
+
+static void SRAM_setSize(struct adapter *adapter, u32 mask)
+{
+	WriteRegDW(adapter, 0x71C, (mask | (~0x30000 & ReadRegDW(adapter, 0x71C))));
+}
+
+static void SRAM_init(struct adapter *adapter)
+{
+	u32 tmp;
+
+	tmp = ReadRegDW(adapter, 0x71C);
+
+	WriteRegDW(adapter, 0x71C, 1);
+
+	if (ReadRegDW(adapter, 0x71C) != 0) {
+		WriteRegDW(adapter, 0x71C, tmp);
+
+		adapter->dwSramType = tmp & 0x30000;
+
+		dprintk("%s: dwSramType = %x\n", __FUNCTION__, adapter->dwSramType);
+
+	} else {
+
+		adapter->dwSramType = 0x10000;
+
+		dprintk("%s: dwSramType = %x\n", __FUNCTION__, adapter->dwSramType);
+	}
+
+	/* return value is never used? */
+/*	return adapter->dwSramType; */
+}
+
+static int SRAM_testLocation(struct adapter *adapter, u32 mask, u32 addr)
+{
+	u8 tmp1, tmp2;
+
+	dprintk("%s: mask = %x, addr = %x\n", __FUNCTION__, mask, addr);
+
+	SRAM_setSize(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->dwSramType == 0x10000)
+		return 32768;	//  32K
+	if (adapter->dwSramType == 0x00000)
+		return 65536;	//  64K        
+	if (adapter->dwSramType == 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 SramDetectForFlex2(struct adapter *adapter)
+{
+	u32 tmp, tmp2, tmp3;
+
+	dprintk("%s:\n", __FUNCTION__);
+
+	tmp = ReadRegDW(adapter, 0x208);
+	WriteRegDW(adapter, 0x208, 0);
+
+	tmp2 = ReadRegDW(adapter, 0x71C);
+
+	dprintk("%s: tmp2 = %x\n", __FUNCTION__, tmp2);
+
+	WriteRegDW(adapter, 0x71C, 1);
+
+	tmp3 = ReadRegDW(adapter, 0x71C);
+
+	dprintk("%s: tmp3 = %x\n", __FUNCTION__, tmp3);
+
+	WriteRegDW(adapter, 0x71C, tmp2);
+
+	// check for internal SRAM ???
+	tmp3--;
+	if (tmp3 != 0) {
+		SRAM_setSize(adapter, 0x10000);
+		SRAM_init(adapter);
+		WriteRegDW(adapter, 0x208, tmp);
+
+		dprintk("%s: sram size = 32K\n", __FUNCTION__);
+
+		return 32;
+	}
+
+	if (SRAM_testLocation(adapter, 0x20000, 0x18000) != 0) {
+		SRAM_setSize(adapter, 0x20000);
+		SRAM_init(adapter);
+		WriteRegDW(adapter, 0x208, tmp);
+
+		dprintk("%s: sram size = 128K\n", __FUNCTION__);
+
+		return 128;
+	}
+
+	if (SRAM_testLocation(adapter, 0x00000, 0x10000) != 0) {
+		SRAM_setSize(adapter, 0x00000);
+		SRAM_init(adapter);
+		WriteRegDW(adapter, 0x208, tmp);
+
+		dprintk("%s: sram size = 64K\n", __FUNCTION__);
+
+		return 64;
+	}
+
+	if (SRAM_testLocation(adapter, 0x10000, 0x00000) != 0) {
+		SRAM_setSize(adapter, 0x10000);
+		SRAM_init(adapter);
+		WriteRegDW(adapter, 0x208, tmp);
+
+		dprintk("%s: sram size = 32K\n", __FUNCTION__);
+
+		return 32;
+	}
+
+	SRAM_setSize(adapter, 0x10000);
+	SRAM_init(adapter);
+	WriteRegDW(adapter, 0x208, tmp);
+
+	dprintk("%s: SRAM detection failed. Set to 32K \n", __FUNCTION__);
+
+	return 0;
+}
+
+static void SLL_detectSramSize(struct adapter *adapter)
+{
+	SramDetectForFlex2(adapter);
+}
+/* EEPROM (Skystar2 has one "24LC08B" chip on board) */
+/*
+static int EEPROM_write(struct adapter *adapter, u16 addr, u8 * buf, u16 len)
+{
+	return FLEXI2C_write(adapter, 0x20000000, 0x50, addr, buf, len);
+}
+*/
+
+static int EEPROM_read(struct adapter *adapter, u16 addr, u8 * buf, u16 len)
+{
+	return FLEXI2C_read(adapter, 0x20000000, 0x50, addr, buf, len);
+}
+
+u8 calc_LRC(u8 * buf, u32 len)
+{
+	u32 i;
+	u8 sum;
+
+	sum = 0;
+
+	for (i = 0; i < len; i++)
+		sum = sum ^ buf[i];
+
+	return sum;
+}
+
+static int EEPROM_LRC_read(struct adapter *adapter, u32 addr, u32 len, u8 * buf, u32 retries)
+{
+	int i;
+
+	for (i = 0; i < retries; i++) {
+		if (EEPROM_read(adapter, addr, buf, len) == len) {
+			if (calc_LRC(buf, len - 1) == buf[len - 1])
+				return 1;
+		}
+	}
+
+	return 0;
+}
+
+/*
+static int EEPROM_LRC_write(struct adapter *adapter, u32 addr, u32 len, u8 * wbuf, u8 * rbuf, u32 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 called from the initialization routine 
+   to unlock SkyStar2 cards, locked by "Europe On Line".
+        
+   in cards from "Europe On Line" the key is:
+
+       u8 key[20] = {
+ 	    0xB2, 0x01, 0x00, 0x00,
+ 	    0x00, 0x00, 0x00, 0x00,
+ 	    0x00, 0x00, 0x00, 0x00,
+ 	    0x00, 0x00, 0x00, 0x00,
+       };
+
+       LRC = 0xB3;
+
+  in unlocked cards the key is:
+
+       u8 key[20] = {
+ 	    0xB2, 0x00, 0x00, 0x00,
+ 	    0x00, 0x00, 0x00, 0x00,
+ 	    0x00, 0x00, 0x00, 0x00,
+ 	    0x00, 0x00, 0x00, 0x00,
+       };
+
+      LRC = 0xB2;
+*/
+/*
+static int EEPROM_writeKey(struct adapter *adapter, u8 * key, u32 len)
+{
+	u8 rbuf[20];
+	u8 wbuf[20];
+
+	if (len != 16)
+		return 0;
+
+	memcpy(wbuf, key, len);
+
+	wbuf[16] = 0;
+	wbuf[17] = 0;
+	wbuf[18] = 0;
+	wbuf[19] = calc_LRC(wbuf, 19);
+
+	return EEPROM_LRC_write(adapter, 0x3E4, 20, wbuf, rbuf, 4);
+}
+*/
+static int EEPROM_readKey(struct adapter *adapter, u8 * key, u32 len)
+{
+	u8 buf[20];
+
+	if (len != 16)
+		return 0;
+
+	if (EEPROM_LRC_read(adapter, 0x3E4, 20, buf, 4) == 0)
+		return 0;
+
+	memcpy(key, buf, len);
+
+	return 1;
+}
+
+static int EEPROM_getMacAddr(struct adapter *adapter, char type, u8 * mac)
+{
+	u8 tmp[8];
+
+	if (EEPROM_LRC_read(adapter, 0x3F8, 8, tmp, 4) != 0) {
+		if (type != 0) {
+			mac[0] = tmp[0];
+			mac[1] = tmp[1];
+			mac[2] = tmp[2];
+			mac[3] = 0xFE;
+			mac[4] = 0xFF;
+			mac[5] = tmp[3];
+			mac[6] = tmp[4];
+			mac[7] = tmp[5];
+
+		} else {
+
+			mac[0] = tmp[0];
+			mac[1] = tmp[1];
+			mac[2] = tmp[2];
+			mac[3] = tmp[3];
+			mac[4] = tmp[4];
+			mac[5] = tmp[5];
+		}
+
+		return 1;
+
+	} else {
+
+		if (type == 0) {
+			memset(mac, 0, 6);
+
+		} else {
+
+			memset(mac, 0, 8);
+		}
+
+		return 0;
+	}
+}
+
+/*
+static char EEPROM_setMacAddr(struct adapter *adapter, char type, u8 * mac)
+{
+	u8 tmp[8];
+
+	if (type != 0) {
+		tmp[0] = mac[0];
+		tmp[1] = mac[1];
+		tmp[2] = mac[2];
+		tmp[3] = mac[5];
+		tmp[4] = mac[6];
+		tmp[5] = mac[7];
+
+	} else {
+
+		tmp[0] = mac[0];
+		tmp[1] = mac[1];
+		tmp[2] = mac[2];
+		tmp[3] = mac[3];
+		tmp[4] = mac[4];
+		tmp[5] = mac[5];
+	}
+
+	tmp[6] = 0;
+	tmp[7] = calc_LRC(tmp, 7);
+
+	if (EEPROM_write(adapter, 0x3F8, tmp, 8) == 8)
+		return 1;
+
+	return 0;
+}
+*/
+
+/* PID filter */
+static void FilterEnableStream1Filter(struct adapter *adapter, u32 op)
+{
+	dprintk("%s: op=%x\n", __FUNCTION__, op);
+
+	if (op == 0) {
+		WriteRegOp(adapter, 0x208, 2, ~0x00000001, 0);
+
+	} else {
+
+		WriteRegOp(adapter, 0x208, 1, 0, 0x00000001);
+	}
+}
+
+static void FilterEnableStream2Filter(struct adapter *adapter, u32 op)
+{
+	dprintk("%s: op=%x\n", __FUNCTION__, op);
+
+	if (op == 0) {
+		WriteRegOp(adapter, 0x208, 2, ~0x00000002, 0);
+
+	} else {
+
+		WriteRegOp(adapter, 0x208, 1, 0, 0x00000002);
+	}
+}
+
+static void FilterEnablePcrFilter(struct adapter *adapter, u32 op)
+{
+	dprintk("%s: op=%x\n", __FUNCTION__, op);
+
+	if (op == 0) {
+		WriteRegOp(adapter, 0x208, 2, ~0x00000004, 0);
+
+	} else {
+
+		WriteRegOp(adapter, 0x208, 1, 0, 0x00000004);
+	}
+}
+
+static void FilterEnablePmtFilter(struct adapter *adapter, u32 op)
+{
+	dprintk("%s: op=%x\n", __FUNCTION__, op);
+
+	if (op == 0) {
+		WriteRegOp(adapter, 0x208, 2, ~0x00000008, 0);
+
+	} else {
+
+		WriteRegOp(adapter, 0x208, 1, 0, 0x00000008);
+	}
+}
+
+static void FilterEnableEmmFilter(struct adapter *adapter, u32 op)
+{
+	dprintk("%s: op=%x\n", __FUNCTION__, op);
+
+	if (op == 0) {
+		WriteRegOp(adapter, 0x208, 2, ~0x00000010, 0);
+
+	} else {
+
+		WriteRegOp(adapter, 0x208, 1, 0, 0x00000010);
+	}
+}
+
+static void FilterEnableEcmFilter(struct adapter *adapter, u32 op)
+{
+	dprintk("%s: op=%x\n", __FUNCTION__, op);
+
+	if (op == 0) {
+		WriteRegOp(adapter, 0x208, 2, ~0x00000020, 0);
+
+	} else {
+
+		WriteRegOp(adapter, 0x208, 1, 0, 0x00000020);
+	}
+}
+
+/*
+static void FilterEnableNullFilter(struct adapter *adapter, u32 op)
+{
+	dprintk("%s: op=%x\n", __FUNCTION__, op);
+
+	if (op == 0) {
+		WriteRegOp(adapter, 0x208, 2, ~0x00000040, 0);
+
+	} else {
+
+		WriteRegOp(adapter, 0x208, 1, 0, 0x00000040);
+	}
+}
+*/
+
+static void FilterEnableMaskFilter(struct adapter *adapter, u32 op)
+{
+	dprintk("%s: op=%x\n", __FUNCTION__, op);
+
+	if (op == 0) {
+		WriteRegOp(adapter, 0x208, 2, ~0x00000080, 0);
+
+	} else {
+
+		WriteRegOp(adapter, 0x208, 1, 0, 0x00000080);
+	}
+}
+
+
+static void CtrlEnableMAC(struct adapter *adapter, u32 op)
+{
+	if (op == 0) {
+		WriteRegOp(adapter, 0x208, 2, ~0x00004000, 0);
+
+	} else {
+
+		WriteRegOp(adapter, 0x208, 1, 0, 0x00004000);
+	}
+}
+
+static int CASetMacDstAddrFilter(struct adapter *adapter, u8 * mac)
+{
+	u32 tmp1, tmp2;
+
+	tmp1 = (mac[3] << 0x18) | (mac[2] << 0x10) | (mac[1] << 0x08) | mac[0];
+	tmp2 = (mac[5] << 0x08) | mac[4];
+
+	WriteRegDW(adapter, 0x418, tmp1);
+	WriteRegDW(adapter, 0x41C, tmp2);
+
+	return 0;
+}
+
+/*
+static void SetIgnoreMACFilter(struct adapter *adapter, u8 op)
+{
+	if (op != 0) {
+		WriteRegOp(adapter, 0x208, 2, ~0x00004000, 0);
+
+		adapter->mac_filter = 1;
+
+	} else {
+
+		if (adapter->mac_filter != 0) {
+			adapter->mac_filter = 0;
+
+			WriteRegOp(adapter, 0x208, 1, 0, 0x00004000);
+		}
+	}
+}
+*/
+
+/*
+static void CheckNullFilterEnable(struct adapter *adapter)
+{
+	FilterEnableNullFilter(adapter, 1);
+	FilterEnableMaskFilter(adapter, 1);
+}
+*/
+
+static void InitPIDsInfo(struct adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < 0x27; i++)
+		adapter->pids[i] = 0x1FFF;
+}
+
+static int CheckPID(struct adapter *adapter, u16 pid)
+{
+	u32 i;
+
+	if (pid == 0x1FFF)
+		return 0;
+
+	for (i = 0; i < 0x27; i++) {
+		if (adapter->pids[i] == pid)
+			return 1;
+	}
+
+	return 0;
+}
+
+static void PidSetGroupPID(struct adapter * adapter, u32 pid)
+{
+	u32 value;
+
+	dprintk("%s: pid=%x\n", __FUNCTION__, pid);
+
+	value = (pid & 0x3FFF) | (ReadRegDW(adapter, 0x30C) & 0xFFFF0000);
+
+	WriteRegDW(adapter, 0x30C, value);
+
+	/* return value is never used? */
+/*	return value; */
+}
+
+static void PidSetGroupMASK(struct adapter * adapter, u32 pid)
+{
+	u32 value;
+
+	dprintk("%s: pid=%x\n", __FUNCTION__, pid);
+
+	value = ((pid & 0x3FFF) << 0x10) | (ReadRegDW(adapter, 0x30C) & 0xFFFF);
+
+	WriteRegDW(adapter, 0x30C, value);
+
+	/* return value is never used? */
+/*	return value; */
+}
+
+static void PidSetStream1PID(struct adapter * adapter, u32 pid)
+{
+	u32 value;
+
+	dprintk("%s: pid=%x\n", __FUNCTION__, pid);
+
+	value = (pid & 0x3FFF) | (ReadRegDW(adapter, 0x300) & 0xFFFFC000);
+
+	WriteRegDW(adapter, 0x300, value);
+
+	/* return value is never used? */
+/*	return value; */
+}
+
+static void PidSetStream2PID(struct adapter * adapter, u32 pid)
+{
+	u32 value;
+
+	dprintk("%s: pid=%x\n", __FUNCTION__, pid);
+
+	value = ((pid & 0x3FFF) << 0x10) | (ReadRegDW(adapter, 0x300) & 0xFFFF);
+
+	WriteRegDW(adapter, 0x300, value);
+
+	/* return value is never used? */
+/*	return value; */
+}
+
+static void PidSetPcrPID(struct adapter * adapter, u32 pid)
+{
+	u32 value;
+
+	dprintk("%s: pid=%x\n", __FUNCTION__, pid);
+
+	value = (pid & 0x3FFF) | (ReadRegDW(adapter, 0x304) & 0xFFFFC000);
+
+	WriteRegDW(adapter, 0x304, value);
+
+	/* return value is never used? */
+/*	return value; */
+}
+
+static void PidSetPmtPID(struct adapter * adapter, u32 pid)
+{
+	u32 value;
+
+	dprintk("%s: pid=%x\n", __FUNCTION__, pid);
+
+	value = ((pid & 0x3FFF) << 0x10) | (ReadRegDW(adapter, 0x304) & 0x3FFF);
+
+	WriteRegDW(adapter, 0x304, value);
+
+	/* return value is never used? */
+/*	return value; */
+}
+
+static void PidSetEmmPID(struct adapter * adapter, u32 pid)
+{
+	u32 value;
+
+	dprintk("%s: pid=%x\n", __FUNCTION__, pid);
+
+	value = (pid & 0xFFFF) | (ReadRegDW(adapter, 0x308) & 0xFFFF0000);
+
+	WriteRegDW(adapter, 0x308, value);
+
+	/* return value is never used? */
+/*	return value; */
+}
+
+static void PidSetEcmPID(struct adapter * adapter, u32 pid)
+{
+	u32 value;
+
+	dprintk("%s: pid=%x\n", __FUNCTION__, pid);
+
+	value = (pid << 0x10) | (ReadRegDW(adapter, 0x308) & 0xFFFF);
+
+	WriteRegDW(adapter, 0x308, value);
+
+	/* return value is never used? */
+/*	return value; */
+}
+
+static int PidGetStream1PID(struct adapter * adapter)
+{
+	return ReadRegDW(adapter, 0x300) & 0x00001FFF;
+}
+
+static int PidGetStream2PID(struct adapter * adapter)
+{
+	return (ReadRegDW(adapter, 0x300) >> 0x10)& 0x00001FFF;
+}
+
+static int PidGetPcrPID(struct adapter * adapter)
+{
+	return ReadRegDW(adapter, 0x304) & 0x00001FFF;
+}
+
+static int PidGetPmtPID(struct adapter * adapter)
+{
+	return (ReadRegDW(adapter, 0x304) >> 0x10)& 0x00001FFF;
+}
+
+static int PidGetEmmPID(struct adapter * adapter)
+{
+	return ReadRegDW(adapter, 0x308) & 0x00001FFF;
+}
+
+static int PidGetEcmPID(struct adapter * adapter)
+{
+	return (ReadRegDW(adapter, 0x308) >> 0x10)& 0x00001FFF;
+}
+
+static int PidGetGroupPID(struct adapter * adapter)
+{
+	return ReadRegDW(adapter, 0x30C) & 0x00001FFF;
+}
+
+static int PidGetGroupMASK(struct adapter * adapter)
+{
+	return (ReadRegDW(adapter, 0x30C) >> 0x10)& 0x00001FFF;
+}
+
+/*
+static void ResetHardwarePIDFilter(struct adapter *adapter)
+{
+	PidSetStream1PID(adapter, 0x1FFF);
+
+	PidSetStream2PID(adapter, 0x1FFF);
+	FilterEnableStream2Filter(adapter, 0);
+
+	PidSetPcrPID(adapter, 0x1FFF);
+	FilterEnablePcrFilter(adapter, 0);
+
+	PidSetPmtPID(adapter, 0x1FFF);
+	FilterEnablePmtFilter(adapter, 0);
+
+	PidSetEcmPID(adapter, 0x1FFF);
+	FilterEnableEcmFilter(adapter, 0);
+
+	PidSetEmmPID(adapter, 0x1FFF);
+	FilterEnableEmmFilter(adapter, 0);
+}
+*/
+
+static void OpenWholeBandwidth(struct adapter *adapter)
+{
+	PidSetGroupPID(adapter, 0);
+
+	PidSetGroupMASK(adapter, 0);
+
+	FilterEnableMaskFilter(adapter, 1);
+}
+
+static int AddHwPID(struct adapter *adapter, u32 pid)
+{
+	dprintk("%s: pid=%d\n", __FUNCTION__, pid);
+
+	if (pid <= 0x1F)
+		return 1;
+
+	if ((PidGetGroupMASK(adapter) == 0) && (PidGetGroupPID(adapter) == 0))
+		return 0;
+
+	if (PidGetStream1PID(adapter) == 0x1FFF) {
+		PidSetStream1PID(adapter, pid & 0xFFFF);
+
+		FilterEnableStream1Filter(adapter, 1);
+
+		return 1;
+	}
+
+	if (PidGetStream2PID(adapter) == 0x1FFF) {
+		PidSetStream2PID(adapter, (pid & 0xFFFF));
+
+		FilterEnableStream2Filter(adapter, 1);
+
+		return 1;
+	}
+
+	if (PidGetPcrPID(adapter) == 0x1FFF) {
+		PidSetPcrPID(adapter, (pid & 0xFFFF));
+
+		FilterEnablePcrFilter(adapter, 1);
+
+		return 1;
+	}
+
+	if ((PidGetPmtPID(adapter) & 0x1FFF) == 0x1FFF) {
+		PidSetPmtPID(adapter, (pid & 0xFFFF));
+
+		FilterEnablePmtFilter(adapter, 1);
+
+		return 1;
+	}
+
+	if ((PidGetEmmPID(adapter) & 0x1FFF) == 0x1FFF) {
+		PidSetEmmPID(adapter, (pid & 0xFFFF));
+
+		FilterEnableEmmFilter(adapter, 1);
+
+		return 1;
+	}
+
+	if ((PidGetEcmPID(adapter) & 0x1FFF) == 0x1FFF) {
+		PidSetEcmPID(adapter, (pid & 0xFFFF));
+
+		FilterEnableEcmFilter(adapter, 1);
+
+		return 1;
+	}
+
+	return -1;
+}
+
+static int RemoveHwPID(struct adapter *adapter, u32 pid)
+{
+	dprintk("%s: pid=%d\n", __FUNCTION__, pid);
+
+	if (pid <= 0x1F)
+		return 1;
+
+	if (PidGetStream1PID(adapter) == pid) {
+		PidSetStream1PID(adapter, 0x1FFF);
+
+		return 1;
+	}
+
+	if (PidGetStream2PID(adapter) == pid) {
+		PidSetStream2PID(adapter, 0x1FFF);
+
+		FilterEnableStream2Filter(adapter, 0);
+
+		return 1;
+	}
+
+	if (PidGetPcrPID(adapter) == pid) {
+		PidSetPcrPID(adapter, 0x1FFF);
+
+		FilterEnablePcrFilter(adapter, 0);
+
+		return 1;
+	}
+
+	if (PidGetPmtPID(adapter) == pid) {
+		PidSetPmtPID(adapter, 0x1FFF);
+
+		FilterEnablePmtFilter(adapter, 0);
+
+		return 1;
+	}
+
+	if (PidGetEmmPID(adapter) == pid) {
+		PidSetEmmPID(adapter, 0x1FFF);
+
+		FilterEnableEmmFilter(adapter, 0);
+
+		return 1;
+	}
+
+	if (PidGetEcmPID(adapter) == pid) {
+		PidSetEcmPID(adapter, 0x1FFF);
+
+		FilterEnableEcmFilter(adapter, 0);
+
+		return 1;
+	}
+
+	return -1;
+}
+
+static int AddPID(struct adapter *adapter, u32 pid)
+{
+	int i;
+
+	dprintk("%s: pid=%d\n", __FUNCTION__, pid);
+
+	if (pid > 0x1FFE)
+		return -1;
+
+	if (CheckPID(adapter, pid) == 1)
+		return 1;
+
+	for (i = 0; i < 0x27; i++) {
+		if (adapter->pids[i] == 0x1FFF)	// find free pid filter
+		{
+			adapter->pids[i] = pid;
+
+			if (AddHwPID(adapter, pid) < 0)
+				OpenWholeBandwidth(adapter);
+
+			return 1;
+		}
+	}
+
+	return -1;
+}
+
+static int RemovePID(struct adapter *adapter, u32 pid)
+{
+	u32 i;
+
+	dprintk("%s: pid=%d\n", __FUNCTION__, pid);
+
+	if (pid > 0x1FFE)
+		return -1;
+
+	for (i = 0; i < 0x27; i++) {
+		if (adapter->pids[i] == pid) {
+			adapter->pids[i] = 0x1FFF;
+
+			RemoveHwPID(adapter, pid);
+
+			return 1;
+		}
+	}
+
+	return -1;
+}
+
+/* dma & irq */
+static void CtrlEnableSmc(struct adapter *adapter, u32 op)
+{
+	if (op == 0) {
+		WriteRegOp(adapter, 0x208, 2, ~0x00000800, 0);
+
+	} else {
+
+		WriteRegOp(adapter, 0x208, 1, 0, 0x00000800);
+	}
+}
+
+static void DmaEnableDisableIrq(struct adapter *adapter, u32 flag1, u32 flag2, u32 flag3)
+{
+	adapter->dma_ctrl = adapter->dma_ctrl & 0x000F0000;
+
+	if (flag1 == 0) {
+		if (flag2 == 0)
+			adapter->dma_ctrl = adapter->dma_ctrl & ~0x00010000;
+		else
+			adapter->dma_ctrl = adapter->dma_ctrl | 0x00010000;
+
+		if (flag3 == 0)
+			adapter->dma_ctrl = adapter->dma_ctrl & ~0x00020000;
+		else
+			adapter->dma_ctrl = adapter->dma_ctrl | 0x00020000;
+
+	} else {
+
+		if (flag2 == 0)
+			adapter->dma_ctrl = adapter->dma_ctrl & ~0x00040000;
+		else
+			adapter->dma_ctrl = adapter->dma_ctrl | 0x00040000;
+
+		if (flag3 == 0)
+			adapter->dma_ctrl = adapter->dma_ctrl & ~0x00080000;
+		else
+			adapter->dma_ctrl = adapter->dma_ctrl | 0x00080000;
+	}
+}
+
+static void IrqDmaEnableDisableIrq(struct adapter * adapter, u32 op)
+{
+	u32 value;
+
+	value = ReadRegDW(adapter, 0x208) & 0xFFF0FFFF;
+
+	if (op != 0)
+		value = value | (adapter->dma_ctrl & 0x000F0000);
+
+	WriteRegDW(adapter, 0x208, value);
+}
+
+/* FlexCopII has 2 dma channels. DMA1 is used to transfer TS data to
+   system memory.
+
+   The DMA1 buffer is divided in 2 subbuffers of equal size.
+   FlexCopII will transfer TS data to one subbuffer, signal an interrupt
+   when the subbuffer is full and continue fillig the second subbuffer.
+
+   For DMA1:
+       subbuffer size in 32-bit words is stored in the first 24 bits of
+       register 0x004. The last 8 bits of register 0x004 contain the number
+       of subbuffers.
+       
+       the first 30 bits of register 0x000 contain the address of the first
+       subbuffer. The last 2 bits contain 0, when dma1 is disabled and 1,
+       when dma1 is enabled.
+
+       the first 30 bits of register 0x00C contain the address of the second
+       subbuffer. the last 2 bits contain 1.
+
+       register 0x008 will contain the address of the subbuffer that was filled
+       with TS data, when FlexCopII will generate an interrupt.
+
+   For DMA2:
+       subbuffer size in 32-bit words is stored in the first 24 bits of
+       register 0x014. The last 8 bits of register 0x014 contain the number
+       of subbuffers.
+       
+       the first 30 bits of register 0x010 contain the address of the first
+       subbuffer.  The last 2 bits contain 0, when dma1 is disabled and 1,
+       when dma1 is enabled.
+
+       the first 30 bits of register 0x01C contain the address of the second
+       subbuffer. the last 2 bits contain 1.
+
+       register 0x018 contains the address of the subbuffer that was filled
+       with TS data, when FlexCopII generates an interrupt.
+*/
+static int DmaInitDMA(struct adapter *adapter, u32 dma_channel)
+{
+	u32 subbuffers, subbufsize, subbuf0, subbuf1;
+
+	if (dma_channel == 0) {
+		dprintk("%s: Initializing DMA1 channel\n", __FUNCTION__);
+
+		subbuffers = 2;
+
+		subbufsize = (((adapter->dmaq1.buffer_size / 2) / 4) << 8) | subbuffers;
+
+		subbuf0 = adapter->dmaq1.bus_addr & 0xFFFFFFFC;
+
+		subbuf1 = ((adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) & 0xFFFFFFFC) | 1;
+
+		dprintk("%s: first subbuffer address = 0x%x\n", __FUNCTION__, subbuf0);
+		udelay(1000);
+		WriteRegDW(adapter, 0x000, subbuf0);
+
+		dprintk("%s: subbuffer size = 0x%x\n", __FUNCTION__, (subbufsize >> 8) * 4);
+		udelay(1000);
+		WriteRegDW(adapter, 0x004, subbufsize);
+
+		dprintk("%s: second subbuffer address = 0x%x\n", __FUNCTION__, subbuf1);
+		udelay(1000);
+		WriteRegDW(adapter, 0x00C, subbuf1);
+
+		dprintk("%s: counter = 0x%x\n", __FUNCTION__, adapter->dmaq1.bus_addr & 0xFFFFFFFC);
+		WriteRegDW(adapter, 0x008, adapter->dmaq1.bus_addr & 0xFFFFFFFC);
+		udelay(1000);
+
+		if (subbuffers == 0)
+			DmaEnableDisableIrq(adapter, 0, 1, 0);
+		else
+			DmaEnableDisableIrq(adapter, 0, 1, 1);
+
+		IrqDmaEnableDisableIrq(adapter, 1);
+
+		SRAMSetMediaDest(adapter, 1);
+		SRAMSetNetDest(adapter, 1);
+		SRAMSetCaiDest(adapter, 2);
+		SRAMSetCaoDest(adapter, 2);
+	}
+
+	if (dma_channel == 1) {
+		dprintk("%s: Initializing DMA2 channel\n", __FUNCTION__);
+
+		subbuffers = 2;
+
+		subbufsize = (((adapter->dmaq2.buffer_size / 2) / 4) << 8) | subbuffers;
+
+		subbuf0 = adapter->dmaq2.bus_addr & 0xFFFFFFFC;
+
+		subbuf1 = ((adapter->dmaq2.bus_addr + adapter->dmaq2.buffer_size / 2) & 0xFFFFFFFC) | 1;
+
+		dprintk("%s: first subbuffer address = 0x%x\n", __FUNCTION__, subbuf0);
+		udelay(1000);
+		WriteRegDW(adapter, 0x010, subbuf0);
+
+		dprintk("%s: subbuffer size = 0x%x\n", __FUNCTION__, (subbufsize >> 8) * 4);
+		udelay(1000);
+		WriteRegDW(adapter, 0x014, subbufsize);
+
+		dprintk("%s: second buffer address = 0x%x\n", __FUNCTION__, subbuf1);
+		udelay(1000);
+		WriteRegDW(adapter, 0x01C, subbuf1);
+
+		SRAMSetCaiDest(adapter, 2);
+	}
+
+	return 0;
+}
+
+static void CtrlEnableReceiveData(struct adapter *adapter, u32 op)
+{
+	if (op == 0) {
+		WriteRegOp(adapter, 0x208, 2, ~0x00008000, 0);
+
+		adapter->dma_status = adapter->dma_status & ~0x00000004;
+
+	} else {
+
+		WriteRegOp(adapter, 0x208, 1, 0, 0x00008000);
+
+		adapter->dma_status = adapter->dma_status | 0x00000004;
+	}
+}
+
+/* bit 0 of dma_mask is set to 1 if dma1 channel has to be enabled/disabled
+   bit 1 of dma_mask is set to 1 if dma2 channel has to be enabled/disabled
+*/
+static void DmaStartStop0x2102(struct adapter *adapter, u32 dma_mask, u32 start_stop)
+{
+	u32 dma_enable, dma1_enable, dma2_enable;
+
+	dprintk("%s: dma_mask=%x\n", __FUNCTION__, dma_mask);
+
+	if (start_stop == 1) {
+		dprintk("%s: starting dma\n", __FUNCTION__);
+
+		dma1_enable = 0;
+		dma2_enable = 0;
+
+		if (((dma_mask & 1) != 0) && ((adapter->dma_status & 1) == 0) && (adapter->dmaq1.bus_addr != 0)) {
+			adapter->dma_status = adapter->dma_status | 1;
+			dma1_enable = 1;
+		}
+
+		if (((dma_mask & 2) != 0) && ((adapter->dma_status & 2) == 0) && (adapter->dmaq2.bus_addr != 0)) {
+			adapter->dma_status = adapter->dma_status | 2;
+			dma2_enable = 1;
+		}
+		// enable dma1 and dma2
+		if ((dma1_enable == 1) && (dma2_enable == 1)) {
+			WriteRegDW(adapter, 0x000, adapter->dmaq1.bus_addr | 1);
+			WriteRegDW(adapter, 0x00C, (adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) | 1);
+			WriteRegDW(adapter, 0x010, adapter->dmaq2.bus_addr | 1);
+
+			CtrlEnableReceiveData(adapter, 1);
+
+			return;
+		}
+		// enable dma1
+		if ((dma1_enable == 1) && (dma2_enable == 0)) {
+			WriteRegDW(adapter, 0x000, adapter->dmaq1.bus_addr | 1);
+			WriteRegDW(adapter, 0x00C, (adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) | 1);
+
+			CtrlEnableReceiveData(adapter, 1);
+
+			return;
+		}
+		// enable dma2
+		if ((dma1_enable == 0) && (dma2_enable == 1)) {
+			WriteRegDW(adapter, 0x010, adapter->dmaq2.bus_addr | 1);
+
+			CtrlEnableReceiveData(adapter, 1);
+
+			return;
+		}
+		// start dma
+		if ((dma1_enable == 0) && (dma2_enable == 0)) {
+			CtrlEnableReceiveData(adapter, 1);
+
+			return;
+		}
+
+	} else {
+
+		dprintk("%s: stoping dma\n", __FUNCTION__);
+
+		dma_enable = adapter->dma_status & 0x00000003;
+
+		if (((dma_mask & 1) != 0) && ((adapter->dma_status & 1) != 0)) {
+			dma_enable = dma_enable & 0xFFFFFFFE;
+		}
+
+		if (((dma_mask & 2) != 0) && ((adapter->dma_status & 2) != 0)) {
+			dma_enable = dma_enable & 0xFFFFFFFD;
+		}
+		//stop dma
+		if ((dma_enable == 0) && ((adapter->dma_status & 4) != 0)) {
+			CtrlEnableReceiveData(adapter, 0);
+
+			udelay(3000);
+		}
+		//disable dma1
+		if (((dma_mask & 1) != 0) && ((adapter->dma_status & 1) != 0) && (adapter->dmaq1.bus_addr != 0)) {
+			WriteRegDW(adapter, 0x000, adapter->dmaq1.bus_addr);
+			WriteRegDW(adapter, 0x00C, (adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) | 1);
+
+			adapter->dma_status = adapter->dma_status & ~0x00000001;
+		}
+		//disable dma2
+		if (((dma_mask & 2) != 0) && ((adapter->dma_status & 2) != 0) && (adapter->dmaq2.bus_addr != 0)) {
+			WriteRegDW(adapter, 0x010, adapter->dmaq2.bus_addr);
+
+			adapter->dma_status = adapter->dma_status & ~0x00000002;
+		}
+	}
+}
+
+static void OpenStream(struct adapter *adapter, u32 pid)
+{
+	u32 dma_mask;
+
+	if (adapter->capturing == 0)
+		adapter->capturing = 1;
+
+	FilterEnableMaskFilter(adapter, 1);
+
+	AddPID(adapter, pid);
+
+	dprintk("%s: adapter->dma_status=%x\n", __FUNCTION__, adapter->dma_status);
+
+	if ((adapter->dma_status & 7) != 7) {
+		dma_mask = 0;
+
+		if (((adapter->dma_status & 0x10000000) != 0) && ((adapter->dma_status & 1) == 0)) {
+			dma_mask = dma_mask | 1;
+
+			adapter->dmaq1.head = 0;
+			adapter->dmaq1.tail = 0;
+
+			memset(adapter->dmaq1.buffer, 0, adapter->dmaq1.buffer_size);
+		}
+
+		if (((adapter->dma_status & 0x20000000) != 0) && ((adapter->dma_status & 2) == 0)) {
+			dma_mask = dma_mask | 2;
+
+			adapter->dmaq2.head = 0;
+			adapter->dmaq2.tail = 0;
+		}
+
+		if (dma_mask != 0) {
+			IrqDmaEnableDisableIrq(adapter, 1);
+
+			DmaStartStop0x2102(adapter, dma_mask, 1);
+		}
+	}
+}
+
+static void CloseStream(struct adapter *adapter, u32 pid)
+{
+	u32 dma_mask;
+
+	if (adapter->capturing != 0)
+		adapter->capturing = 0;
+
+	dprintk("%s: dma_status=%x\n", __FUNCTION__, adapter->dma_status);
+
+	dma_mask = 0;
+
+	if ((adapter->dma_status & 1) != 0)
+		dma_mask = dma_mask | 0x00000001;
+	if ((adapter->dma_status & 2) != 0)
+		dma_mask = dma_mask | 0x00000002;
+
+	if (dma_mask != 0) {
+		DmaStartStop0x2102(adapter, dma_mask, 0);
+	}
+
+	RemovePID(adapter, pid);
+}
+
+static void InterruptServiceDMA1(struct adapter *adapter)
+{
+	struct dvb_demux *dvbdmx = &adapter->demux;
+	struct packet_header packet_header;
+
+	int nCurDmaCounter;
+	u32 nNumBytesParsed;
+	u32 nNumNewBytesTransferred;
+	u32 dwDefaultPacketSize = 188;
+	u8 gbTmpBuffer[188];
+	u8 *pbDMABufCurPos;
+
+	nCurDmaCounter = readl(adapter->io_mem + 0x008) - adapter->dmaq1.bus_addr;
+	nCurDmaCounter = (nCurDmaCounter / dwDefaultPacketSize) * dwDefaultPacketSize;
+
+	if ((nCurDmaCounter < 0) || (nCurDmaCounter > adapter->dmaq1.buffer_size)) {
+		dprintk("%s: dma counter outside dma buffer\n", __FUNCTION__);
+		return;
+	}
+
+	adapter->dmaq1.head = nCurDmaCounter;
+
+	if (adapter->dmaq1.tail <= nCurDmaCounter) {
+		nNumNewBytesTransferred = nCurDmaCounter - adapter->dmaq1.tail;
+
+	} else {
+
+		nNumNewBytesTransferred = (adapter->dmaq1.buffer_size - adapter->dmaq1.tail) + nCurDmaCounter;
+	}
+
+//  dprintk("%s: nCurDmaCounter   = %d\n" , __FUNCTION__, nCurDmaCounter);
+//	dprintk("%s: dmaq1.tail       = %d\n" , __FUNCTION__, adapter->dmaq1.tail):
+//  dprintk("%s: BytesTransferred = %d\n" , __FUNCTION__, nNumNewBytesTransferred);
+
+	if (nNumNewBytesTransferred < dwDefaultPacketSize)
+		return;
+
+	nNumBytesParsed = 0;
+
+	while (nNumBytesParsed < nNumNewBytesTransferred) {
+		pbDMABufCurPos = adapter->dmaq1.buffer + adapter->dmaq1.tail;
+
+		if (adapter->dmaq1.buffer + adapter->dmaq1.buffer_size < adapter->dmaq1.buffer + adapter->dmaq1.tail + 188) {
+			memcpy(gbTmpBuffer, adapter->dmaq1.buffer + adapter->dmaq1.tail, adapter->dmaq1.buffer_size - adapter->dmaq1.tail);
+			memcpy(gbTmpBuffer + (adapter->dmaq1.buffer_size - adapter->dmaq1.tail), adapter->dmaq1.buffer, (188 - (adapter->dmaq1.buffer_size - adapter->dmaq1.tail)));
+
+			pbDMABufCurPos = gbTmpBuffer;
+		}
+
+		if (adapter->capturing != 0) {
+			u32 *dq = (u32 *) pbDMABufCurPos;
+
+			packet_header.sync_byte = *dq & 0x000000FF;
+			packet_header.transport_error_indicator = *dq & 0x00008000;
+			packet_header.payload_unit_start_indicator = *dq & 0x00004000;
+			packet_header.transport_priority = *dq & 0x00002000;
+			packet_header.pid = ((*dq & 0x00FF0000) >> 0x10) | (*dq & 0x00001F00);
+			packet_header.transport_scrambling_control = *dq >> 0x1E;
+			packet_header.adaptation_field_control = (*dq & 0x30000000) >> 0x1C;
+			packet_header.continuity_counter = (*dq & 0x0F000000) >> 0x18;
+
+			if ((packet_header.sync_byte == 0x47) && (packet_header.transport_error_indicator == 0) && (packet_header.pid != 0x1FFF)) {
+				if (CheckPID(adapter, packet_header.pid & 0x0000FFFF) != 0) {
+					dvb_dmx_swfilter_packets(dvbdmx, pbDMABufCurPos, dwDefaultPacketSize / 188);
+
+				} else {
+
+//                  dprintk("%s: pid=%x\n", __FUNCTION__, packet_header.pid);
+				}
+			}
+		}
+
+		nNumBytesParsed = nNumBytesParsed + dwDefaultPacketSize;
+
+		adapter->dmaq1.tail = adapter->dmaq1.tail + dwDefaultPacketSize;
+
+		if (adapter->dmaq1.tail >= adapter->dmaq1.buffer_size)
+			adapter->dmaq1.tail = adapter->dmaq1.tail - adapter->dmaq1.buffer_size;
+	};
+}
+
+static void InterruptServiceDMA2(struct adapter *adapter)
+{
+	printk("%s:\n", __FUNCTION__);
+}
+
+static irqreturn_t isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct adapter *tmp = dev_id;
+
+	u32 value;
+
+//  dprintk("%s:\n", __FUNCTION__);
+
+	spin_lock_irq(&tmp->lock);
+
+	if (0 == ((value = ReadRegDW(tmp, 0x20C)) & 0x0F)) {
+		spin_unlock_irq(&tmp->lock);
+		return IRQ_NONE;
+	}
+	
+	while (value != 0) {
+		if ((value & 0x03) != 0)
+			InterruptServiceDMA1(tmp);
+		if ((value & 0x0C) != 0)
+			InterruptServiceDMA2(tmp);
+		value = ReadRegDW(tmp, 0x20C) & 0x0F;
+	}
+
+	spin_unlock_irq(&tmp->lock);
+	return IRQ_HANDLED;
+}
+
+static void Initdmaqueue(struct adapter *adapter)
+{
+	dma_addr_t dma_addr;
+
+	if (adapter->dmaq1.buffer != 0)
+		return;
+
+	adapter->dmaq1.head = 0;
+	adapter->dmaq1.tail = 0;
+	adapter->dmaq1.buffer = 0;
+
+	adapter->dmaq1.buffer = pci_alloc_consistent(adapter->pdev, SizeOfBufDMA1 + 0x80, &dma_addr);
+
+	if (adapter->dmaq1.buffer != 0) {
+		memset(adapter->dmaq1.buffer, 0, SizeOfBufDMA1);
+
+		adapter->dmaq1.bus_addr = dma_addr;
+		adapter->dmaq1.buffer_size = SizeOfBufDMA1;
+
+		DmaInitDMA(adapter, 0);
+
+		adapter->dma_status = adapter->dma_status | 0x10000000;
+
+		dprintk("%s: allocated dma buffer at 0x%x, length=%d\n", __FUNCTION__, (int) adapter->dmaq1.buffer, SizeOfBufDMA1);
+
+	} else {
+
+		adapter->dma_status = adapter->dma_status & ~0x10000000;
+	}
+
+	if (adapter->dmaq2.buffer != 0)
+		return;
+
+	adapter->dmaq2.head = 0;
+	adapter->dmaq2.tail = 0;
+	adapter->dmaq2.buffer = 0;
+
+	adapter->dmaq2.buffer = pci_alloc_consistent(adapter->pdev, SizeOfBufDMA2 + 0x80, &dma_addr);
+
+	if (adapter->dmaq2.buffer != 0) {
+		memset(adapter->dmaq2.buffer, 0, SizeOfBufDMA2);
+
+		adapter->dmaq2.bus_addr = dma_addr;
+		adapter->dmaq2.buffer_size = SizeOfBufDMA2;
+
+		DmaInitDMA(adapter, 1);
+
+		adapter->dma_status = adapter->dma_status | 0x20000000;
+
+		dprintk("%s: allocated dma buffer at 0x%x, length=%d\n", __FUNCTION__, (int) adapter->dmaq2.buffer, (int) SizeOfBufDMA2);
+
+	} else {
+
+		adapter->dma_status = adapter->dma_status & ~0x20000000;
+	}
+}
+
+static void Freedmaqueue(struct adapter *adapter)
+{
+	if (adapter->dmaq1.buffer != 0) {
+		pci_free_consistent(adapter->pdev, SizeOfBufDMA1 + 0x80, adapter->dmaq1.buffer, adapter->dmaq1.bus_addr);
+
+		adapter->dmaq1.bus_addr = 0;
+		adapter->dmaq1.head = 0;
+		adapter->dmaq1.tail = 0;
+		adapter->dmaq1.buffer_size = 0;
+		adapter->dmaq1.buffer = 0;
+	}
+
+	if (adapter->dmaq2.buffer != 0) {
+		pci_free_consistent(adapter->pdev, SizeOfBufDMA2 + 0x80, adapter->dmaq2.buffer, adapter->dmaq2.bus_addr);
+
+		adapter->dmaq2.bus_addr = 0;
+		adapter->dmaq2.head = 0;
+		adapter->dmaq2.tail = 0;
+		adapter->dmaq2.buffer_size = 0;
+		adapter->dmaq2.buffer = 0;
+	}
+}
+
+static void FreeAdapterObject(struct adapter *adapter)
+{
+	dprintk("%s:\n", __FUNCTION__);
+
+	CloseStream(adapter, 0);
+
+	if (adapter->irq != 0)
+		free_irq(adapter->irq, adapter);
+
+	Freedmaqueue(adapter);
+
+	if (adapter->io_mem != 0)
+		iounmap((void *) adapter->io_mem);
+
+	if (adapter != 0)
+		kfree(adapter);
+}
+
+static struct pci_driver skystar2_pci_driver;
+
+static int ClaimAdapter(struct adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+
+	u16 var;
+
+	if (!request_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1), skystar2_pci_driver.name))
+		return -EBUSY;
+
+	if (!request_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0), skystar2_pci_driver.name))
+		return -EBUSY;
+
+	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &adapter->card_revision);
+
+	dprintk("%s: card revision %x \n", __FUNCTION__, adapter->card_revision);
+
+	if (pci_enable_device(pdev))
+		return -EIO;
+
+	pci_read_config_word(pdev, 4, &var);
+
+	if ((var & 4) == 0)
+		pci_set_master(pdev);
+
+	adapter->io_port = pdev->resource[1].start;
+
+	adapter->io_mem = (u32) ioremap(pdev->resource[0].start, 0x800);
+
+	if (adapter->io_mem == 0) {
+		dprintk("%s: can not map io memory\n", __FUNCTION__);
+
+		return 2;
+	}
+
+	dprintk("%s: io memory maped at %x\n", __FUNCTION__, adapter->io_mem);
+
+	return 1;
+}
+
+/*
+static int SLL_reset_FlexCOP(struct adapter *adapter)
+{
+	WriteRegDW(adapter, 0x208, 0);
+	WriteRegDW(adapter, 0x210, 0xB2FF);
+
+	return 0;
+}
+*/
+
+static int DriverInitialize(struct pci_dev * pdev)
+{
+	struct adapter *adapter;
+	u32 tmp;
+	u8 key[16];
+
+	if (!(adapter = kmalloc(sizeof(struct adapter), GFP_KERNEL))) {
+		dprintk("%s: out of memory!\n", __FUNCTION__);
+
+		return -ENOMEM;
+	}
+
+	memset(adapter, 0, sizeof(struct adapter));
+
+	pci_set_drvdata(pdev,adapter);
+
+	adapter->pdev = pdev;
+	adapter->irq = pdev->irq;
+
+	if ((ClaimAdapter(adapter)) != 1) {
+		FreeAdapterObject(adapter);
+
+		return -ENODEV;
+	}
+
+	IrqDmaEnableDisableIrq(adapter, 0);
+
+	if (request_irq(pdev->irq, isr, 0x4000000, "Skystar2", adapter) != 0) {
+		dprintk("%s: unable to allocate irq=%d !\n", __FUNCTION__, pdev->irq);
+
+		FreeAdapterObject(adapter);
+
+		return -ENODEV;
+	}
+
+	ReadRegDW(adapter, 0x208);
+	WriteRegDW(adapter, 0x208, 0);
+	WriteRegDW(adapter, 0x210, 0xB2FF);
+	WriteRegDW(adapter, 0x208, 0x40);
+
+	InitPIDsInfo(adapter);
+
+	PidSetGroupPID(adapter, 0);
+	PidSetGroupMASK(adapter, 0x1FE0);
+	PidSetStream1PID(adapter, 0x1FFF);
+	PidSetStream2PID(adapter, 0x1FFF);
+	PidSetPmtPID(adapter, 0x1FFF);
+	PidSetPcrPID(adapter, 0x1FFF);
+	PidSetEcmPID(adapter, 0x1FFF);
+	PidSetEmmPID(adapter, 0x1FFF);
+
+	Initdmaqueue(adapter);
+
+	if ((adapter->dma_status & 0x30000000) == 0) {
+		FreeAdapterObject(adapter);
+
+		return -ENODEV;
+	}
+
+	adapter->b2c2_revision = (ReadRegDW(adapter, 0x204) >> 0x18);
+
+	if ((adapter->b2c2_revision != 0x82) && (adapter->b2c2_revision != 0xC3))
+		if (adapter->b2c2_revision != 0x82) {
+			dprintk("%s: The revision of the FlexCopII chip on your card is - %d\n", __FUNCTION__, adapter->b2c2_revision);
+			dprintk("%s: This driver works now only with FlexCopII(rev.130) and FlexCopIIB(rev.195).\n", __FUNCTION__);
+
+			FreeAdapterObject(adapter);
+
+			return -ENODEV;
+		}
+
+	tmp = ReadRegDW(adapter, 0x204);
+
+	WriteRegDW(adapter, 0x204, 0);
+	mdelay(20);
+
+	WriteRegDW(adapter, 0x204, tmp);
+	mdelay(10);
+
+	tmp = ReadRegDW(adapter, 0x308);
+	WriteRegDW(adapter, 0x308, 0x4000 | tmp);
+
+	adapter->dwSramType = 0x10000;
+
+	SLL_detectSramSize(adapter);
+
+	dprintk("%s sram length = %d, sram type= %x\n", __FUNCTION__, SRAM_length(adapter), adapter->dwSramType);
+
+	SRAMSetMediaDest(adapter, 1);
+	SRAMSetNetDest(adapter, 1);
+
+	CtrlEnableSmc(adapter, 0);
+
+	SRAMSetCaiDest(adapter, 2);
+	SRAMSetCaoDest(adapter, 2);
+
+	DmaEnableDisableIrq(adapter, 1, 0, 0);
+
+	if (EEPROM_getMacAddr(adapter, 0, adapter->mac_addr) != 0) {
+		printk("%s MAC address = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x \n", __FUNCTION__, adapter->mac_addr[0], adapter->mac_addr[1], adapter->mac_addr[2], adapter->mac_addr[3], adapter->mac_addr[4], adapter->mac_addr[5], adapter->mac_addr[6], adapter->mac_addr[7]
+		    );
+
+		CASetMacDstAddrFilter(adapter, adapter->mac_addr);
+		CtrlEnableMAC(adapter, 1);
+	}
+
+	EEPROM_readKey(adapter, key, 16);
+
+	printk("%s key = \n %02x %02x %02x %02x \n %02x %02x %02x %02x \n %02x %02x %02x %02x \n %02x %02x %02x %02x \n", __FUNCTION__, key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7], key[8], key[9], key[10], key[11], key[12], key[13], key[14], key[15]);
+
+	adapter->lock = SPIN_LOCK_UNLOCKED;
+
+	return 0;
+}
+
+static void DriverHalt(struct pci_dev *pdev)
+{
+	struct adapter *adapter;
+
+	adapter = pci_get_drvdata(pdev);
+
+	IrqDmaEnableDisableIrq(adapter, 0);
+
+	CtrlEnableReceiveData(adapter, 0);
+
+	FreeAdapterObject(adapter);
+
+	pci_set_drvdata(pdev, NULL);
+
+	release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
+
+	release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
+}
+
+static int dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	struct adapter *adapter = (struct adapter *) dvbdmx->priv;
+
+	dprintk("%s: PID=%d, type=%d\n", __FUNCTION__, dvbdmxfeed->pid, dvbdmxfeed->type);
+
+	OpenStream(adapter, dvbdmxfeed->pid);
+
+	return 0;
+}
+
+static int dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	struct adapter *adapter = (struct adapter *) dvbdmx->priv;
+
+	dprintk("%s: PID=%d, type=%d\n", __FUNCTION__, dvbdmxfeed->pid, dvbdmxfeed->type);
+
+	CloseStream(adapter, dvbdmxfeed->pid);
+
+	return 0;
+}
+
+/* lnb control */
+static void set_tuner_tone(struct adapter *adapter, u8 tone)
+{
+	u16 wzHalfPeriodFor45MHz[] = { 0x01FF, 0x0154, 0x00FF, 0x00CC };
+	u16 ax;
+
+	dprintk("%s: %u\n", __FUNCTION__, tone);
+
+	switch (tone) {
+	case 1:
+		ax = wzHalfPeriodFor45MHz[0];
+		break;
+	case 2:
+		ax = wzHalfPeriodFor45MHz[1];
+		break;
+	case 3:
+		ax = wzHalfPeriodFor45MHz[2];
+		break;
+	case 4:
+		ax = wzHalfPeriodFor45MHz[3];
+		break;
+
+	default:
+		ax = 0;
+	}
+
+	if (ax != 0) {
+		WriteRegDW(adapter, 0x200, ((ax << 0x0F) + (ax & 0x7FFF)) | 0x40000000);
+
+	} else {
+
+		WriteRegDW(adapter, 0x200, 0x40FF8000);
+	}
+}
+
+static void set_tuner_polarity(struct adapter *adapter, u8 polarity)
+{
+	u32 var;
+
+	dprintk("%s : polarity = %u \n", __FUNCTION__, polarity);
+
+	var = ReadRegDW(adapter, 0x204);
+
+	if (polarity == 0) {
+		dprintk("%s: LNB power off\n", __FUNCTION__);
+		var = var | 1;
+	};
+
+	if (polarity == 1) {
+		var = var & ~1;
+		var = var & ~4;
+	};
+
+	if (polarity == 2) {
+		var = var & ~1;
+		var = var | 4;
+	}
+
+	WriteRegDW(adapter, 0x204, var);
+}
+
+static int flexcop_diseqc_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
+{
+	struct adapter *adapter = fe->before_after_data;
+
+	switch (cmd) {
+	case FE_SLEEP:
+		{
+			printk("%s: FE_SLEEP\n", __FUNCTION__);
+
+			set_tuner_polarity(adapter, 0);
+
+			// return -EOPNOTSUPP, to make DVB core also send "FE_SLEEP" command to frontend.
+			return -EOPNOTSUPP;
+		}
+
+	case FE_SET_VOLTAGE:
+		{
+			dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__);
+
+			switch ((fe_sec_voltage_t) arg) {
+			case SEC_VOLTAGE_13:
+
+				printk("%s: SEC_VOLTAGE_13, %x\n", __FUNCTION__, SEC_VOLTAGE_13);
+
+				set_tuner_polarity(adapter, 1);
+
+				break;
+
+			case SEC_VOLTAGE_18:
+
+				printk("%s: SEC_VOLTAGE_18, %x\n", __FUNCTION__, SEC_VOLTAGE_18);
+
+				set_tuner_polarity(adapter, 2);
+
+				break;
+
+			default:
+
+				return -EINVAL;
+			};
+
+			break;
+		}
+
+	case FE_SET_TONE:
+		{
+			dprintk("%s: FE_SET_TONE\n", __FUNCTION__);
+
+			switch ((fe_sec_tone_mode_t) arg) {
+			case SEC_TONE_ON:
+
+				printk("%s: SEC_TONE_ON, %x\n", __FUNCTION__, SEC_TONE_ON);
+
+				set_tuner_tone(adapter, 1);
+
+				break;
+
+			case SEC_TONE_OFF:
+
+				printk("%s: SEC_TONE_OFF, %x\n", __FUNCTION__, SEC_TONE_OFF);
+
+				set_tuner_tone(adapter, 0);
+
+				break;
+
+			default:
+
+				return -EINVAL;
+			};
+
+			break;
+		}
+
+	default:
+
+		return -EOPNOTSUPP;
+	};
+
+	return 0;
+}
+
+static int skystar2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct adapter *adapter;
+	struct dvb_adapter *dvb_adapter;
+	struct dvb_demux *dvbdemux;
+
+	int ret;
+
+	if (pdev == NULL)
+		return -ENODEV;
+
+	if (DriverInitialize(pdev) != 0)
+		return -ENODEV;
+
+	dvb_register_adapter(&dvb_adapter, skystar2_pci_driver.name);
+
+	if (dvb_adapter == NULL) {
+		printk("%s: Error registering DVB adapter\n", __FUNCTION__);
+
+		DriverHalt(pdev);
+
+		return -ENODEV;
+	}
+
+	adapter = (struct adapter *) pci_get_drvdata(pdev);
+
+	adapter->dvb_adapter = dvb_adapter;
+
+	init_MUTEX(&adapter->i2c_sem);
+
+	adapter->i2c_bus = dvb_register_i2c_bus(master_xfer, adapter, adapter->dvb_adapter, 0);
+
+	if (!adapter->i2c_bus)
+		return -ENOMEM;
+
+	dvb_add_frontend_ioctls(adapter->dvb_adapter, flexcop_diseqc_ioctl, NULL, adapter);
+
+	dvbdemux = &adapter->demux;
+
+	dvbdemux->priv = (void *) adapter;
+	dvbdemux->filternum = 32;
+	dvbdemux->feednum = 32;
+	dvbdemux->start_feed = dvb_start_feed;
+	dvbdemux->stop_feed = dvb_stop_feed;
+	dvbdemux->write_to_decoder = 0;
+	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
+
+	dvb_dmx_init(&adapter->demux);
+
+	adapter->hw_frontend.source = DMX_FRONTEND_0;
+
+	adapter->dmxdev.filternum = 32;
+	adapter->dmxdev.demux = &dvbdemux->dmx;
+	adapter->dmxdev.capabilities = 0;
+
+	dvb_dmxdev_init(&adapter->dmxdev, adapter->dvb_adapter);
+
+	ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &adapter->hw_frontend);
+	if (ret < 0)
+		return ret;
+
+	adapter->mem_frontend.source = DMX_MEMORY_FE;
+
+	ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &adapter->mem_frontend);
+	if (ret < 0)
+		return ret;
+
+	ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, &adapter->hw_frontend);
+	if (ret < 0)
+		return ret;
+
+	dvb_net_init(adapter->dvb_adapter, &adapter->dvbnet, &dvbdemux->dmx);
+	return 0;
+}
+
+static void skystar2_remove(struct pci_dev *pdev)
+{
+	struct adapter *adapter;
+	struct dvb_demux *dvbdemux;
+
+	if (pdev == NULL)
+		return;
+
+	adapter = pci_get_drvdata(pdev);
+
+	if (adapter != NULL) {
+		dvb_net_release(&adapter->dvbnet);
+		dvbdemux = &adapter->demux;
+
+		dvbdemux->dmx.close(&dvbdemux->dmx);
+		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &adapter->hw_frontend);
+		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &adapter->mem_frontend);
+
+		dvb_dmxdev_release(&adapter->dmxdev);
+		dvb_dmx_release(&adapter->demux);
+
+		if (adapter->dvb_adapter != NULL) {
+			dvb_remove_frontend_ioctls(adapter->dvb_adapter, flexcop_diseqc_ioctl, NULL);
+
+			if (adapter->i2c_bus != NULL)
+				dvb_unregister_i2c_bus(master_xfer, adapter->i2c_bus->adapter, adapter->i2c_bus->id);
+
+			dvb_unregister_adapter(adapter->dvb_adapter);
+		}
+
+		DriverHalt(pdev);
+	}
+}
+
+static struct pci_device_id skystar2_pci_tbl[] = {
+	{0x000013D0, 0x00002103, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000},
+	{0,},
+};
+
+static struct pci_driver skystar2_pci_driver = {
+	.name = "Technisat SkyStar2 driver",
+	.id_table = skystar2_pci_tbl,
+	.probe = skystar2_probe,
+	.remove = skystar2_remove,
+};
+
+static int skystar2_init(void)
+{
+	return pci_module_init(&skystar2_pci_driver);
+}
+
+static void skystar2_cleanup(void)
+{
+	pci_unregister_driver(&skystar2_pci_driver);
+}
+
+module_init(skystar2_init);
+module_exit(skystar2_cleanup);
+
+MODULE_DESCRIPTION("Technisat SkyStar2 DVB PCI Driver");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
--- a/drivers/media/dvb/dvb-core/dvb_demux.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c	Sat Jul 19 12:54:23 2003
@@ -403,13 +403,16 @@
 {
 	int p = 0,i, j;
 	
+	spin_lock(&demux->lock);
+
 	if ((i = demux->tsbufp)) {
 		if (count < (j=188-i)) {
 			memcpy(&demux->tsbuf[i], buf, count);
 			demux->tsbufp += count;
-			return;
+			goto bailout;
 		}
 		memcpy(&demux->tsbuf[i], buf, j);
+		if (demux->tsbuf[0] == 0x47)
 		dvb_dmx_swfilter_packet(demux, demux->tsbuf);
 		demux->tsbufp = 0;
 		p += j;
@@ -424,11 +427,14 @@
 				i = count-p;
 				memcpy(demux->tsbuf, buf+p, i);
 				demux->tsbufp=i;
-				return;
+				goto bailout;
 			}
 		} else 
 			p++;
 	}
+
+bailout:
+	spin_unlock(&demux->lock);
 }
 
 
@@ -1030,9 +1036,11 @@
 
 	if (down_interruptible (&dvbdemux->mutex))
 		return -ERESTARTSYS;
-
 	dvb_dmx_swfilter(dvbdemux, buf, count);
 	up(&dvbdemux->mutex);
+
+	if (signal_pending(current))
+		return -EINTR;
 	return count;
 }
 
@@ -1110,8 +1118,8 @@
 	return 0;
 }
 
-int 
-dvb_dmx_init(struct dvb_demux *dvbdemux)
+
+int dvb_dmx_init(struct dvb_demux *dvbdemux)
 {
 	int i, err;
 	struct dmx_demux *dmx = &dvbdemux->dmx;
@@ -1181,8 +1189,8 @@
 	return 0;
 }
 
-int 
-dvb_dmx_release(struct dvb_demux *dvbdemux)
+
+int dvb_dmx_release(struct dvb_demux *dvbdemux)
 {
 	struct dmx_demux *dmx = &dvbdemux->dmx;
 
diff -Nru a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c	Sat Jul 19 12:54:23 2003
@@ -263,8 +263,14 @@
                 if (flags & O_NONBLOCK)
                         return -EWOULDBLOCK;
 
+		up(&fe->sem);
+
                 ret = wait_event_interruptible (events->wait_queue,
                                                 events->eventw != events->eventr);
+
+        	if (down_interruptible (&fe->sem))
+			return -ERESTARTSYS;
+
                 if (ret < 0)
                         return ret;
         }
diff -Nru a/drivers/media/dvb/dvb-core/dvb_functions.c b/drivers/media/dvb/dvb-core/dvb_functions.c
--- a/drivers/media/dvb/dvb-core/dvb_functions.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/media/dvb/dvb-core/dvb_functions.c	Sat Jul 19 12:54:27 2003
@@ -1,11 +1,11 @@
 #include <linux/version.h>
-#include <linux/string.h>
-#include <linux/smp_lock.h>
-#include <linux/fs.h>
 #include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/string.h>
 #include <linux/module.h>
 #include <linux/ioctl.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 
 void dvb_kernel_thread_setup (const char *thread_name)
diff -Nru a/drivers/media/dvb/dvb-core/dvb_functions.h b/drivers/media/dvb/dvb-core/dvb_functions.h
--- a/drivers/media/dvb/dvb-core/dvb_functions.h	Sat Jul 19 12:54:25 2003
+++ b/drivers/media/dvb/dvb-core/dvb_functions.h	Sat Jul 19 12:54:25 2003
@@ -1,6 +1,8 @@
 #ifndef __DVB_FUNCTIONS_H__
 #define __DVB_FUNCTIONS_H__
 
+#include <linux/version.h>
+
 /**
  *  a sleeping delay function, waits i ms
  *
diff -Nru a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
--- a/drivers/media/dvb/dvb-core/dvb_net.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/media/dvb/dvb-core/dvb_net.c	Sat Jul 19 12:54:23 2003
@@ -24,22 +24,25 @@
  * 
  */
 
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ioctl.h>
-#include <linux/slab.h>
-#include <asm/uaccess.h>
-
 #include <linux/dvb/net.h>
+#include <asm/uaccess.h>
 
 #include "dvb_demux.h"
 #include "dvb_net.h"
 #include "dvb_functions.h"
 
+
+#if 1
+#define dprintk(x...) printk(x)
+#else
+#define dprintk(x...)
+#endif
+
+
 #define DVB_NET_MULTICAST_MAX 10
 
 struct dvb_net_priv {
+	int in_use;
         struct net_device_stats stats;
         char name[6];
 	u16 pid;
@@ -49,10 +52,17 @@
 	int multi_num;
 	struct dmx_section_filter *multi_secfilter[DVB_NET_MULTICAST_MAX];
 	unsigned char multi_macs[DVB_NET_MULTICAST_MAX][6];
-	int mode;
+	int rx_mode;
+#define RX_MODE_UNI 0
+#define RX_MODE_MULTI 1
+#define RX_MODE_ALL_MULTI 2
+#define RX_MODE_PROMISC 3
+	struct work_struct set_multicast_list_wq;
+	struct work_struct restart_net_feed_wq;
 };
 
-/*
+
+/**
  *	Determine the packet's protocol ID. The rule here is that we 
  *	assume 802.3 if the type field is short enough to be a length.
  *	This is normal practice and works for any 'now in use' protocol.
@@ -60,8 +70,8 @@
  *  stolen from eth.c out of the linux kernel, hacked for dvb-device
  *  by Michael Holzt <kju@debian.org>
  */
- 
-unsigned short my_eth_type_trans(struct sk_buff *skb, struct net_device *dev)
+static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,
+				      struct net_device *dev)
 {
 	struct ethhdr *eth;
 	unsigned char *rawp;
@@ -70,8 +80,7 @@
 	skb_pull(skb,dev->hard_header_len);
 	eth= skb->mac.ethernet;
 	
-	if(*eth->h_dest&1)
-	{
+	if (*eth->h_dest & 1) {
 		if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
 			skb->pkt_type=PACKET_BROADCAST;
 		else
@@ -83,7 +92,7 @@
 		
 	rawp = skb->data;
 	
-	/*
+	/**
 	 *	This is a magic hack to spot IPX packets. Older Novell breaks
 	 *	the protocol design and runs IPX over 802.3 without an 802.2 LLC
 	 *	layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
@@ -92,42 +101,73 @@
 	if (*(unsigned short *)rawp == 0xFFFF)
 		return htons(ETH_P_802_3);
 		
-	/*
+	/**
 	 *	Real 802.2 LLC
 	 */
 	return htons(ETH_P_802_2);
 }
 
-static void dvb_net_sec(struct net_device *dev, const u8 *pkt, int pkt_len)
+
+static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len)
 {
         u8 *eth;
         struct sk_buff *skb;
 
-        if (pkt_len<13) {
-                printk("%s: IP/MPE packet length = %d too small.\n", dev->name, pkt_len);
+	/* note: pkt_len includes a 32bit checksum */
+	if (pkt_len < 16) {
+		printk("%s: IP/MPE packet length = %d too small.\n",
+			dev->name, pkt_len);
+		((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
+		((struct dvb_net_priv *) dev->priv)->stats.rx_length_errors++;
+		return;
+	}
+	if ((pkt[5] & 0xfd) != 0xc1) {
+		/* drop scrambled or broken packets */
+		((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
+		((struct dvb_net_priv *) dev->priv)->stats.rx_crc_errors++;
 		return;
 	}
-        skb = dev_alloc_skb(pkt_len+2);
-        if (skb == NULL) {
-                printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
-                       dev->name);
+	if (pkt[5] & 0x02) {
+		//FIXME: handle LLC/SNAP
                 ((struct dvb_net_priv *)dev->priv)->stats.rx_dropped++;
                 return;
         }
-        eth=(u8 *) skb_put(skb, pkt_len+2);
-        memcpy(eth+14, (void*)pkt+12, pkt_len-12);
+	if (pkt[7]) {
+		/* FIXME: assemble datagram from multiple sections */
+		((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
+		((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++;
+		return;
+	}
 
+	/* we have 14 byte ethernet header (ip header follows);
+	 * 12 byte MPE header; 4 byte checksum; + 2 byte alignment
+	 */
+	if (!(skb = dev_alloc_skb(pkt_len - 4 - 12 + 14 + 2))) {
+		//printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
+		((struct dvb_net_priv *) dev->priv)->stats.rx_dropped++;
+		return;
+	}
+	skb_reserve(skb, 2);    /* longword align L3 header */
+	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);
+
+	/* create ethernet header: */
         eth[0]=pkt[0x0b];
         eth[1]=pkt[0x0a];
         eth[2]=pkt[0x09];
         eth[3]=pkt[0x08];
         eth[4]=pkt[0x04];
         eth[5]=pkt[0x03];
+
         eth[6]=eth[7]=eth[8]=eth[9]=eth[10]=eth[11]=0;
-        eth[12]=0x08; eth[13]=0x00;
 
-	skb->protocol=my_eth_type_trans(skb,dev);
-        skb->dev=dev;
+	eth[12] = 0x08;	/* ETH_P_IP */
+	eth[13] = 0x00;
+
+	skb->protocol = dvb_net_eth_type_trans(skb, dev);
         
         ((struct dvb_net_priv *)dev->priv)->stats.rx_packets++;
         ((struct dvb_net_priv *)dev->priv)->stats.rx_bytes+=skb->len;
@@ -141,9 +181,11 @@
 {
         struct net_device *dev=(struct net_device *) filter->priv;
 
-	/* FIXME: this only works if exactly one complete section is
-	          delivered in buffer1 only */
-	dvb_net_sec(dev, buffer1, buffer1_len);
+	/**
+	 * we rely on the DVB API definition where exactly one complete
+	 * section is delivered in buffer1
+	 */
+	dvb_net_sec (dev, (u8*) buffer1, buffer1_len);
 	return 0;
 }
 
@@ -178,24 +220,27 @@
 	memset((*secfilter)->filter_mode,  0xff, DMX_MAX_FILTER_SIZE);
 
 	(*secfilter)->filter_value[0]=0x3e;
-	(*secfilter)->filter_mask[0]=0xff;
-
 	(*secfilter)->filter_value[3]=mac[5];
-	(*secfilter)->filter_mask[3]=mac_mask[5];
 	(*secfilter)->filter_value[4]=mac[4];
-	(*secfilter)->filter_mask[4]=mac_mask[4];
 	(*secfilter)->filter_value[8]=mac[3];
-	(*secfilter)->filter_mask[8]=mac_mask[3];
 	(*secfilter)->filter_value[9]=mac[2];
-	(*secfilter)->filter_mask[9]=mac_mask[2];
-
 	(*secfilter)->filter_value[10]=mac[1];
-	(*secfilter)->filter_mask[10]=mac_mask[1];
 	(*secfilter)->filter_value[11]=mac[0];
+
+	(*secfilter)->filter_mask[0] = 0xff;
+	(*secfilter)->filter_mask[3] = mac_mask[5];
+	(*secfilter)->filter_mask[4] = mac_mask[4];
+	(*secfilter)->filter_mask[8] = mac_mask[3];
+	(*secfilter)->filter_mask[9] = mac_mask[2];
+	(*secfilter)->filter_mask[10] = mac_mask[1];
 	(*secfilter)->filter_mask[11]=mac_mask[0];
 
-	printk("%s: filter mac=%02x %02x %02x %02x %02x %02x\n", 
+	dprintk("%s: filter mac=%02x %02x %02x %02x %02x %02x\n",
 	       dev->name, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+	dprintk("%s: filter mask=%02x %02x %02x %02x %02x %02x\n",
+	       dev->name, mac_mask[0], mac_mask[1], mac_mask[2],
+	       mac_mask[3], mac_mask[4], mac_mask[5]);
+
 	return 0;
 }
 
@@ -206,46 +251,57 @@
         struct dmx_demux *demux = priv->demux;
         unsigned char *mac = (unsigned char *) dev->dev_addr;
 		
+	dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode);
+	if (priv->secfeed || priv->secfilter || priv->multi_secfilter[0])
+		printk("%s: BUG %d\n", __FUNCTION__, __LINE__);
+
 	priv->secfeed=0;
 	priv->secfilter=0;
 
+	dprintk("%s: alloc secfeed\n", __FUNCTION__);
 	ret=demux->allocate_section_feed(demux, &priv->secfeed, 
 					 dvb_net_callback);
 	if (ret<0) {
-		printk("%s: could not get section feed\n", dev->name);
+		printk("%s: could not allocate section feed\n", dev->name);
 		return ret;
 	}
 
-	ret=priv->secfeed->set(priv->secfeed, priv->pid, 32768, 0, 0);
+	ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 0, 1);
+
 	if (ret<0) {
 		printk("%s: could not set section feed\n", dev->name);
-		priv->demux->
-		        release_section_feed(priv->demux, priv->secfeed);
+		priv->demux->release_section_feed(priv->demux, priv->secfeed);
 		priv->secfeed=0;
 		return ret;
 	}
-	/* fixme: is this correct? */
-	try_module_get(THIS_MODULE);
 
-	if (priv->mode<3) 
+	if (priv->rx_mode != RX_MODE_PROMISC) {
+		dprintk("%s: set secfilter\n", __FUNCTION__);
 		dvb_net_filter_set(dev, &priv->secfilter, mac, mask_normal);
+	}
 
-	switch (priv->mode) {
-	case 1:
-		for (i=0; i<priv->multi_num; i++) 
+	switch (priv->rx_mode) {
+	case RX_MODE_MULTI:
+		for (i = 0; i < priv->multi_num; i++) {
+			dprintk("%s: set multi_secfilter[%d]\n", __FUNCTION__, i);
 			dvb_net_filter_set(dev, &priv->multi_secfilter[i],
 					   priv->multi_macs[i], mask_normal);
+		}
 		break;
-	case 2:
+	case RX_MODE_ALL_MULTI:
 		priv->multi_num=1;
-		dvb_net_filter_set(dev, &priv->multi_secfilter[0], mac_allmulti, mask_allmulti);
+		dprintk("%s: set multi_secfilter[0]\n", __FUNCTION__);
+		dvb_net_filter_set(dev, &priv->multi_secfilter[0],
+				   mac_allmulti, mask_allmulti);
 		break;
-	case 3:
+	case RX_MODE_PROMISC:
 		priv->multi_num=0;
+		dprintk("%s: set secfilter\n", __FUNCTION__);
 		dvb_net_filter_set(dev, &priv->secfilter, mac, mask_promisc);
 		break;
 	}
 	
+	dprintk("%s: start filtering\n", __FUNCTION__);
 	priv->secfeed->start_filtering(priv->secfeed);
 	return 0;
 }
@@ -255,89 +311,93 @@
 	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
 	int i;
 
+	dprintk("%s\n", __FUNCTION__);
         if (priv->secfeed) {
-	        if (priv->secfeed->is_filtering)
+		if (priv->secfeed->is_filtering) {
+			dprintk("%s: stop secfeed\n", __FUNCTION__);
 		        priv->secfeed->stop_filtering(priv->secfeed);
-	        if (priv->secfilter)
-		        priv->secfeed->
-			        release_filter(priv->secfeed, 
+		}
+
+		if (priv->secfilter) {
+			dprintk("%s: release secfilter\n", __FUNCTION__);
+			priv->secfeed->release_filter(priv->secfeed,
 					       priv->secfilter);
 		priv->secfilter=0;
+		}
 
 		for (i=0; i<priv->multi_num; i++) {
-			if (priv->multi_secfilter[i])
-				priv->secfeed->
-					release_filter(priv->secfeed, 
+			if (priv->multi_secfilter[i]) {
+				dprintk("%s: release multi_filter[%d]\n", __FUNCTION__, i);
+				priv->secfeed->release_filter(priv->secfeed,
 						       priv->multi_secfilter[i]);
 			priv->multi_secfilter[i]=0;
 		}
-		priv->demux->
-		        release_section_feed(priv->demux, priv->secfeed);
+		}
+
+		priv->demux->release_section_feed(priv->demux, priv->secfeed);
 		priv->secfeed=0;
-		/* fixme: is this correct? */
-		module_put(THIS_MODULE);
 	} else
 		printk("%s: no feed to stop\n", dev->name);
 }
 
-static int dvb_add_mc_filter(struct net_device *dev, struct dev_mc_list *mc)
+
+static int dvb_set_mc_filter (struct net_device *dev, struct dev_mc_list *mc)
 {
 	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
-	int ret;
 
-	if (priv->multi_num >= DVB_NET_MULTICAST_MAX)
+	if (priv->multi_num == DVB_NET_MULTICAST_MAX)
 		return -ENOMEM;
 
-	ret = memcmp(priv->multi_macs[priv->multi_num], mc->dmi_addr, 6);
 	memcpy(priv->multi_macs[priv->multi_num], mc->dmi_addr, 6);
 
 	priv->multi_num++;
-
-	return ret;
+	return 0;
 }
 
-static void dvb_net_set_multi(struct net_device *dev)
+
+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 dev_mc_list *mc;
-	int mci;
-	int update = 0;
+
+	dvb_net_feed_stop(dev);
+
+	priv->rx_mode = RX_MODE_UNI;
 	
 	if(dev->flags & IFF_PROMISC) {
-//	printk("%s: promiscuous mode\n", dev->name);
-		if(priv->mode != 3)
-			update = 1;
-		priv->mode = 3;
-	} else if(dev->flags & IFF_ALLMULTI) {
-//	printk("%s: allmulti mode\n", dev->name);
-		if(priv->mode != 2)
-			update = 1;
-		priv->mode = 2;
-	} else if(dev->mc_count > 0) {
-//	printk("%s: set_mc_list, %d entries\n", 
-//	       dev->name, dev->mc_count);
-		if(priv->mode != 1)
-			update = 1;
-		priv->mode = 1;
+		dprintk("%s: promiscuous mode\n", dev->name);
+		priv->rx_mode = RX_MODE_PROMISC;
+	} else if ((dev->flags & IFF_ALLMULTI)) {
+		dprintk("%s: allmulti mode\n", dev->name);
+		priv->rx_mode = RX_MODE_ALL_MULTI;
+	} else if (dev->mc_count) {
+		int mci;
+		struct dev_mc_list *mc;
+
+		dprintk("%s: set_mc_list, %d entries\n",
+			dev->name, dev->mc_count);
+
+		priv->rx_mode = RX_MODE_MULTI;
 		priv->multi_num = 0;
+
 		for (mci = 0, mc=dev->mc_list; 
 		     mci < dev->mc_count;
-		     mc=mc->next, mci++)
-			if(dvb_add_mc_filter(dev, mc) != 0)
-				update = 1;
-	} else {
-		if(priv->mode != 0)
-			update = 1;
-		priv->mode = 0;
+		     mc = mc->next, mci++) {
+			dvb_set_mc_filter(dev, mc);
+		}
 	}
 
-	if(netif_running(dev) != 0 && update > 0)
-	{
-		dvb_net_feed_stop(dev);
 		dvb_net_feed_start(dev);
 	}
+
+
+static void dvb_net_set_multicast_list (struct net_device *dev)
+{
+	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+	schedule_work(&priv->set_multicast_list_wq);
 }
 
+
 static int dvb_net_set_config(struct net_device *dev, struct ifmap *map)
 {
 	if (netif_running(dev))
@@ -345,29 +405,47 @@
 	return 0;
 }
 
-static int dvb_net_set_mac(struct net_device *dev, void *p)
+
+static void wq_restart_net_feed (void *data)
 {
-	struct sockaddr *addr=p;
-	int update;
+	struct net_device *dev = data;
 
-	update = memcmp(dev->dev_addr, addr->sa_data, dev->addr_len);
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-	if (netif_running(dev) != 0 && update > 0) {
+	if (netif_running(dev)) {
 		dvb_net_feed_stop(dev);
 		dvb_net_feed_start(dev);
 	}
+}
+
+
+static int dvb_net_set_mac (struct net_device *dev, void *p)
+{
+	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+	struct sockaddr *addr=p;
+
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+	if (netif_running(dev))
+		schedule_work(&priv->restart_net_feed_wq);
+
 	return 0;
 }
 
 
 static int dvb_net_open(struct net_device *dev)
 {
+	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+
+	priv->in_use++;
 	dvb_net_feed_start(dev);
 	return 0;
 }
 
+
 static int dvb_net_stop(struct net_device *dev)
 {
+	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+
+	priv->in_use--;
         dvb_net_feed_stop(dev);
 	return 0;
 }
@@ -386,16 +464,14 @@
 	dev->stop		= dvb_net_stop;
 	dev->hard_start_xmit	= dvb_net_tx;
 	dev->get_stats		= dvb_net_get_stats;
-	dev->set_multicast_list = dvb_net_set_multi;
+	dev->set_multicast_list = dvb_net_set_multicast_list;
 	dev->set_config         = dvb_net_set_config;
 	dev->set_mac_address    = dvb_net_set_mac;
 	dev->mtu		= 4096;
 	dev->mc_count           = 0;
-
-	dev->flags             |= IFF_NOARP;
 	dev->hard_header_cache  = NULL;
 
-	//SET_MODULE_OWNER(dev);
+	dev->flags |= IFF_NOARP;
 	
 	return 0;
 }
@@ -404,18 +480,19 @@
 {
 	int i;
 
-	for (i=0; i<dvbnet->dev_num; i++) 
+	for (i=0; i<DVB_NET_DEVICES_MAX; i++)
 		if (!dvbnet->state[i])
 			break;
-	if (i==dvbnet->dev_num)
+
+	if (i == DVB_NET_DEVICES_MAX)
 		return -1;
+
 	dvbnet->state[i]=1;
 	return i;
 }
 
 
-int 
-dvb_net_add_if(struct dvb_net *dvbnet, u16 pid)
+static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid)
 {
         struct net_device *net;
 	struct dmx_demux *demux;
@@ -423,59 +500,63 @@
 	int result;
 	int if_num;
  
-	if_num=get_if(dvbnet);
-	if (if_num<0)
+	if ((if_num = get_if(dvbnet)) < 0)
 		return -EINVAL;
 
 	net=&dvbnet->device[if_num];
 	demux=dvbnet->demux;
 	
-	net->base_addr = 0;
-	net->irq       = 0;
-	net->dma       = 0;
-	net->mem_start = 0;
+	memset(net, 0, sizeof(struct net_device));
+
         memcpy(net->name, "dvb0_0", 7);
-        net->name[3]=dvbnet->card_num+0x30;
-        net->name[5]=if_num+0x30;
+	net->name[3]   = dvbnet->dvbdev->adapter->num + '0';
+	net->name[5]   = if_num + '0';
+	net->addr_len  = 6;
+	memcpy(net->dev_addr, dvbnet->dvbdev->adapter->proposed_mac, 6);
         net->next      = NULL;
         net->init      = dvb_net_init_dev;
-        net->priv      = kmalloc(sizeof(struct dvb_net_priv), GFP_KERNEL);
-	if (net->priv == NULL)
+
+	if (!(net->priv = kmalloc(sizeof(struct dvb_net_priv), GFP_KERNEL)))
 			return -ENOMEM;
 
 	priv = net->priv;
 	memset(priv, 0, sizeof(struct dvb_net_priv));
         priv->demux = demux;
         priv->pid = pid;
-	priv->mode = 0;
+	priv->rx_mode = RX_MODE_UNI;
+
+	INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list, net);
+	INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed, net);
 
         net->base_addr = pid;
                 
 	if ((result = register_netdev(net)) < 0) {
 		return result;
 	}
-	/* fixme: is this correct? */
-	try_module_get(THIS_MODULE);
 
         return if_num;
 }
 
-int 
-dvb_net_remove_if(struct dvb_net *dvbnet, int num)
+
+static int dvb_net_remove_if(struct dvb_net *dvbnet, int num)
 {
+	struct dvb_net_priv *priv = dvbnet->device[num].priv;
+
 	if (!dvbnet->state[num])
 		return -EINVAL;
+	if (priv->in_use)
+		return -EBUSY;
+
 	dvb_net_stop(&dvbnet->device[num]);
-        kfree(dvbnet->device[num].priv);
+	flush_scheduled_work();
+	kfree(priv);
         unregister_netdev(&dvbnet->device[num]);
 	dvbnet->state[num]=0;
-	/* fixme: is this correct? */
-	module_put(THIS_MODULE);
-
 	return 0;
 }
 
-int dvb_net_do_ioctl(struct inode *inode, struct file *file, 
+
+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;
@@ -490,6 +571,8 @@
 		struct dvb_net_if *dvbnetif=(struct dvb_net_if *)parg;
 		int result;
 		
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
 		result=dvb_net_add_if(dvbnet, dvbnetif->pid);
 		if (result<0)
 			return result;
@@ -502,7 +585,7 @@
 		struct dvb_net_priv *priv_data;
 		struct dvb_net_if *dvbnetif=(struct dvb_net_if *)parg;
 
-		if (dvbnetif->if_num >= dvbnet->dev_num ||
+		if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
 		    !dvbnet->state[dvbnetif->if_num])
 			return -EFAULT;
 
@@ -512,7 +595,9 @@
 		break;
 	}
 	case NET_REMOVE_IF:
-		return dvb_net_remove_if(dvbnet, (long) parg);
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		return dvb_net_remove_if(dvbnet, (int) parg);
 	default:
 		return -EINVAL;
 	}
@@ -542,28 +627,29 @@
         .fops = &dvb_net_fops,
 };
 
-void
-dvb_net_release(struct dvb_net *dvbnet)
+
+void dvb_net_release (struct dvb_net *dvbnet)
 {
 	int i;
 
 	dvb_unregister_device(dvbnet->dvbdev);
-	for (i=0; i<dvbnet->dev_num; i++) {
+
+	for (i=0; i<DVB_NET_DEVICES_MAX; i++) {
 		if (!dvbnet->state[i])
 			continue;
 		dvb_net_remove_if(dvbnet, i);
 	}
 }
 
-int
-dvb_net_init(struct dvb_adapter *adap, struct dvb_net *dvbnet, struct dmx_demux *dmx)
+
+int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet,
+		  struct dmx_demux *dmx)
 {
 	int i;
 		
 	dvbnet->demux = dmx;
-	dvbnet->dev_num = DVB_NET_DEVICES_MAX;
 
-	for (i=0; i<dvbnet->dev_num; i++) 
+	for (i=0; i<DVB_NET_DEVICES_MAX; i++)
 		dvbnet->state[i] = 0;
 
 	dvb_register_device (adap, &dvbnet->dvbdev, &dvbdev_net,
diff -Nru a/drivers/media/dvb/dvb-core/dvb_net.h b/drivers/media/dvb/dvb-core/dvb_net.h
--- a/drivers/media/dvb/dvb-core/dvb_net.h	Sat Jul 19 12:54:22 2003
+++ b/drivers/media/dvb/dvb-core/dvb_net.h	Sat Jul 19 12:54:22 2003
@@ -35,8 +35,6 @@
 
 struct dvb_net {
 	struct dvb_device *dvbdev;
-	int card_num;
-	int dev_num;
 	struct net_device device[DVB_NET_DEVICES_MAX];
 	int state[DVB_NET_DEVICES_MAX];
 	struct dmx_demux *demux;
diff -Nru a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
--- a/drivers/media/dvb/dvb-core/dvbdev.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/media/dvb/dvb-core/dvbdev.c	Sat Jul 19 12:54:23 2003
@@ -29,8 +29,6 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/version.h>
-#include <asm/semaphore.h>
 
 #include "dvbdev.h"
 #include "dvb_functions.h"
diff -Nru a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h
--- a/drivers/media/dvb/dvb-core/dvbdev.h	Sat Jul 19 12:54:24 2003
+++ b/drivers/media/dvb/dvb-core/dvbdev.h	Sat Jul 19 12:54:24 2003
@@ -27,8 +27,9 @@
 #include <linux/types.h>
 #include <linux/poll.h>
 #include <linux/fs.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/list.h>
+#include <linux/version.h>
+#include <linux/devfs_fs_kernel.h>
 
 #define DVB_MAJOR 250
 
@@ -48,6 +49,7 @@
 	struct list_head list_head;
 	struct list_head device_list;
 	const char *name;
+	u8 proposed_mac [6];
 };
 
 
diff -Nru a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
--- a/drivers/media/dvb/frontends/Kconfig	Sat Jul 19 12:54:23 2003
+++ b/drivers/media/dvb/frontends/Kconfig	Sat Jul 19 12:54:23 2003
@@ -93,6 +93,16 @@
 	  DVB adapter simply enable all supported frontends, the 
 	  right one will get autodetected.
 
+config DVB_MT312
+	tristate "Zarlink MT312 Satellite Channel Decoder (QPSK)"
+	depends on DVB_CORE
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
+	  If you don't know what tuner module is soldered on your 
+	  DVB adapter simply enable all supported frontends, the 
+	  right one will get autodetected.
+
 config DVB_VES1820
 	tristate "Frontends with external VES1820 demodulator (QAM)"
 	depends on DVB_CORE
@@ -105,3 +115,23 @@
 	  DVB adapter simply enable all supported frontends, the 
 	  right one will get autodetected.
 
+config DVB_TDA1004X
+	tristate "Frontends with external TDA1004X demodulators (OFDM)"
+	depends on DVB_CORE
+	help
+	  A DVB-T tuner module. Say Y when you want to support this frontend.
+
+	  If you don't know what tuner module is soldered on your
+	  DVB adapter simply enable all supported frontends, the
+	  right one will get autodetected.
+
+config DVB_TDA1004X_FIRMWARE_FILE
+        string "Full pathname of tda1004x.bin firmware file"
+        depends on DVB_TDA1004X
+        default "/etc/dvb/tda1004x.bin"
+        help
+          The TDA1004X requires additional firmware in order to function.
+          The firmware file can obtained as follows:
+            wget http://www.technotrend.de/new/215/TTweb_215a_budget_20_05_2003.zip
+            unzip -j TTweb_215a_budget_20_05_2003.zip Software/Oem/PCI/App/ttlcdacc.dll
+            mv ttlcdacc.dll /etc/dvb/tda1004x.bin
diff -Nru a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
--- a/drivers/media/dvb/frontends/Makefile	Sat Jul 19 12:54:21 2003
+++ b/drivers/media/dvb/frontends/Makefile	Sat Jul 19 12:54:21 2003
@@ -12,4 +12,6 @@
 obj-$(CONFIG_DVB_CX24110) += cx24110.o
 obj-$(CONFIG_DVB_GRUNDIG_29504_491) += grundig_29504-491.o
 obj-$(CONFIG_DVB_GRUNDIG_29504_401) += grundig_29504-401.o
+obi-$(CONFIG_DVB_MT312) += mt312.o
 obj-$(CONFIG_DVB_VES1820) += ves1820.o
+obj-$(CONFIG_DVB_TDA1004X) += tda1004x.o
diff -Nru a/drivers/media/dvb/frontends/alps_bsrv2.c b/drivers/media/dvb/frontends/alps_bsrv2.c
--- a/drivers/media/dvb/frontends/alps_bsrv2.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/media/dvb/frontends/alps_bsrv2.c	Sat Jul 19 12:54:23 2003
@@ -55,7 +55,7 @@
         0x01, 0xA4, 0x35, 0x81, 0x2A, 0x0d, 0x55, 0xC4,
         0x09, 0x69, 0x00, 0x86, 0x4c, 0x28, 0x7F, 0x00,
         0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
-        0x80, 0x00, 0x31, 0xb0, 0x14, 0x00, 0xDC, 0x20,
+        0x80, 0x00, 0x31, 0xb0, 0x14, 0x00, 0xDC, 0x00,
         0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x55, 0x00, 0x00, 0x7f, 0x00
@@ -158,6 +158,11 @@
 {
 	u8 val;
 
+	/*
+	 * inversion on/off are interchanged because i and q seem to
+	 * be swapped on the hardware
+	 */
+
 	switch (inversion) {
 	case INVERSION_OFF:
 		val = 0xc0;
@@ -166,13 +171,16 @@
 		val = 0x80;
 		break;
 	case INVERSION_AUTO:
-		val = 0x40;
+		val = 0x00;
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	return ves1893_writereg (i2c, 0x0c, (init_1893_tab[0x0c] & 0x3f) | val);
+	/* needs to be saved for FE_GET_FRONTEND */
+	init_1893_tab[0x0c] = (init_1893_tab[0x0c] & 0x3f) | val;
+
+	return ves1893_writereg (i2c, 0x0c, init_1893_tab[0x0c]);
 }
 
 
@@ -383,8 +391,14 @@
 		afc = (afc * (int)(p->u.qpsk.symbol_rate/1000/8))/16;
 
 		p->frequency -= afc;
+
+		/*
+		 * inversion indicator is only valid
+		 * if auto inversion was used
+		 */
+		if (!(init_1893_tab[0x0c] & 0x80))
 		p->inversion = (ves1893_readreg (i2c, 0x0f) & 2) ? 
-					INVERSION_ON : INVERSION_OFF;
+					INVERSION_OFF : INVERSION_ON;
 		p->u.qpsk.fec_inner = ves1893_get_fec (i2c);
 	/*  XXX FIXME: timing offset !! */
 		break;
diff -Nru a/drivers/media/dvb/frontends/alps_tdlb7.c b/drivers/media/dvb/frontends/alps_tdlb7.c
--- a/drivers/media/dvb/frontends/alps_tdlb7.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/media/dvb/frontends/alps_tdlb7.c	Sat Jul 19 12:54:23 2003
@@ -349,6 +349,9 @@
 
 		sp5659_set_tv_freq (i2c, p->frequency);
 
+		// read status reg in order to clear pending irqs
+		sp8870_readreg(i2c, 0x200);
+
 		// sample rate correction bit [23..17]
 		sp8870_writereg(i2c,0x0319,0x000A);
 		
diff -Nru a/drivers/media/dvb/frontends/grundig_29504-401.c b/drivers/media/dvb/frontends/grundig_29504-401.c
--- a/drivers/media/dvb/frontends/grundig_29504-401.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/media/dvb/frontends/grundig_29504-401.c	Sat Jul 19 12:54:23 2003
@@ -37,15 +37,15 @@
 
 
 struct dvb_frontend_info grundig_29504_401_info = {
-	.name 			= "Grundig 29504-401",
-	.type 			= FE_OFDM,
-/*	.frequency_min 		= ???,*/
-/*	.frequency_max 		= ???,*/
-	.frequency_stepsize 	= 166666,
-/*      .frequency_tolerance 	= ???,*/
-/*      .symbol_rate_tolerance 	= ???,*/
-	.notifier_delay =  0,
-	.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 
+	name: "Grundig 29504-401",
+	type: FE_OFDM,
+/*	frequency_min: ???,*/
+/*	frequency_max: ???,*/
+	frequency_stepsize: 166666,
+/*      frequency_tolerance: ???,*/
+/*      symbol_rate_tolerance: ???,*/
+	notifier_delay: 0,
+	caps: FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 
 	      FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
 	      FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
 	      FE_CAN_MUTE_TS /*| FE_CAN_CLEAN_SETUP*/
@@ -109,15 +109,15 @@
 	div = (36125000 + freq) / 166666;
 	cfg = 0x88;
 
-	cpump = div < 175000000 ? 2 : div < 390000000 ? 1 :
-		div < 470000000 ? 2 : div < 750000000 ? 1 : 3;
+	cpump = freq < 175000000 ? 2 : freq < 390000000 ? 1 :
+		freq < 470000000 ? 2 : freq < 750000000 ? 1 : 3;
 
-	band_select = div < 175000000 ? 0x0e : div < 470000000 ? 0x05 : 0x03;
+	band_select = freq < 175000000 ? 0x0e : freq < 470000000 ? 0x05 : 0x03;
 
 	buf [0] = (div >> 8) & 0x7f;
 	buf [1] = div & 0xff;
 	buf [2] = ((div >> 10) & 0x60) | cfg;
-	buf [3] = cpump | band_select;
+	buf [3] = (cpump << 6) | band_select;
 
 	return tsa5060_write (i2c, buf);
 }
@@ -267,12 +267,12 @@
 }
 
 
-static void reset_and_configure (struct dvb_i2c_bus *i2c)
+static int reset_and_configure (struct dvb_i2c_bus *i2c)
 {
 	u8 buf [] = { 0x06 };
 	struct i2c_msg msg = { .addr = 0x00, .flags = 0, .buf = buf, .len = 1 };
 
-	i2c->xfer (i2c, &msg, 1);
+	return (i2c->xfer (i2c, &msg, 1) == 1) ? 0 : -ENODEV;
 }
 
 
@@ -391,7 +391,7 @@
 		struct dvb_frontend_parameters *p = arg;
 
 		tsa5060_set_tv_freq (i2c, p->frequency);
-		apply_frontend_param (i2c, p);
+		return apply_frontend_param (i2c, p);
 	}
         case FE_GET_FRONTEND:
 		/*  we could correct the frequency here, but...
@@ -417,25 +417,61 @@
 
 static int l64781_attach (struct dvb_i2c_bus *i2c)
 {
+	u8 reg0x3e;
 	u8 b0 [] = { 0x1a };
 	u8 b1 [] = { 0x00 };
 	struct i2c_msg msg [] = { { .addr = 0x55, .flags = 0, .buf = b0, .len = 1 },
 			   { .addr = 0x55, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
 
-	if (i2c->xfer (i2c, msg, 2) == 2)   /*  probably an EEPROM... */
+	/**
+	 *  the L64781 won't show up before we send the reset_and_configure()
+	 *  broadcast. If nothing responds there is no L64781 on the bus...
+	 */
+	if (reset_and_configure(i2c) < 0) {
+		dprintk("no response on reset_and_configure() broadcast, bailing out...\n");
 		return -ENODEV;
+	}
 
-	reset_and_configure (i2c);
-
-	if (i2c->xfer (i2c, msg, 2) != 2)   /*  nothing... */
+	/* The chip always responds to reads */
+	if (i2c->xfer(i2c, msg, 2) != 2) {  
+	        dprintk("no response to read on I2C bus\n");
 		return -ENODEV;
+	}
 
-	if (b1[0] != 0xa1)
+	/* Save current register contents for bailout */
+	reg0x3e = l64781_readreg(i2c, 0x3e);
+
+	/* Reading the POWER_DOWN register always returns 0 */
+	if (reg0x3e != 0) {
+	        dprintk("Device doesn't look like L64781\n");
 		return -ENODEV;
+	}
+
+	/* Turn the chip off */
+	l64781_writereg (i2c, 0x3e, 0x5a);
+
+	/* Responds to all reads with 0 */
+	if (l64781_readreg(i2c, 0x1a) != 0) {
+ 	        dprintk("Read 1 returned unexpcted value\n");
+	        goto bailout;
+	}	  
+
+	/* Turn the chip on */
+	l64781_writereg (i2c, 0x3e, 0xa5);
+	
+	/* Responds with register default value */
+	if (l64781_readreg(i2c, 0x1a) != 0xa1) { 
+ 	        dprintk("Read 2 returned unexpcted value\n");
+	        goto bailout;
+	}
 
 	dvb_register_frontend (grundig_29504_401_ioctl, i2c, NULL,
 			       &grundig_29504_401_info);
 	return 0;
+
+ bailout:
+	l64781_writereg (i2c, 0x3e, reg0x3e);  /* restore reg 0x3e */
+	return -ENODEV;
 }
 
 
diff -Nru a/drivers/media/dvb/frontends/grundig_29504-491.c b/drivers/media/dvb/frontends/grundig_29504-491.c
--- a/drivers/media/dvb/frontends/grundig_29504-491.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/media/dvb/frontends/grundig_29504-491.c	Sat Jul 19 12:54:27 2003
@@ -179,10 +179,7 @@
 	static fe_code_rate_t fec_tab [] = { FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4,
 				       FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8 };
 
-	index = tda8083_readreg (i2c, 0x0e) & 0x3;
-
-	if (index > 7)
-		return FEC_NONE;
+	index = tda8083_readreg(i2c, 0x0e) & 0x07;
 
 	return fec_tab [index];
 }
diff -Nru a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/frontends/mt312.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,749 @@
+/* 
+    Driver for Zarlink MT312 Satellite Channel Decoder
+
+    Copyright (C) 2003 Andreas Oberritter <obi@saftware.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    References:
+    http://products.zarlink.com/product_profiles/MT312.htm
+    http://products.zarlink.com/product_profiles/SL1935.htm
+*/
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "dvb_frontend.h"
+#include "mt312.h"
+
+#define I2C_ADDR_MT312		0x0e
+#define I2C_ADDR_SL1935		0x61
+#define I2C_ADDR_TSA5059	0x61
+
+#define MT312_DEBUG		0
+
+#define MT312_SYS_CLK		90000000UL	/* 90 MHz */
+#define MT312_PLL_CLK		10000000UL	/* 10 MHz */
+
+static struct dvb_frontend_info mt312_info = {
+	.name = "Zarlink MT312",
+	.type = FE_QPSK,
+	.frequency_min = 950000,
+	.frequency_max = 2150000,
+	.frequency_stepsize = (MT312_PLL_CLK / 1000) / 128,
+	/*.frequency_tolerance = 29500,         FIXME: binary compatibility waste? */
+	.symbol_rate_min = MT312_SYS_CLK / 128,
+	.symbol_rate_max = MT312_SYS_CLK / 2,
+	/*.symbol_rate_tolerance = 500,         FIXME: binary compatibility waste? 2% */
+	.notifier_delay = 0,
+	.caps =
+	    FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
+	    FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
+	    FE_CAN_FEC_AUTO | FE_CAN_QPSK | FE_CAN_RECOVER |
+	    FE_CAN_CLEAN_SETUP | FE_CAN_MUTE_TS
+};
+
+static int mt312_read(struct dvb_i2c_bus *i2c,
+		      const enum mt312_reg_addr reg, void *buf,
+		      const size_t count)
+{
+	int ret;
+	struct i2c_msg msg[2];
+	u8 regbuf[1] = { reg };
+
+	msg[0].addr = I2C_ADDR_MT312;
+	msg[0].flags = 0;
+	msg[0].buf = regbuf;
+	msg[0].len = 1;
+	msg[1].addr = I2C_ADDR_MT312;
+	msg[1].flags = I2C_M_RD;
+	msg[1].buf = buf;
+	msg[1].len = count;
+
+	ret = i2c->xfer(i2c, msg, 2);
+
+	if (ret != 2) {
+		printk(KERN_ERR "%s: ret == %d\n", __FUNCTION__, ret);
+		return -EREMOTEIO;
+	}
+#ifdef MT312_DEBUG
+	{
+		int i;
+		printk(KERN_INFO "R(%d):", reg & 0x7f);
+		for (i = 0; i < count; i++)
+			printk(" %02x", ((const u8 *) buf)[i]);
+		printk("\n");
+	}
+#endif
+
+	return 0;
+}
+
+static int mt312_write(struct dvb_i2c_bus *i2c,
+		       const enum mt312_reg_addr reg, const void *src,
+		       const size_t count)
+{
+	int ret;
+	u8 buf[count + 1];
+	struct i2c_msg msg;
+
+#ifdef MT312_DEBUG
+	{
+		int i;
+		printk(KERN_INFO "W(%d):", reg & 0x7f);
+		for (i = 0; i < count; i++)
+			printk(" %02x", ((const u8 *) src)[i]);
+		printk("\n");
+	}
+#endif
+
+	buf[0] = reg;
+	memcpy(&buf[1], src, count);
+
+	msg.addr = I2C_ADDR_MT312;
+	msg.flags = 0;
+	msg.buf = buf;
+	msg.len = count + 1;
+
+	ret = i2c->xfer(i2c, &msg, 1);
+
+	if (ret != 1) {
+		printk(KERN_ERR "%s: ret == %d\n", __FUNCTION__, ret);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static inline int mt312_readreg(struct dvb_i2c_bus *i2c,
+				const enum mt312_reg_addr reg, u8 * val)
+{
+	return mt312_read(i2c, reg, val, 1);
+}
+
+static inline int mt312_writereg(struct dvb_i2c_bus *i2c,
+				 const enum mt312_reg_addr reg, const u8 val)
+{
+	return mt312_write(i2c, reg, &val, 1);
+}
+
+static int mt312_pll_write(struct dvb_i2c_bus *i2c, const u8 addr,
+			   u8 * buf, const u8 len)
+{
+	int ret;
+	struct i2c_msg msg;
+
+	msg.addr = addr;
+	msg.flags = 0;
+	msg.buf = buf;
+	msg.len = len;
+
+	if ((ret = mt312_writereg(i2c, GPP_CTRL, 0x40)) < 0)
+		return ret;
+
+	if ((ret = i2c->xfer(i2c, &msg, 1)) != 1)
+		printk(KERN_ERR "%s: i/o error (ret == %d)\n", __FUNCTION__, ret);
+
+	if ((ret = mt312_writereg(i2c, GPP_CTRL, 0x00)) < 0)
+		return ret;
+
+	return 0;
+}
+
+static inline u32 mt312_div(u32 a, u32 b)
+{
+	return (a + (b / 2)) / b;
+}
+
+static int sl1935_set_tv_freq(struct dvb_i2c_bus *i2c, u32 freq, u32 sr)
+{
+	/* 155 uA, Baseband Path B */
+	u8 buf[4] = { 0x00, 0x00, 0x80, 0x00 };
+
+	u8 exp;
+	u32 ref;
+	u32 div;
+
+	if (sr < 10000000) {	/* 1-10 MSym/s: ratio 2 ^ 3 */
+		exp = 3;
+		buf[2] |= 0x40;	/* 690 uA */
+	} else if (sr < 15000000) {	/* 10-15 MSym/s: ratio 2 ^ 4 */
+		exp = 4;
+		buf[2] |= 0x20;	/* 330 uA */
+	} else {		/* 15-45 MSym/s: ratio 2 ^ 7 */
+		exp = 7;
+		buf[3] |= 0x08;	/* Baseband Path A */
+	}
+
+	div = mt312_div(MT312_PLL_CLK, 1 << exp);
+	ref = mt312_div(freq * 1000, div);
+	mt312_info.frequency_stepsize = mt312_div(div, 1000);
+
+	buf[0] = (ref >> 8) & 0x7f;
+	buf[1] = (ref >> 0) & 0xff;
+	buf[2] |= (exp - 1);
+
+	if (freq < 1550000)
+		buf[3] |= 0x10;
+
+	printk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0],
+	       buf[1], buf[2], buf[3]);
+
+	return mt312_pll_write(i2c, I2C_ADDR_SL1935, buf, sizeof(buf));
+}
+
+static int tsa5059_set_tv_freq(struct dvb_i2c_bus *i2c, u32 freq, u32 sr)
+{
+	u8 buf[4];
+
+	u32 ref = mt312_div(freq, 125);
+
+	buf[0] = (ref >> 8) & 0x7f;
+	buf[1] = (ref >> 0) & 0xff;
+	buf[2] = 0x84 | ((ref >> 10) & 0x60);
+	buf[3] = 0x80;
+	
+	if (freq < 1550000)
+		buf[3] |= 0x02;
+
+	printk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0],
+	       buf[1], buf[2], buf[3]);
+
+	return mt312_pll_write(i2c, I2C_ADDR_TSA5059, buf, sizeof(buf));
+}
+
+static int mt312_reset(struct dvb_i2c_bus *i2c, const u8 full)
+{
+	return mt312_writereg(i2c, RESET, full ? 0x80 : 0x40);
+}
+
+static int mt312_init(struct dvb_i2c_bus *i2c, const long id)
+{
+	int ret;
+	u8 buf[2];
+
+	/* wake up */
+	if ((ret = mt312_writereg(i2c, CONFIG, 0x8c)) < 0)
+		return ret;
+
+	/* wait at least 150 usec */
+	udelay(150);
+
+	/* full reset */
+	if ((ret = mt312_reset(i2c, 1)) < 0)
+		return ret;
+
+	/* SYS_CLK */
+	buf[0] = mt312_div(MT312_SYS_CLK * 2, 1000000);
+
+	/* DISEQC_RATIO */
+	buf[1] = mt312_div(MT312_PLL_CLK, 15000 * 4);
+
+	if ((ret = mt312_write(i2c, SYS_CLK, buf, sizeof(buf))) < 0)
+		return ret;
+
+	if ((ret = mt312_writereg(i2c, SNR_THS_HIGH, 0x32)) < 0)
+		return ret;
+
+	if ((ret = mt312_writereg(i2c, OP_CTRL, 0x53)) < 0)
+		return ret;
+
+	/* TS_SW_LIM */
+	buf[0] = 0x8c;
+	buf[1] = 0x98;
+
+	if ((ret = mt312_write(i2c, TS_SW_LIM_L, buf, sizeof(buf))) < 0)
+		return ret;
+
+	if ((ret = mt312_writereg(i2c, CS_SW_LIM, 0x69)) < 0)
+		return ret;
+
+	return 0;
+}
+
+static int mt312_send_master_cmd(struct dvb_i2c_bus *i2c,
+				 const struct dvb_diseqc_master_cmd *c)
+{
+	int ret;
+	u8 diseqc_mode;
+
+	if ((c->msg_len == 0) || (c->msg_len > sizeof(c->msg)))
+		return -EINVAL;
+
+	if ((ret = mt312_readreg(i2c, DISEQC_MODE, &diseqc_mode)) < 0)
+		return ret;
+
+	if ((ret =
+	     mt312_write(i2c, (0x80 | DISEQC_INSTR), c->msg, c->msg_len)) < 0)
+		return ret;
+
+	if ((ret =
+	     mt312_writereg(i2c, DISEQC_MODE,
+			    (diseqc_mode & 0x40) | ((c->msg_len - 1) << 3)
+			    | 0x04)) < 0)
+		return ret;
+
+	/* set DISEQC_MODE[2:0] to zero if a return message is expected */
+	if (c->msg[0] & 0x02)
+		if ((ret =
+		     mt312_writereg(i2c, DISEQC_MODE, (diseqc_mode & 0x40))) < 0)
+			return ret;
+
+	return 0;
+}
+
+static int mt312_recv_slave_reply(struct dvb_i2c_bus *i2c,
+				  struct dvb_diseqc_slave_reply *r)
+{
+	/* TODO */
+	return -EOPNOTSUPP;
+}
+
+static int mt312_send_burst(struct dvb_i2c_bus *i2c, const fe_sec_mini_cmd_t c)
+{
+	const u8 mini_tab[2] = { 0x02, 0x03 };
+
+	int ret;
+	u8 diseqc_mode;
+
+	if (c > SEC_MINI_B)
+		return -EINVAL;
+
+	if ((ret = mt312_readreg(i2c, DISEQC_MODE, &diseqc_mode)) < 0)
+		return ret;
+
+	if ((ret =
+	     mt312_writereg(i2c, DISEQC_MODE,
+			    (diseqc_mode & 0x40) | mini_tab[c])) < 0)
+		return ret;
+
+	return 0;
+}
+
+static int mt312_set_tone(struct dvb_i2c_bus *i2c, const fe_sec_tone_mode_t t)
+{
+	const u8 tone_tab[2] = { 0x01, 0x00 };
+
+	int ret;
+	u8 diseqc_mode;
+
+	if (t > SEC_TONE_OFF)
+		return -EINVAL;
+
+	if ((ret = mt312_readreg(i2c, DISEQC_MODE, &diseqc_mode)) < 0)
+		return ret;
+
+	if ((ret =
+	     mt312_writereg(i2c, DISEQC_MODE,
+			    (diseqc_mode & 0x40) | tone_tab[t])) < 0)
+		return ret;
+
+	return 0;
+}
+
+static int mt312_set_voltage(struct dvb_i2c_bus *i2c, const fe_sec_voltage_t v)
+{
+	const u8 volt_tab[3] = { 0x00, 0x40, 0x00 };
+
+	if (v > SEC_VOLTAGE_OFF)
+		return -EINVAL;
+
+	return mt312_writereg(i2c, DISEQC_MODE, volt_tab[v]);
+}
+
+static int mt312_read_status(struct dvb_i2c_bus *i2c, fe_status_t * s)
+{
+	int ret;
+	u8 status[3];
+
+	*s = 0;
+
+	if ((ret = mt312_read(i2c, QPSK_STAT_H, status, sizeof(status))) < 0)
+		return ret;
+
+	if (status[0] & 0xc0)
+		*s |= FE_HAS_SIGNAL;	/* signal noise ratio */
+	if (status[0] & 0x04)
+		*s |= FE_HAS_CARRIER;	/* qpsk carrier lock */
+	if (status[2] & 0x02)
+		*s |= FE_HAS_VITERBI;	/* viterbi lock */
+	if (status[2] & 0x04)
+		*s |= FE_HAS_SYNC;	/* byte align lock */
+	if (status[0] & 0x01)
+		*s |= FE_HAS_LOCK;	/* qpsk lock */
+
+	return 0;
+}
+
+static int mt312_read_bercnt(struct dvb_i2c_bus *i2c, u32 * ber)
+{
+	int ret;
+	u8 buf[3];
+
+	if ((ret = mt312_read(i2c, RS_BERCNT_H, buf, 3)) < 0)
+		return ret;
+
+	*ber = ((buf[0] << 16) | (buf[1] << 8) | buf[2]) * 64;
+
+	return 0;
+}
+
+static int mt312_read_agc(struct dvb_i2c_bus *i2c, u16 * signal_strength)
+{
+	int ret;
+	u8 buf[3];
+	u16 agc;
+	s16 err_db;
+
+	if ((ret = mt312_read(i2c, AGC_H, buf, sizeof(buf))) < 0)
+		return ret;
+
+	agc = (buf[0] << 6) | (buf[1] >> 2);
+	err_db = (s16) (((buf[1] & 0x03) << 14) | buf[2] << 6) >> 6;
+
+	*signal_strength = agc;
+
+	printk(KERN_DEBUG "agc=%08x err_db=%hd\n", agc, err_db);
+
+	return 0;
+}
+
+static int mt312_read_snr(struct dvb_i2c_bus *i2c, u16 * snr)
+{
+	int ret;
+	u8 buf[2];
+
+	if ((ret = mt312_read(i2c, M_SNR_H, &buf, sizeof(buf))) < 0)
+		return ret;
+
+	*snr = 0xFFFF - ((((buf[0] & 0x7f) << 8) | buf[1]) << 1);
+
+	return 0;
+}
+
+static int mt312_read_ubc(struct dvb_i2c_bus *i2c, u32 * ubc)
+{
+	int ret;
+	u8 buf[2];
+
+	if ((ret = mt312_read(i2c, RS_UBC_H, &buf, sizeof(buf))) < 0)
+		return ret;
+
+	*ubc = (buf[0] << 8) | buf[1];
+
+	return 0;
+}
+
+static int mt312_set_frontend(struct dvb_i2c_bus *i2c,
+			      const struct dvb_frontend_parameters *p,
+			      const long id)
+{
+	int ret;
+	u8 buf[5];
+	u16 sr;
+
+	const u8 fec_tab[10] =
+	    { 0x00, 0x01, 0x02, 0x04, 0x3f, 0x08, 0x10, 0x20, 0x3f, 0x3f };
+	const u8 inv_tab[3] = { 0x00, 0x40, 0x80 };
+
+	int (*set_tv_freq)(struct dvb_i2c_bus *i2c, u32 freq, u32 sr);
+
+	if ((p->frequency < mt312_info.frequency_min)
+	    || (p->frequency > mt312_info.frequency_max))
+		return -EINVAL;
+
+	if ((p->inversion < INVERSION_OFF)
+	    || (p->inversion > INVERSION_AUTO))
+		return -EINVAL;
+
+	if ((p->u.qpsk.symbol_rate < mt312_info.symbol_rate_min)
+	    || (p->u.qpsk.symbol_rate > mt312_info.symbol_rate_max))
+		return -EINVAL;
+
+	if ((p->u.qpsk.fec_inner < FEC_NONE)
+	    || (p->u.qpsk.fec_inner > FEC_AUTO))
+		return -EINVAL;
+
+	if ((p->u.qpsk.fec_inner == FEC_4_5)
+	    || (p->u.qpsk.fec_inner == FEC_8_9))
+		return -EINVAL;
+
+	switch (id) {
+	case ID_VP310:
+		set_tv_freq = tsa5059_set_tv_freq;
+		break;
+	case ID_MT312:
+		set_tv_freq = sl1935_set_tv_freq;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if ((ret = set_tv_freq(i2c, p->frequency, p->u.qpsk.symbol_rate)) < 0)
+		return ret;
+
+	/* sr = (u16)(sr * 256.0 / 1000000.0) */
+	sr = mt312_div(p->u.qpsk.symbol_rate * 4, 15625);
+
+	/* SYM_RATE */
+	buf[0] = (sr >> 8) & 0x3f;
+	buf[1] = (sr >> 0) & 0xff;
+
+	/* VIT_MODE */
+	buf[2] = inv_tab[p->inversion] | fec_tab[p->u.qpsk.fec_inner];
+
+	/* QPSK_CTRL */
+	buf[3] = 0x40;		/* swap I and Q before QPSK demodulation */
+
+	if (p->u.qpsk.symbol_rate < 10000000)
+		buf[3] |= 0x04;	/* use afc mode */
+
+	/* GO */
+	buf[4] = 0x01;
+
+	if ((ret = mt312_write(i2c, SYM_RATE_H, buf, sizeof(buf))) < 0)
+		return ret;
+
+	return 0;
+}
+
+static int mt312_get_inversion(struct dvb_i2c_bus *i2c,
+			       fe_spectral_inversion_t * i)
+{
+	int ret;
+	u8 vit_mode;
+
+	if ((ret = mt312_readreg(i2c, VIT_MODE, &vit_mode)) < 0)
+		return ret;
+
+	if (vit_mode & 0x80)	/* auto inversion was used */
+		*i = (vit_mode & 0x40) ? INVERSION_ON : INVERSION_OFF;
+
+	return 0;
+}
+
+static int mt312_get_symbol_rate(struct dvb_i2c_bus *i2c, u32 * sr)
+{
+	int ret;
+	u8 sym_rate_h;
+	u8 dec_ratio;
+	u16 sym_rat_op;
+	u16 monitor;
+	u8 buf[2];
+
+	if ((ret = mt312_readreg(i2c, SYM_RATE_H, &sym_rate_h)) < 0)
+		return ret;
+
+	if (sym_rate_h & 0x80) {	/* symbol rate search was used */
+		if ((ret = mt312_writereg(i2c, MON_CTRL, 0x03)) < 0)
+			return ret;
+
+		if ((ret = mt312_read(i2c, MONITOR_H, buf, sizeof(buf))) < 0)
+			return ret;
+
+		monitor = (buf[0] << 8) | buf[1];
+
+		printk(KERN_DEBUG "sr(auto) = %u\n",
+		       mt312_div(monitor * 15625, 4));
+	} else {
+		if ((ret = mt312_writereg(i2c, MON_CTRL, 0x05)) < 0)
+			return ret;
+
+		if ((ret = mt312_read(i2c, MONITOR_H, buf, sizeof(buf))) < 0)
+			return ret;
+
+		dec_ratio = ((buf[0] >> 5) & 0x07) * 32;
+
+		if ((ret = mt312_read(i2c, SYM_RAT_OP_H, buf, sizeof(buf))) < 0)
+			return ret;
+
+		sym_rat_op = (buf[0] << 8) | buf[1];
+
+		printk(KERN_DEBUG "sym_rat_op=%d dec_ratio=%d\n",
+		       sym_rat_op, dec_ratio);
+		printk(KERN_DEBUG "*sr(manual) = %lu\n",
+		       (((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) *
+			2) - dec_ratio);
+	}
+
+	return 0;
+}
+
+static int mt312_get_code_rate(struct dvb_i2c_bus *i2c, fe_code_rate_t * cr)
+{
+	const fe_code_rate_t fec_tab[8] =
+	    { FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_6_7, FEC_7_8,
+		FEC_AUTO, FEC_AUTO };
+
+	int ret;
+	u8 fec_status;
+
+	if ((ret = mt312_readreg(i2c, FEC_STATUS, &fec_status)) < 0)
+		return ret;
+
+	*cr = fec_tab[(fec_status >> 4) & 0x07];
+
+	return 0;
+}
+
+static int mt312_get_frontend(struct dvb_i2c_bus *i2c,
+			      struct dvb_frontend_parameters *p)
+{
+	int ret;
+
+	if ((ret = mt312_get_inversion(i2c, &p->inversion)) < 0)
+		return ret;
+
+	if ((ret = mt312_get_symbol_rate(i2c, &p->u.qpsk.symbol_rate)) < 0)
+		return ret;
+
+	if ((ret = mt312_get_code_rate(i2c, &p->u.qpsk.fec_inner)) < 0)
+		return ret;
+
+	return 0;
+}
+
+static int mt312_sleep(struct dvb_i2c_bus *i2c)
+{
+	int ret;
+	u8 config;
+
+	/* reset all registers to defaults */
+	if ((ret = mt312_reset(i2c, 1)) < 0)
+		return ret;
+
+	if ((ret = mt312_readreg(i2c, CONFIG, &config)) < 0)
+		return ret;
+
+	/* enter standby */
+	if ((ret = mt312_writereg(i2c, CONFIG, config & 0x7f)) < 0)
+		return ret;
+
+	return 0;
+}
+
+static int mt312_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
+{
+	struct dvb_i2c_bus *i2c = fe->i2c;
+
+	switch (cmd) {
+	case FE_GET_INFO:
+		memcpy(arg, &mt312_info, sizeof(struct dvb_frontend_info));
+		break;
+
+	case FE_DISEQC_RESET_OVERLOAD:
+		return -EOPNOTSUPP;
+
+	case FE_DISEQC_SEND_MASTER_CMD:
+		return mt312_send_master_cmd(i2c, arg);
+
+	case FE_DISEQC_RECV_SLAVE_REPLY:
+		if ((long) fe->data == ID_MT312)
+			return mt312_recv_slave_reply(i2c, arg);
+		else
+			return -EOPNOTSUPP;
+
+	case FE_DISEQC_SEND_BURST:
+		return mt312_send_burst(i2c, (fe_sec_mini_cmd_t) arg);
+
+	case FE_SET_TONE:
+		return mt312_set_tone(i2c, (fe_sec_tone_mode_t) arg);
+
+	case FE_SET_VOLTAGE:
+		return mt312_set_voltage(i2c, (fe_sec_voltage_t) arg);
+
+	case FE_ENABLE_HIGH_LNB_VOLTAGE:
+		return -EOPNOTSUPP;
+
+	case FE_READ_STATUS:
+		return mt312_read_status(i2c, arg);
+
+	case FE_READ_BER:
+		return mt312_read_bercnt(i2c, arg);
+
+	case FE_READ_SIGNAL_STRENGTH:
+		return mt312_read_agc(i2c, arg);
+
+	case FE_READ_SNR:
+		return mt312_read_snr(i2c, arg);
+
+	case FE_READ_UNCORRECTED_BLOCKS:
+		return mt312_read_ubc(i2c, arg);
+
+	case FE_SET_FRONTEND:
+		return mt312_set_frontend(i2c, arg, (long) fe->data);
+
+	case FE_GET_FRONTEND:
+		return mt312_get_frontend(i2c, arg);
+
+	case FE_GET_EVENT:
+		return -EOPNOTSUPP;
+
+	case FE_SLEEP:
+		return mt312_sleep(i2c);
+
+	case FE_INIT:
+		return mt312_init(i2c, (long) fe->data);
+
+	case FE_RESET:
+		return mt312_reset(i2c, 0);
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	return 0;
+}
+
+static int mt312_attach(struct dvb_i2c_bus *i2c)
+{
+	int ret;
+	u8 id;
+
+	if ((ret = mt312_readreg(i2c, ID, &id)) < 0)
+		return ret;
+
+	if ((id != ID_VP310) && (id != ID_MT312))
+		return -ENODEV;
+
+	return dvb_register_frontend(mt312_ioctl, i2c, (void *) (long) id,
+				     &mt312_info);
+}
+
+static void mt312_detach(struct dvb_i2c_bus *i2c)
+{
+	dvb_unregister_frontend(mt312_ioctl, i2c);
+}
+
+static int __init mt312_module_init(void)
+{
+	return dvb_register_i2c_device(THIS_MODULE, mt312_attach, mt312_detach);
+}
+
+static void __exit mt312_module_exit(void)
+{
+	dvb_unregister_i2c_device(mt312_attach);
+}
+
+module_init(mt312_module_init);
+module_exit(mt312_module_exit);
+
+MODULE_DESCRIPTION("MT312 Satellite Channel Decoder Driver");
+MODULE_AUTHOR("Andreas Oberritter <obi@saftware.de>");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/frontends/mt312.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,162 @@
+/* 
+    Driver for Zarlink MT312 QPSK Frontend
+
+    Copyright (C) 2003 Andreas Oberritter <obi@saftware.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef _DVB_FRONTENDS_MT312
+#define _DVB_FRONTENDS_MT312
+
+enum mt312_reg_addr {
+	QPSK_INT_H = 0,
+	QPSK_INT_M = 1,
+	QPSK_INT_L = 2,
+	FEC_INT = 3,
+	QPSK_STAT_H = 4,
+	QPSK_STAT_L = 5,
+	FEC_STATUS = 6,
+	LNB_FREQ_H = 7,
+	LNB_FREQ_L = 8,
+	M_SNR_H = 9,
+	M_SNR_L = 10,
+	VIT_ERRCNT_H = 11,
+	VIT_ERRCNT_M = 12,
+	VIT_ERRCNT_L = 13,
+	RS_BERCNT_H = 14,
+	RS_BERCNT_M = 15,
+	RS_BERCNT_L = 16,
+	RS_UBC_H = 17,
+	RS_UBC_L = 18,
+	SIG_LEVEL = 19,
+	GPP_CTRL = 20,
+	RESET = 21,
+	DISEQC_MODE = 22,
+	SYM_RATE_H = 23,
+	SYM_RATE_L = 24,
+	VIT_MODE = 25,
+	QPSK_CTRL = 26,
+	GO = 27,
+	IE_QPSK_H = 28,
+	IE_QPSK_M = 29,
+	IE_QPSK_L = 30,
+	IE_FEC = 31,
+	QPSK_STAT_EN = 32,
+	FEC_STAT_EN = 33,
+	SYS_CLK = 34,
+	DISEQC_RATIO = 35,
+	DISEQC_INSTR = 36,
+	FR_LIM = 37,
+	FR_OFF = 38,
+	AGC_CTRL = 39,
+	AGC_INIT = 40,
+	AGC_REF = 41,
+	AGC_MAX = 42,
+	AGC_MIN = 43,
+	AGC_LK_TH = 44,
+	TS_AGC_LK_TH = 45,
+	AGC_PWR_SET = 46,
+	QPSK_MISC = 47,
+	SNR_THS_LOW = 48,
+	SNR_THS_HIGH = 49,
+	TS_SW_RATE = 50,
+	TS_SW_LIM_L = 51,
+	TS_SW_LIM_H = 52,
+	CS_SW_RATE_1 = 53,
+	CS_SW_RATE_2 = 54,
+	CS_SW_RATE_3 = 55,
+	CS_SW_RATE_4 = 56,
+	CS_SW_LIM = 57,
+	TS_LPK = 58,
+	TS_LPK_M = 59,
+	TS_LPK_L = 60,
+	CS_KPROP_H = 61,
+	CS_KPROP_L = 62,
+	CS_KINT_H = 63,
+	CS_KINT_L = 64,
+	QPSK_SCALE = 65,
+	TLD_OUTCLK_TH = 66,
+	TLD_INCLK_TH = 67,
+	FLD_TH = 68,
+	PLD_OUTLK3 = 69,
+	PLD_OUTLK2 = 70,
+	PLD_OUTLK1 = 71,
+	PLD_OUTLK0 = 72,
+	PLD_INLK3 = 73,
+	PLD_INLK2 = 74,
+	PLD_INLK1 = 75,
+	PLD_INLK0 = 76,
+	PLD_ACC_TIME = 77,
+	SWEEP_PAR = 78,
+	STARTUP_TIME = 79,
+	LOSSLOCK_TH = 80,
+	FEC_LOCK_TM = 81,
+	LOSSLOCK_TM = 82,
+	VIT_ERRPER_H = 83,
+	VIT_ERRPER_M = 84,
+	VIT_ERRPER_L = 85,
+	VIT_SETUP = 86,
+	VIT_REF0 = 87,
+	VIT_REF1 = 88,
+	VIT_REF2 = 89,
+	VIT_REF3 = 90,
+	VIT_REF4 = 91,
+	VIT_REF5 = 92,
+	VIT_REF6 = 93,
+	VIT_MAXERR = 94,
+	BA_SETUPT = 95,
+	OP_CTRL = 96,
+	FEC_SETUP = 97,
+	PROG_SYNC = 98,
+	AFC_SEAR_TH = 99,
+	CSACC_DIF_TH = 100,
+	QPSK_LK_CT = 101,
+	QPSK_ST_CT = 102,
+	MON_CTRL = 103,
+	QPSK_RESET = 104,
+	QPSK_TST_CT = 105,
+	QPSK_TST_ST = 106,
+	TEST_R = 107,
+	AGC_H = 108,
+	AGC_M = 109,
+	AGC_L = 110,
+	FREQ_ERR1_H = 111,
+	FREQ_ERR1_M = 112,
+	FREQ_ERR1_L = 113,
+	FREQ_ERR2_H = 114,
+	FREQ_ERR2_L = 115,
+	SYM_RAT_OP_H = 116,
+	SYM_RAT_OP_L = 117,
+	DESEQC2_INT = 118,
+	DISEQC2_STAT = 119,
+	DISEQC2_FIFO = 120,
+	DISEQC2_CTRL1 = 121,
+	DISEQC2_CTRL2 = 122,
+	MONITOR_H = 123,
+	MONITOR_L = 124,
+	TEST_MODE = 125,
+	ID = 126,
+	CONFIG = 127
+};
+
+enum mt312_model_id {
+	ID_VP310 = 1,
+	ID_MT312 = 3
+};
+
+#endif				/* DVB_FRONTENDS_MT312 */
diff -Nru a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c
--- a/drivers/media/dvb/frontends/nxt6000.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/media/dvb/frontends/nxt6000.c	Sat Jul 19 12:54:26 2003
@@ -6,8 +6,10 @@
 	
 	Alps TDME7 (Tuner: MITEL SP5659)
 	Alps TDED4 (Tuner: TI ALP510, external Nxt6000)
+	Comtech DVBT-6k07 (PLL IC: SP5730)
 
     Copyright (C) 2002-2003 Florian Schirmer <schirmer@taytron.net>
+    Copyright (C) 2003 Paul Andreassen <paul@andreassen.com.au>
 
     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
@@ -78,6 +80,7 @@
 
 #define TUNER_TYPE_ALP510	0
 #define TUNER_TYPE_SP5659	1
+#define TUNER_TYPE_SP5730	2
 
 #define FE2NXT(fe) ((struct nxt6000_config *)&(fe->data))
 #define FREQ2DIV(freq) ((freq + 36166667) / 166667)
@@ -212,6 +215,39 @@
 	
 }
 
+static int sp5730_set_tv_freq(struct dvb_frontend *fe, u32 freq)
+{
+
+	u8 buf[4];
+	struct nxt6000_config *nxt = FE2NXT(fe);
+
+	buf[0] = (FREQ2DIV(freq) >> 8) & 0x7F;
+	buf[1] = FREQ2DIV(freq) & 0xFF;
+	buf[2] = 0x93;
+
+	if ((freq >= 51000000) && (freq < 132100000))
+		buf[3] = 0x05;
+	else if ((freq >= 132100000) && (freq < 143000000))
+		buf[3] = 0x45;
+	else if ((freq >= 146000000) && (freq < 349100000))
+		buf[3] = 0x06;
+	else if ((freq >= 349100000) && (freq < 397100000))
+		buf[3] = 0x46;
+	else if ((freq >= 397100000) && (freq < 426000000))
+		buf[3] = 0x86;
+	else if ((freq >= 430000000) && (freq < 659100000))
+		buf[3] = 0x03;
+	else if ((freq >= 659100000) && (freq < 759100000))
+		buf[3] = 0x43;
+	else if ((freq >= 759100000) && (freq < 858000000))
+		buf[3] = 0x83;
+	else
+		return -EINVAL;
+
+	return pll_write(fe->i2c, nxt->demod_addr, nxt->tuner_addr, buf, 4);
+	
+}
+
 static void nxt6000_reset(struct dvb_frontend *fe)
 {
 
@@ -756,6 +792,13 @@
 						
 					break;
 					
+				case TUNER_TYPE_SP5730:
+
+					if ((result = sp5730_set_tv_freq(fe, param->frequency)) < 0)
+						return result;
+
+					break;
+
 				default:
 				
 					return -EFAULT;
@@ -815,6 +858,14 @@
 			nxt.clock_inversion = 0;
 	
 			dprintk("nxt6000: detected MITEL SP5659 tuner at 0x%02X\n", nxt.tuner_addr);
+		
+		} else if (pll_write(i2c, demod_addr_tbl[addr_nr], 0xC0, NULL, 0) == 0) {
+
+			nxt.tuner_addr = 0xC0;
+			nxt.tuner_type = TUNER_TYPE_SP5730;
+			nxt.clock_inversion = 0;
+	
+			dprintk("nxt6000: detected SP5730 tuner at 0x%02X\n", nxt.tuner_addr);
 		
 		} else {
 
diff -Nru a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/frontends/tda1004x.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,1158 @@
+  /*
+     Driver for Philips tda1004x OFDM Frontend
+
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published by
+     the Free Software Foundation; either version 2 of the License, or
+     (at your option) any later version.
+
+     This program is distributed in the hope that it will be useful,
+     but WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+
+     GNU General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with this program; if not, write to the Free Software
+     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   */
+
+/*
+    This driver needs a copy of the DLL "ttlcdacc.dll" from the Haupauge or Technotrend
+    windows driver saved as '/etc/dvb/tda1004x.mc'.
+    You can also pass the complete file name with the module parameter 'tda1004x_firmware'.
+
+    Currently the DLL from v2.15a of the technotrend driver is supported. Other versions can
+    be added reasonably painlessly.
+
+    Windows driver URL: http://www.technotrend.de/
+ */
+
+
+#define __KERNEL_SYSCALLS__
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/unistd.h>
+#include <linux/fcntl.h>
+#include <linux/errno.h>
+#include "dvb_frontend.h"
+#include "dvb_functions.h"
+
+#ifndef CONFIG_TDA1004X_MC_LOCATION
+#define CONFIG_TDA1004X_MC_LOCATION "/etc/dvb/tda1004x.mc"
+#endif
+
+static int tda1004x_debug = 0;
+static char *tda1004x_firmware = CONFIG_TDA1004X_MC_LOCATION;
+
+
+#define TDA10045H_ADDRESS        0x08
+#define TD1344_ADDRESS           0x61
+#define TDM1316L_ADDRESS         0x63
+#define MC44BC374_ADDRESS        0x65
+
+#define TDA1004X_CHIPID          0x00
+#define TDA1004X_AUTO            0x01
+#define TDA1004X_IN_CONF1        0x02
+#define TDA1004X_IN_CONF2        0x03
+#define TDA1004X_OUT_CONF1       0x04
+#define TDA1004X_OUT_CONF2       0x05
+#define TDA1004X_STATUS_CD       0x06
+#define TDA1004X_CONFC4          0x07
+#define TDA1004X_DSSPARE2        0x0C
+#define TDA1004X_CODE_IN         0x0D
+#define TDA1004X_FWPAGE          0x0E
+#define TDA1004X_SCAN_CPT        0x10
+#define TDA1004X_DSP_CMD         0x11
+#define TDA1004X_DSP_ARG         0x12
+#define TDA1004X_DSP_DATA1       0x13
+#define TDA1004X_DSP_DATA2       0x14
+#define TDA1004X_CONFADC1        0x15
+#define TDA1004X_CONFC1          0x16
+#define TDA1004X_SIGNAL_STRENGTH 0x1a
+#define TDA1004X_SNR             0x1c
+#define TDA1004X_REG1E           0x1e
+#define TDA1004X_REG1F           0x1f
+#define TDA1004X_CBER_RESET      0x20
+#define TDA1004X_CBER_MSB        0x21
+#define TDA1004X_CBER_LSB        0x22
+#define TDA1004X_CVBER_LUT       0x23
+#define TDA1004X_VBER_MSB        0x24
+#define TDA1004X_VBER_MID        0x25
+#define TDA1004X_VBER_LSB        0x26
+#define TDA1004X_UNCOR           0x27
+#define TDA1004X_CONFPLL_P       0x2D
+#define TDA1004X_CONFPLL_M_MSB   0x2E
+#define TDA1004X_CONFPLL_M_LSB   0x2F
+#define TDA1004X_CONFPLL_N       0x30
+#define TDA1004X_UNSURW_MSB      0x31
+#define TDA1004X_UNSURW_LSB      0x32
+#define TDA1004X_WREF_MSB        0x33
+#define TDA1004X_WREF_MID        0x34
+#define TDA1004X_WREF_LSB        0x35
+#define TDA1004X_MUXOUT          0x36
+#define TDA1004X_CONFADC2        0x37
+#define TDA1004X_IOFFSET         0x38
+
+#define dprintk if (tda1004x_debug) printk
+
+static struct dvb_frontend_info tda10045h_info = {
+	.name = "Philips TDA10045H",
+	.type = FE_OFDM,
+	.frequency_min = 51000000,
+	.frequency_max = 858000000,
+	.frequency_stepsize = 166667,
+	.caps = FE_CAN_INVERSION_AUTO |
+	    FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+	    FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+	    FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+	    FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO
+};
+
+#pragma pack(1)
+struct tda1004x_state {
+	u8 tda1004x_address;
+	u8 tuner_address;
+	u8 initialised:1;
+};
+#pragma pack()
+
+struct fwinfo {
+	int file_size;
+	int fw_offset;
+	int fw_size;
+};
+static struct fwinfo tda10045h_fwinfo[] = { {.file_size = 286720,.fw_offset = 0x34cc5,.fw_size = 30555} };
+static int tda10045h_fwinfo_count = sizeof(tda10045h_fwinfo) / sizeof(struct fwinfo);
+
+static int errno;
+
+
+static int tda1004x_write_byte(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int reg, int data)
+{
+	int ret;
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = { .addr=0, .flags=0, .buf=buf, .len=2 };
+
+	dprintk("%s: reg=0x%x, data=0x%x\n", __FUNCTION__, reg, data);
+
+        msg.addr = tda_state->tda1004x_address;
+	ret = i2c->xfer(i2c, &msg, 1);
+
+	if (ret != 1)
+		dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
+		       __FUNCTION__, reg, data, ret);
+
+	dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __FUNCTION__,
+		reg, data, ret);
+	return (ret != 1) ? -1 : 0;
+}
+
+static int tda1004x_read_byte(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int reg)
+{
+	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}};
+
+	dprintk("%s: reg=0x%x\n", __FUNCTION__, reg);
+
+        msg[0].addr = tda_state->tda1004x_address;
+        msg[1].addr = tda_state->tda1004x_address;
+	ret = i2c->xfer(i2c, msg, 2);
+
+	if (ret != 2) {
+		dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg,
+		       ret);
+		return -1;
+	}
+
+	dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __FUNCTION__,
+		reg, b1[0], ret);
+	return b1[0];
+}
+
+static int tda1004x_write_mask(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int reg, int mask, int data)
+{
+        int val;
+	dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __FUNCTION__, reg,
+		mask, data);
+
+	// read a byte and check
+	val = tda1004x_read_byte(i2c, tda_state, reg);
+	if (val < 0)
+		return val;
+
+	// mask if off
+	val = val & ~mask;
+	val |= data & 0xff;
+
+	// write it out again
+	return tda1004x_write_byte(i2c, tda_state, reg, val);
+}
+
+static int tda1004x_write_buf(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int reg, unsigned char *buf, int len)
+{
+	int i;
+	int result;
+
+	dprintk("%s: reg=0x%x, len=0x%x\n", __FUNCTION__, reg, len);
+
+	result = 0;
+	for (i = 0; i < len; i++) {
+		result = tda1004x_write_byte(i2c, tda_state, reg + i, buf[i]);
+		if (result != 0)
+			break;
+	}
+
+	return result;
+}
+
+static int tda1004x_enable_tuner_i2c(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state)
+{
+        int result;
+	dprintk("%s\n", __FUNCTION__);
+
+	result = tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 2, 2);
+	dvb_delay(1);
+	return result;
+}
+
+static int tda1004x_disable_tuner_i2c(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state)
+{
+
+	dprintk("%s\n", __FUNCTION__);
+
+	return tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 2, 0);
+}
+
+
+static int tda10045h_set_bandwidth(struct dvb_i2c_bus *i2c,
+	                           struct tda1004x_state *tda_state,
+		                   fe_bandwidth_t bandwidth)
+{
+        static u8 bandwidth_6mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x60, 0x1e, 0xa7, 0x45, 0x4f };
+        static u8 bandwidth_7mhz[] = { 0x02, 0x00, 0x37, 0x00, 0x4a, 0x2f, 0x6d, 0x76, 0xdb };
+        static u8 bandwidth_8mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x48, 0x17, 0x89, 0xc7, 0x14 };
+
+        switch (bandwidth) {
+	case BANDWIDTH_6_MHZ:
+		tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0x14);
+		tda1004x_write_buf(i2c, tda_state, TDA1004X_CONFPLL_P, bandwidth_6mhz, sizeof(bandwidth_6mhz));
+		break;
+
+	case BANDWIDTH_7_MHZ:
+		tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0x80);
+		tda1004x_write_buf(i2c, tda_state, TDA1004X_CONFPLL_P, bandwidth_7mhz, sizeof(bandwidth_7mhz));
+		break;
+
+	case BANDWIDTH_8_MHZ:
+		tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0x14);
+		tda1004x_write_buf(i2c, tda_state, TDA1004X_CONFPLL_P, bandwidth_8mhz, sizeof(bandwidth_8mhz));
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	tda1004x_write_byte(i2c, tda_state, TDA1004X_IOFFSET, 0);
+
+        // done
+        return 0;
+}
+
+
+static int tda1004x_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state)
+{
+	u8 fw_buf[65];
+	struct i2c_msg fw_msg = {.addr = 0,.flags = 0,.buf = fw_buf,.len = 0 };
+	struct i2c_msg tuner_msg = {.addr = 0,.flags = 0,.buf = 0,.len = 0 };
+	unsigned char *firmware = NULL;
+	int filesize;
+	int fd;
+	int fwinfo_idx;
+	int fw_size = 0;
+	int fw_pos;
+	int tx_size;
+        static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
+	mm_segment_t fs = get_fs();
+
+	dprintk("%s\n", __FUNCTION__);
+
+	// Load the firmware
+	set_fs(get_ds());
+	fd = open(tda1004x_firmware, 0, 0);
+	if (fd < 0) {
+		printk("%s: Unable to open firmware %s\n", __FUNCTION__,
+		       tda1004x_firmware);
+		return -EIO;
+	}
+	filesize = lseek(fd, 0L, 2);
+	if (filesize <= 0) {
+		printk("%s: Firmware %s is empty\n", __FUNCTION__,
+		       tda1004x_firmware);
+		sys_close(fd);
+		return -EIO;
+	}
+
+	// find extraction parameters
+	for (fwinfo_idx = 0; fwinfo_idx < tda10045h_fwinfo_count; fwinfo_idx++) {
+		if (tda10045h_fwinfo[fwinfo_idx].file_size == filesize)
+			break;
+	}
+	if (fwinfo_idx >= tda10045h_fwinfo_count) {
+		printk("%s: Unsupported firmware %s\n", __FUNCTION__, tda1004x_firmware);
+		sys_close(fd);
+		return -EIO;
+	}
+	fw_size = tda10045h_fwinfo[fwinfo_idx].fw_size;
+
+	// allocate buffer for it
+	firmware = vmalloc(fw_size);
+	if (firmware == NULL) {
+		printk("%s: Out of memory loading firmware\n",
+		       __FUNCTION__);
+		sys_close(fd);
+		return -EIO;
+	}
+
+	// read it!
+	lseek(fd, tda10045h_fwinfo[fwinfo_idx].fw_offset, 0);
+	if (read(fd, firmware, fw_size) != fw_size) {
+		printk("%s: Failed to read firmware\n", __FUNCTION__);
+		vfree(firmware);
+		sys_close(fd);
+		return -EIO;
+	}
+	sys_close(fd);
+	set_fs(fs);
+
+	// Disable the MC44BC374C
+	tda1004x_enable_tuner_i2c(i2c, tda_state);
+	tuner_msg.addr = MC44BC374_ADDRESS;
+	tuner_msg.buf = disable_mc44BC374c;
+	tuner_msg.len = sizeof(disable_mc44BC374c);
+	if (i2c->xfer(i2c, &tuner_msg, 1) != 1) {
+		i2c->xfer(i2c, &tuner_msg, 1);
+	}
+	tda1004x_disable_tuner_i2c(i2c, tda_state);
+
+	// set some valid bandwith parameters
+        switch(tda_state->tda1004x_address) {
+        case TDA10045H_ADDRESS:
+                tda10045h_set_bandwidth(i2c, tda_state, BANDWIDTH_8_MHZ);
+                break;
+        }
+	dvb_delay(500);
+
+	// do the firmware upload
+	tda1004x_write_byte(i2c, tda_state, TDA1004X_FWPAGE, 0);
+        fw_msg.addr = tda_state->tda1004x_address;
+	fw_pos = 0;
+	while (fw_pos != fw_size) {
+		// work out how much to send this time
+		tx_size = fw_size - fw_pos;
+		if (tx_size > 64) {
+			tx_size = 64;
+		}
+		// send the chunk
+		fw_buf[0] = TDA1004X_CODE_IN;
+		memcpy(fw_buf + 1, firmware + fw_pos, tx_size);
+		fw_msg.len = tx_size + 1;
+		if (i2c->xfer(i2c, &fw_msg, 1) != 1) {
+			vfree(firmware);
+			return -EIO;
+		}
+		fw_pos += tx_size;
+
+		dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, fw_pos);
+	}
+	dvb_delay(100);
+	vfree(firmware);
+
+	// Initialise the DSP and check upload was OK
+	tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x10, 0);
+	tda1004x_write_byte(i2c, tda_state, TDA1004X_DSP_CMD, 0x67);
+	if ((tda1004x_read_byte(i2c, tda_state, TDA1004X_DSP_DATA1) != 0x67) ||
+	    (tda1004x_read_byte(i2c, tda_state, TDA1004X_DSP_DATA2) != 0x2c)) {
+		printk("%s: firmware upload failed!\n", __FUNCTION__);
+		return -EIO;
+	}
+
+	// tda setup
+	tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 8, 0);
+        tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x10, 0x10);
+        tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0xC0, 0x0);
+        tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x20, 0);
+        tda1004x_write_byte(i2c, tda_state, TDA1004X_CONFADC1, 0x2e);
+	tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x80, 0x80);
+	tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x40, 0);
+	tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x10, 0);
+        tda1004x_write_byte(i2c, tda_state, TDA1004X_REG1E, 0);
+	tda1004x_write_byte(i2c, tda_state, TDA1004X_REG1F, 0);
+	tda1004x_write_mask(i2c, tda_state, TDA1004X_VBER_MSB, 0xe0, 0xa0);
+
+	// done
+	return 0;
+}
+
+static int tda1004x_encode_fec(int fec)
+{
+	// convert known FEC values
+	switch (fec) {
+	case FEC_1_2:
+		return 0;
+	case FEC_2_3:
+		return 1;
+	case FEC_3_4:
+		return 2;
+	case FEC_5_6:
+		return 3;
+	case FEC_7_8:
+		return 4;
+	}
+
+	// unsupported
+	return -EINVAL;
+}
+
+static int tda1004x_decode_fec(int tdafec)
+{
+	// convert known FEC values
+	switch (tdafec) {
+	case 0:
+		return FEC_1_2;
+	case 1:
+		return FEC_2_3;
+	case 2:
+		return FEC_3_4;
+	case 3:
+		return FEC_5_6;
+	case 4:
+		return FEC_7_8;
+	}
+
+	// unsupported
+	return -1;
+}
+
+static int tda1004x_set_frequency(struct dvb_i2c_bus *i2c,
+			   struct tda1004x_state *tda_state,
+			   struct dvb_frontend_parameters *fe_params)
+{
+	u8 tuner_buf[4];
+	struct i2c_msg tuner_msg = {.addr=0, .flags=0, .buf=tuner_buf, .len=sizeof(tuner_buf) };
+	int tuner_frequency;
+        u8 band, cp, filter;
+	int counter, counter2;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	// setup the frequency buffer
+	switch (tda_state->tuner_address) {
+	case TD1344_ADDRESS:
+
+		// setup tuner buffer
+		tuner_frequency =
+                        (((fe_params->frequency / 1000) * 6) + 217502) / 1000;
+		tuner_buf[0] = tuner_frequency >> 8;
+		tuner_buf[1] = tuner_frequency & 0xff;
+		tuner_buf[2] = 0x88;
+		if (fe_params->frequency < 550000000) {
+			tuner_buf[3] = 0xab;
+		} else {
+			tuner_buf[3] = 0xeb;
+		}
+
+		// tune it
+		tda1004x_enable_tuner_i2c(i2c, tda_state);
+		tuner_msg.addr = tda_state->tuner_address;
+		tuner_msg.len = 4;
+		i2c->xfer(i2c, &tuner_msg, 1);
+
+		// wait for it to finish
+		tuner_msg.len = 1;
+		tuner_msg.flags = I2C_M_RD;
+		counter = 0;
+		counter2 = 0;
+		while (counter++ < 100) {
+			if (i2c->xfer(i2c, &tuner_msg, 1) == 1) {
+				if (tuner_buf[0] & 0x40) {
+					counter2++;
+				} else {
+					counter2 = 0;
+				}
+			}
+
+			if (counter2 > 10) {
+				break;
+			}
+		}
+		tda1004x_disable_tuner_i2c(i2c, tda_state);
+		break;
+
+	case TDM1316L_ADDRESS:
+		// determine charge pump
+		tuner_frequency = fe_params->frequency + 36130000;
+		if (tuner_frequency < 87000000) {
+			return -EINVAL;
+		} else if (tuner_frequency < 130000000) {
+                        cp = 3;
+		} else if (tuner_frequency < 160000000) {
+			cp = 5;
+		} else if (tuner_frequency < 200000000) {
+			cp = 6;
+		} else if (tuner_frequency < 290000000) {
+			cp = 3;
+		} else if (tuner_frequency < 420000000) {
+			cp = 5;
+		} else if (tuner_frequency < 480000000) {
+			cp = 6;
+		} else if (tuner_frequency < 620000000) {
+			cp = 3;
+		} else if (tuner_frequency < 830000000) {
+			cp = 5;
+		} else if (tuner_frequency < 895000000) {
+			cp = 7;
+		} else {
+			return -EINVAL;
+		}
+
+		// determine band
+		if (fe_params->frequency < 49000000) {
+                        return -EINVAL;
+		} else if (fe_params->frequency < 159000000) {
+                        band = 1;
+		} else if (fe_params->frequency < 444000000) {
+			band = 2;
+		} else if (fe_params->frequency < 861000000) {
+			band = 4;
+		} else {
+			return -EINVAL;
+		}
+
+		// work out filter
+		switch (fe_params->u.ofdm.bandwidth) {
+		case BANDWIDTH_6_MHZ:
+                        // 6 MHz isn't supported directly, but set this to
+                        // the 8 MHz setting in case we can fiddle it later
+                        filter = 1;
+                        break;
+
+                case BANDWIDTH_7_MHZ:
+			filter = 0;
+			break;
+
+		case BANDWIDTH_8_MHZ:
+			filter = 1;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+
+		// calculate tuner parameters
+		tuner_frequency =
+                        (((fe_params->frequency / 1000) * 6) + 217280) / 1000;
+		tuner_buf[0] = tuner_frequency >> 8;
+		tuner_buf[1] = tuner_frequency & 0xff;
+		tuner_buf[2] = 0xca;
+		tuner_buf[3] = (cp << 5) | (filter << 3) | band;
+
+		// tune it
+		tda1004x_enable_tuner_i2c(i2c, tda_state);
+		tuner_msg.addr = tda_state->tuner_address;
+		tuner_msg.len = 4;
+                if (i2c->xfer(i2c, &tuner_msg, 1) != 1) {
+			return -EIO;
+		}
+		dvb_delay(1);
+		tda1004x_disable_tuner_i2c(i2c, tda_state);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	dprintk("%s: success\n", __FUNCTION__);
+
+	// done
+	return 0;
+}
+
+static int tda1004x_set_fe(struct dvb_i2c_bus *i2c,
+	 	           struct tda1004x_state *tda_state,
+		           struct dvb_frontend_parameters *fe_params)
+{
+	int tmp;
+
+	dprintk("%s\n", __FUNCTION__);
+
+
+	// set frequency
+	tmp = tda1004x_set_frequency(i2c, tda_state, fe_params);
+	if (tmp < 0)
+		return tmp;
+
+        // hardcoded to use auto as much as possible
+        fe_params->u.ofdm.code_rate_HP = FEC_AUTO;
+        fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
+        fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
+
+	// Set standard params.. or put them to auto
+	if ((fe_params->u.ofdm.code_rate_HP == FEC_AUTO) ||
+	    (fe_params->u.ofdm.code_rate_LP == FEC_AUTO) ||
+	    (fe_params->u.ofdm.constellation == QAM_AUTO) ||
+	    (fe_params->u.ofdm.hierarchy_information == HIERARCHY_AUTO)) {
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 1, 1);	// enable auto
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x03, 0);	// turn off constellation bits
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 0);	// turn off hierarchy bits
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0x3f, 0);	// turn off FEC bits
+	} else {
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 1, 0);	// disable auto
+
+		// set HP FEC
+		tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_HP);
+		if (tmp < 0) return tmp;
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 7, tmp);
+
+		// set LP FEC
+		if (fe_params->u.ofdm.code_rate_LP != FEC_NONE) {
+			tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_LP);
+			if (tmp < 0) return tmp;
+			tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0x38, tmp << 3);
+		}
+
+		// set constellation
+		switch (fe_params->u.ofdm.constellation) {
+		case QPSK:
+			tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 3, 0);
+			break;
+
+		case QAM_16:
+			tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 3, 1);
+			break;
+
+		case QAM_64:
+			tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 3, 2);
+			break;
+
+		default:
+			return -EINVAL;
+		}
+
+		// set hierarchy
+		switch (fe_params->u.ofdm.hierarchy_information) {
+		case HIERARCHY_NONE:
+			tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 0 << 5);
+			break;
+
+		case HIERARCHY_1:
+			tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 1 << 5);
+			break;
+
+		case HIERARCHY_2:
+			tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 2 << 5);
+			break;
+
+		case HIERARCHY_4:
+			tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 3 << 5);
+			break;
+
+		default:
+			return -EINVAL;
+		}
+	}
+
+        // set bandwidth
+        switch(tda_state->tda1004x_address) {
+        case TDA10045H_ADDRESS:
+                tda10045h_set_bandwidth(i2c, tda_state, fe_params->u.ofdm.bandwidth);
+                break;
+        }
+
+	// set inversion
+	switch (fe_params->inversion) {
+	case INVERSION_OFF:
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x20, 0);
+		break;
+
+	case INVERSION_ON:
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x20, 0x20);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	// set guard interval
+	switch (fe_params->u.ofdm.guard_interval) {
+	case GUARD_INTERVAL_1_32:
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0);
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 0 << 2);
+		break;
+
+	case GUARD_INTERVAL_1_16:
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0);
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 1 << 2);
+		break;
+
+	case GUARD_INTERVAL_1_8:
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0);
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 2 << 2);
+		break;
+
+	case GUARD_INTERVAL_1_4:
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0);
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 3 << 2);
+		break;
+
+	case GUARD_INTERVAL_AUTO:
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 2);
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 0 << 2);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	// set transmission mode
+	switch (fe_params->u.ofdm.transmission_mode) {
+	case TRANSMISSION_MODE_2K:
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 4, 0);
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x10, 0 << 4);
+		break;
+
+	case TRANSMISSION_MODE_8K:
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 4, 0);
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x10, 1 << 4);
+		break;
+
+	case TRANSMISSION_MODE_AUTO:
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 4, 4);
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x10, 0);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	// reset DSP
+	tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 8);
+	tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 0);
+	dvb_delay(10);
+
+	// done
+	return 0;
+}
+
+
+static int tda1004x_get_fe(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, struct dvb_frontend_parameters *fe_params)
+{
+
+	dprintk("%s\n", __FUNCTION__);
+
+	// inversion status
+	fe_params->inversion = INVERSION_OFF;
+	if (tda1004x_read_byte(i2c, tda_state, TDA1004X_CONFC1) & 0x20) {
+		fe_params->inversion = INVERSION_ON;
+	}
+
+	// bandwidth
+	switch (tda1004x_read_byte(i2c, tda_state, TDA1004X_WREF_LSB)) {
+	case 0x14:
+		fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
+		break;
+	case 0xdb:
+		fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
+		break;
+	case 0x4f:
+		fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
+		break;
+	}
+
+	// FEC
+	fe_params->u.ofdm.code_rate_HP =
+	    tda1004x_decode_fec(tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF2) & 7);
+	fe_params->u.ofdm.code_rate_LP =
+	    tda1004x_decode_fec((tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF2) >> 3) & 7);
+
+	// constellation
+	switch (tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 3) {
+	case 0:
+		fe_params->u.ofdm.constellation = QPSK;
+		break;
+	case 1:
+		fe_params->u.ofdm.constellation = QAM_16;
+		break;
+	case 2:
+		fe_params->u.ofdm.constellation = QAM_64;
+		break;
+	}
+
+	// transmission mode
+	fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
+	if (tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 0x10) {
+		fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+	}
+
+	// guard interval
+	switch ((tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 0x0c) >> 2) {
+	case 0:
+		fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_4;
+		break;
+	}
+
+	// hierarchy
+	switch ((tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 0x60) >> 5) {
+	case 0:
+		fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+		break;
+	case 1:
+		fe_params->u.ofdm.hierarchy_information = HIERARCHY_1;
+		break;
+	case 2:
+		fe_params->u.ofdm.hierarchy_information = HIERARCHY_2;
+		break;
+	case 3:
+		fe_params->u.ofdm.hierarchy_information = HIERARCHY_4;
+		break;
+	}
+
+	// done
+	return 0;
+}
+
+
+static int tda1004x_read_status(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, fe_status_t * fe_status)
+{
+	int status;
+        int cber;
+        int vber;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	// read status
+	status = tda1004x_read_byte(i2c, tda_state, TDA1004X_STATUS_CD);
+	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 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(i2c, tda_state, TDA1004X_CBER_LSB);
+                if (cber == -1) return -EIO;
+                status = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_MSB);
+                if (status == -1) return -EIO;
+                cber |= (status << 8);
+                tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_RESET);
+
+                if (cber != 65535) {
+                        *fe_status |= FE_HAS_VITERBI;
+                }
+        }
+
+        // if we DO have some valid VITERBI output, but don't already have SYNC
+        // bytes (i.e. not LOCKED), see if the RS decoder is getting anything valid.
+        if ((*fe_status & FE_HAS_VITERBI) && (!(*fe_status & FE_HAS_SYNC))) {
+                // read the VBER
+                vber = tda1004x_read_byte(i2c, tda_state, TDA1004X_VBER_LSB);
+                if (vber == -1) return -EIO;
+                status = tda1004x_read_byte(i2c, tda_state, TDA1004X_VBER_MID);
+                if (status == -1) return -EIO;
+                vber |= (status << 8);
+                status = tda1004x_read_byte(i2c, tda_state, TDA1004X_VBER_MSB);
+                if (status == -1) return -EIO;
+                vber |= ((status << 16) & 0x0f);
+                tda1004x_read_byte(i2c, tda_state, TDA1004X_CVBER_LUT);
+
+                // if RS has passed some valid TS packets, then we must be
+                // getting some SYNC bytes
+                if (vber < 16632) {
+                        *fe_status |= FE_HAS_SYNC;
+                }
+        }
+
+	// success
+	dprintk("%s: fe_status=0x%x\n", __FUNCTION__, *fe_status);
+	return 0;
+}
+
+static int tda1004x_read_signal_strength(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u16 * signal)
+{
+	int tmp;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	// read it
+	tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_SIGNAL_STRENGTH);
+	if (tmp < 0)
+		return -EIO;
+
+	// done
+	*signal = (tmp << 8) | tmp;
+	dprintk("%s: signal=0x%x\n", __FUNCTION__, *signal);
+	return 0;
+}
+
+
+static int tda1004x_read_snr(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u16 * snr)
+{
+	int tmp;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	// read it
+	tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_SNR);
+	if (tmp < 0)
+		return -EIO;
+        if (tmp) {
+                tmp = 255 - tmp;
+        }
+
+        // done
+	*snr = ((tmp << 8) | tmp);
+	dprintk("%s: snr=0x%x\n", __FUNCTION__, *snr);
+	return 0;
+}
+
+static int tda1004x_read_ucblocks(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u32* ucblocks)
+{
+	int tmp;
+	int tmp2;
+	int counter;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	// read the UCBLOCKS and reset
+	counter = 0;
+	tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_UNCOR);
+	if (tmp < 0)
+		return -EIO;
+        tmp &= 0x7f;
+	while (counter++ < 5) {
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_UNCOR, 0x80, 0);
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_UNCOR, 0x80, 0);
+		tda1004x_write_mask(i2c, tda_state, TDA1004X_UNCOR, 0x80, 0);
+
+		tmp2 = tda1004x_read_byte(i2c, tda_state, TDA1004X_UNCOR);
+		if (tmp2 < 0)
+			return -EIO;
+		tmp2 &= 0x7f;
+		if ((tmp2 < tmp) || (tmp2 == 0))
+			break;
+	}
+
+	// done
+	if (tmp != 0x7f) {
+		*ucblocks = tmp;
+	} else {
+		*ucblocks = 0xffffffff;
+	}
+	dprintk("%s: ucblocks=0x%x\n", __FUNCTION__, *ucblocks);
+	return 0;
+}
+
+static int tda1004x_read_ber(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u32* ber)
+{
+        int tmp;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	// read it in
+        tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_LSB);
+        if (tmp < 0) return -EIO;
+        *ber = tmp << 1;
+        tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_MSB);
+        if (tmp < 0) return -EIO;
+        *ber |= (tmp << 9);
+        tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_RESET);
+
+	// done
+	dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber);
+	return 0;
+}
+
+
+static int tda1004x_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
+{
+	int status = 0;
+	struct dvb_i2c_bus *i2c = fe->i2c;
+	struct tda1004x_state *tda_state = (struct tda1004x_state *) &(fe->data);
+
+	dprintk("%s: cmd=0x%x\n", __FUNCTION__, cmd);
+
+	switch (cmd) {
+	case FE_GET_INFO:
+                switch(tda_state->tda1004x_address) {
+                case TDA10045H_ADDRESS:
+        		memcpy(arg, &tda10045h_info, sizeof(struct dvb_frontend_info));
+                        break;
+                }
+		break;
+
+	case FE_READ_STATUS:
+		return tda1004x_read_status(i2c, tda_state, (fe_status_t *) arg);
+
+	case FE_READ_BER:
+		return tda1004x_read_ber(i2c, tda_state, (u32 *) arg);
+
+	case FE_READ_SIGNAL_STRENGTH:
+		return tda1004x_read_signal_strength(i2c, tda_state, (u16 *) arg);
+
+	case FE_READ_SNR:
+		return tda1004x_read_snr(i2c, tda_state, (u16 *) arg);
+
+	case FE_READ_UNCORRECTED_BLOCKS:
+		return tda1004x_read_ucblocks(i2c, tda_state, (u32 *) arg);
+
+	case FE_SET_FRONTEND:
+		return tda1004x_set_fe(i2c, tda_state, (struct dvb_frontend_parameters*) arg);
+
+	case FE_GET_FRONTEND:
+		return tda1004x_get_fe(i2c, tda_state, (struct dvb_frontend_parameters*) arg);
+
+	case FE_INIT:
+		// don't bother reinitialising
+		if (tda_state->initialised)
+			return 0;
+
+		// OK, perform initialisation
+                status = tda1004x_init(i2c, tda_state);
+		if (status == 0)
+			tda_state->initialised = 1;
+		return status;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+
+static int tda1004x_attach(struct dvb_i2c_bus *i2c)
+{
+        int tda1004x_address = -1;
+	int tuner_address = -1;
+	struct tda1004x_state tda_state;
+	struct i2c_msg tuner_msg = {.addr=0, .flags=0, .buf=0, .len=0 };
+        static u8 td1344_init[] = { 0x0b, 0xf5, 0x88, 0xab };
+        static u8 tdm1316l_init[] = { 0x0b, 0xf5, 0x85, 0xab };
+
+	dprintk("%s\n", __FUNCTION__);
+
+	// probe for frontend
+        tda_state.tda1004x_address = TDA10045H_ADDRESS;
+	if (tda1004x_read_byte(i2c, &tda_state, TDA1004X_CHIPID) == 0x25) {
+                tda1004x_address = TDA10045H_ADDRESS;
+                printk("tda1004x: Detected Philips TDA10045H.\n");
+        }
+
+        // did we find a frontend?
+        if (tda1004x_address == -1) {
+		return -ENODEV;
+        }
+
+	// supported tuner?
+	tda1004x_enable_tuner_i2c(i2c, &tda_state);
+	tuner_msg.addr = TD1344_ADDRESS;
+	tuner_msg.buf = td1344_init;
+	tuner_msg.len = sizeof(td1344_init);
+	if (i2c->xfer(i2c, &tuner_msg, 1) == 1) {
+                dvb_delay(1);
+		tuner_address = TD1344_ADDRESS;
+		printk("tda1004x: Detected Philips TD1344 tuner. PLEASE CHECK THIS AND REPORT BACK!.\n");
+	} else {
+		tuner_msg.addr = TDM1316L_ADDRESS;
+                tuner_msg.buf = tdm1316l_init;
+                tuner_msg.len = sizeof(tdm1316l_init);
+                if (i2c->xfer(i2c, &tuner_msg, 1) == 1) {
+                        dvb_delay(1);
+			tuner_address = TDM1316L_ADDRESS;
+			printk("tda1004x: Detected Philips TDM1316L tuner.\n");
+		}
+	}
+	tda1004x_disable_tuner_i2c(i2c, &tda_state);
+
+	// did we find a tuner?
+	if (tuner_address == -1) {
+		printk("tda1004x: Detected, but with unknown tuner.\n");
+		return -ENODEV;
+	}
+
+        // create state
+        tda_state.tda1004x_address = tda1004x_address;
+	tda_state.tuner_address = tuner_address;
+	tda_state.initialised = 0;
+
+	// register
+        switch(tda_state.tda1004x_address) {
+        case TDA10045H_ADDRESS:
+        	dvb_register_frontend(tda1004x_ioctl, i2c, (void *)(*((u32*) &tda_state)), &tda10045h_info);
+                break;
+        }
+
+	// success
+	return 0;
+}
+
+
+static
+void tda1004x_detach(struct dvb_i2c_bus *i2c)
+{
+	dprintk("%s\n", __FUNCTION__);
+
+	dvb_unregister_frontend(tda1004x_ioctl, i2c);
+}
+
+
+static
+int __init init_tda1004x(void)
+{
+	return dvb_register_i2c_device(THIS_MODULE, tda1004x_attach, tda1004x_detach);
+}
+
+
+static
+void __exit exit_tda1004x(void)
+{
+	dvb_unregister_i2c_device(tda1004x_attach);
+}
+
+module_init(init_tda1004x);
+module_exit(exit_tda1004x);
+
+MODULE_DESCRIPTION("Philips TDA10045H DVB-T Frontend");
+MODULE_AUTHOR("Andrew de Quincey & Robert Schlabbach");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(tda1004x_debug, "i");
+MODULE_PARM_DESC(tda1004x_debug, "enable verbose debug messages");
+
+MODULE_PARM(tda1004x_firmware, "s");
+MODULE_PARM_DESC(tda1004x_firmware, "Where to find the firmware file");
diff -Nru a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c
--- a/drivers/media/dvb/frontends/ves1820.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/media/dvb/frontends/ves1820.c	Sat Jul 19 12:54:25 2003
@@ -95,7 +95,7 @@
 
 static u8 ves1820_inittab [] =
 {
-	0x69, 0x6A, 0x9B, 0x0A, 0x52, 0x46, 0x26, 0x1A,
+	0x69, 0x6A, 0x9B, 0x12, 0x12, 0x46, 0x26, 0x1A,
 	0x43, 0x6A, 0xAA, 0xAA, 0x1E, 0x85, 0x43, 0x28,
 	0xE0, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
@@ -109,7 +109,7 @@
 {
 	u8 addr = GET_DEMOD_ADDR(fe->data);
         u8 buf[] = { 0x00, reg, data };
-	struct i2c_msg msg = { addr: addr, .flags = 0, .buf = buf, .len = 3 };
+	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
 	struct dvb_i2c_bus *i2c = fe->i2c;
         int ret;
 
@@ -130,8 +130,8 @@
 	u8 b0 [] = { 0x00, reg };
 	u8 b1 [] = { 0 };
 	u8 addr = GET_DEMOD_ADDR(fe->data);
-	struct i2c_msg msg [] = { { addr: addr, .flags = 0, .buf = b0, .len = 2 },
-	                   { addr: addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+	struct i2c_msg msg [] = { { .addr = addr, .flags = 0, .buf = b0, .len = 2 },
+	                   { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
 	struct dvb_i2c_bus *i2c = fe->i2c;
 	int ret;
 
@@ -147,7 +147,7 @@
 static int tuner_write (struct dvb_i2c_bus *i2c, u8 addr, u8 data [4])
 {
         int ret;
-        struct i2c_msg msg = { addr: addr, .flags = 0, .buf = data, .len = 4 };
+        struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 };
 
         ret = i2c->xfer (i2c, &msg, 1);
 
diff -Nru a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile
--- a/drivers/media/dvb/ttpci/Makefile	Sat Jul 19 12:54:23 2003
+++ b/drivers/media/dvb/ttpci/Makefile	Sat Jul 19 12:54:23 2003
@@ -3,16 +3,12 @@
 # and the AV7110 DVB device driver
 #
 
-dvb-ttpci-budget-objs := budget.o
-dvb-ttpci-budget-av-objs := budget-av.o
-dvb-ttpci-budget-ci-objs := budget-ci.o
-dvb-ttpci-budget-patch-objs := budget-patch.o
 dvb-ttpci-objs := av7110.o av7110_ipack.o av7110_ir.o
 
-obj-$(CONFIG_DVB_BUDGET) += budget-core.o dvb-ttpci-budget.o
-obj-$(CONFIG_DVB_BUDGET_CI) += budget-core.o dvb-ttpci-budget-ci.o
-obj-$(CONFIG_DVB_BUDGET_AV) += budget-core.o dvb-ttpci-budget-av.o
-obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-core.o dvb-ttpci-budget-patch.o
-obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o
+obj-$(CONFIG_DVB_BUDGET) += budget-core.o budget.o ttpci-eeprom.o
+obj-$(CONFIG_DVB_BUDGET_AV) += budget-core.o budget-av.o ttpci-eeprom.o
+obj-$(CONFIG_DVB_BUDGET_CI) += budget-core.o budget-ci.o ttpci-eeprom.o
+obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-core.o budget-patch.o ttpci-eeprom.o
+obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o ttpci-eeprom.o
 
 EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
diff -Nru a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
--- a/drivers/media/dvb/ttpci/av7110.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/media/dvb/ttpci/av7110.c	Sat Jul 19 12:54:26 2003
@@ -86,6 +86,7 @@
 	#define DEB_EE(x)
 #endif
 
+#include "ttpci-eeprom.h"
 #include "av7110.h"
 #include "av7110_ipack.h"
 
@@ -110,7 +111,8 @@
 
 int av7110_num = 0;
 
-#define FW_CI_LL_SUPPORT(arm_app) (((arm_app) >> 16) & 0x8000)
+#define FW_CI_LL_SUPPORT(arm_app) ((arm_app) & 0x80000000)
+#define FW_VERSION(arm_app)       ((arm_app) & 0x0000FFFF)
 
 /****************************************************************************
  * DEBI functions
@@ -1089,7 +1091,7 @@
         u32 stat;
 #endif
 
-	DEB_EE(("av7110: %p\n",av7110));
+//	DEB_EE(("av7110: %p\n",av7110));
 
 	if (!av7110->arm_ready) {
 		DEB_D(("arm not ready.\n"));
@@ -1166,7 +1168,7 @@
 {
         int ret;
         
- 	DEB_EE(("av7110: %p\n",av7110));
+// 	DEB_EE(("av7110: %p\n",av7110));
 
         if (!av7110->arm_ready) {
 		DEB_D(("arm not ready.\n"));
@@ -1190,7 +1192,7 @@
         u16 buf[num+2];
         int i, ret;
 
- 	DEB_EE(("av7110: %p\n",av7110));
+// 	DEB_EE(("av7110: %p\n",av7110));
 
         buf[0]=(( type << 8 ) | com);
         buf[1]=num;
@@ -1332,7 +1334,7 @@
 
 static inline int SendDAC(struct av7110 *av7110, u8 addr, u8 data)
 {
- 	DEB_EE(("av7110: %p\n",av7110));
+// 	DEB_EE(("av7110: %p\n",av7110));
 
         return outcom(av7110, COMTYPE_AUDIODAC, AudioDAC, 2, addr, data);
 }
@@ -1659,6 +1661,24 @@
                   color, ((blend>>4)&0x0f));
 }
 
+static int OSDSetPalette(struct av7110 *av7110, u32 *colors, u8 first, u8 last)
+{
+       int i;
+       int length = last - first + 1;
+
+       if (length * 4 > DATA_BUFF3_SIZE)
+               return -1;
+
+       for (i=0; i<length; i++) {
+               u32 blend = (colors[i] & 0xF0000000) >> 4;
+               u32 yuv = blend ? RGB2YUV(colors[i] & 0xFF, (colors[i] >> 8) & 0xFF, (colors[i] >> 16) & 0xFF) | blend : 0;
+               yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16); // TODO kls2003-06-15: not sure if this is endian-proof
+               wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i*4, yuv, 4);
+       }
+       return outcom(av7110, COMTYPE_OSD, Set_Palette, 4,
+               av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]], first, last);
+}
+
 static int OSDSetBlock(struct av7110 *av7110, int x0, int y0, int x1, int y1, int inc, u8 *data)
 {
         uint w, h, bpp, bpl, size, lpb, bnum, brest;
@@ -1721,6 +1741,9 @@
                 return 0;
         case OSD_SetPalette:
         {      
+                if (FW_VERSION(av7110->arm_app) >= 0x2618)
+                        OSDSetPalette(av7110, (u32 *)dc->data, dc->color, dc->x0);
+                else {
                 int i, len=dc->x0-dc->color+1;
                 u8 *colors=(u8 *)dc->data;
 
@@ -1728,6 +1751,7 @@
                         OSDSetColor(av7110, dc->color+i,
                                     colors[i*4]  , colors[i*4+1],
                                     colors[i*4+2], colors[i*4+3]);
+                }
                 return 0;
         }
         case OSD_SetTrans: 
@@ -2087,28 +2111,28 @@
 
 static inline void TestMode(struct av7110 *av7110, int mode)
 {
- 	DEB_EE(("av7110: %p\n",av7110));
+//	DEB_EE(("av7110: %p\n",av7110));
         outcom(av7110, COMTYPE_ENCODER, SetTestMode, 1, mode);
 }
 
 static inline void VidMode(struct av7110 *av7110, int mode)
 {
- 	DEB_EE(("av7110: %p\n",av7110));
+// 	DEB_EE(("av7110: %p\n",av7110));
         outcom(av7110, COMTYPE_ENCODER, SetVidMode, 1, mode);
 }
            
 
-static inline int vidcom(struct av7110 *av7110, u32 com, u32 arg)
+static int inline vidcom(struct av7110 *av7110, u32 com, u32 arg)
 {
- 	DEB_EE(("av7110: %p\n",av7110));
+// 	DEB_EE(("av7110: %p\n",av7110));
         return outcom(av7110, 0x80, 0x02, 4, 
                       (com>>16), (com&0xffff), 
                       (arg>>16), (arg&0xffff));
 }
 
-static inline int audcom(struct av7110 *av7110, u32 com)
+static int inline audcom(struct av7110 *av7110, u32 com)
 {
-	DEB_EE(("av7110: %p\n",av7110));
+//	DEB_EE(("av7110: %p\n",av7110));
 	return outcom(av7110, 0x80, 0x03, 4, 
                       (com>>16), (com&0xffff));
 }
@@ -2583,38 +2607,274 @@
  * V4L SECTION
  ****************************************************************************/
 
-int av7110_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) 
+static struct v4l2_input inputs[2] = {
+	{ 0,	"DVB",		V4L2_INPUT_TYPE_CAMERA,	1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, 
+	{ 1,	"ANALOG",	V4L2_INPUT_TYPE_TUNER,	2, 1, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
+};
+
+/* taken from ves1820.c */
+static int ves1820_writereg(struct saa7146_dev *dev, u8 reg, u8 data)
+{
+	u8 addr = 0x09;
+        u8 buf[] = { 0x00, reg, data };
+	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
+
+  	DEB_EE(("av7710: dev: %p\n",dev));
+
+	if( 1 != saa7146_i2c_transfer(dev, &msg, 1, 1)) {
+		return -1;
+	}
+	return 0;
+}
+
+static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4])
+{
+        struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 };
+
+  	DEB_EE(("av7710: dev: %p\n",dev));
+
+	if( 1 != saa7146_i2c_transfer(dev, &msg, 1, 1)) {
+		return -1;
+	}
+	return 0;
+}
+
+
+/**
+ *   set up the downconverter frequency divisor for a
+ *   reference clock comparision frequency of 62.5 kHz.
+ */
+static int tuner_set_tv_freq (struct saa7146_dev *dev, u32 freq)
+{
+        u32 div;
+	u8 config;
+        u8 buf [4];
+
+ 	DEB_EE(("av7710: freq: 0x%08x\n",freq));
+
+	/* magic number: 56. tuning with the frequency given by v4l2
+	   is always off by 56*62.5 kHz...*/
+	div = freq + 56;
+
+	buf[0] = (div >> 8) & 0x7f;
+	buf[1] = div & 0xff;
+	buf[2] = 0x8e;
+
+	if (freq < 16*168.25 ) 
+		config = 0xa0;
+	else if (freq < 16*447.25) 
+		config = 0x90;
+	else
+		config = 0x30;
+	config &= ~0x02;
+
+	buf[3] = config;
+
+        return tuner_write (dev, 0x61, buf);
+}
+
+static struct saa7146_standard analog_standard[];
+static struct saa7146_standard dvb_standard[];
+static struct saa7146_standard standard[];
+
+int av7110_dvb_c_switch(struct saa7146_fh *fh)
+{
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
+	u16 buf[3] = { ((COMTYPE_AUDIODAC << 8) + ADSwitch), 1, 1 };
+
+	u8 band = 0;
+	int source, sync;
+	struct saa7146_fh *ov_fh = NULL;
+	int restart_overlay = 0;
+
+	DEB_EE(("av7110: %p\n",av7110));
+
+	if( vv->ov_data != NULL ) {
+		ov_fh = vv->ov_data->fh;
+		saa7146_stop_preview(ov_fh);
+		restart_overlay = 1;
+	}
+
+	if( 0 != av7110->current_input ) {
+		buf[2] = 0;
+		band = 0x68; /* analog band */
+		source = SAA7146_HPS_SOURCE_PORT_B;
+		sync = SAA7146_HPS_SYNC_PORT_B;
+		memcpy(standard,analog_standard,sizeof(struct saa7146_standard)*2);
+	} else {
+		buf[2] = 1;
+		band = 0x28; /* digital band */	
+		source = SAA7146_HPS_SOURCE_PORT_A;
+		sync = SAA7146_HPS_SYNC_PORT_A;
+		memcpy(standard,dvb_standard,sizeof(struct saa7146_standard)*2);
+	}
+
+	/* hmm, this does not do anything!? */
+	if (OutCommand(av7110, buf, 3)) {
+		printk("ADSwitch error\n");
+	}
+
+	if( 0 != ves1820_writereg(dev, 0x0f, band )) {
+		printk("setting band in demodulator failed.\n");
+	}
+	saa7146_set_hps_source_and_sync(dev, source, sync);
+
+	/* restart overlay if it was active before */
+	if( 0 != restart_overlay ) {
+		saa7146_start_preview(ov_fh);
+	}
+
+	return 0;
+}
+
+int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) 
 {
+	struct saa7146_dev *dev = fh->dev;
+	struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
  	DEB_EE(("saa7146_dev: %p\n",dev));
 
 	switch(cmd) {
+	case VIDIOC_G_TUNER:
+	{
+		struct v4l2_tuner *t = arg;
+
+		DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
+
+		if( 0 == av7110->has_analog_tuner || av7110->current_input != 1 ) {
+			return -EINVAL;
+		}
+
+		memset(t,0,sizeof(*t));
+		strcpy(t->name, "Television");
+
+		t->type = V4L2_TUNER_ANALOG_TV;
+		t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
+		t->rangelow = 772;	/* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */
+		t->rangehigh = 13684;	/* 855.25 MHz / 62.5 kHz = 13684 */
+		/* FIXME: add the real signal strength here */
+		t->signal = 0xffff;
+		t->afc = 0;		
+		/* fixme: real autodetection here */
+		t->rxsubchans 	= V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
+
+		return 0;
+	}
+	case VIDIOC_S_TUNER:
+	{
+		struct v4l2_tuner *t = arg;
+		
+		DEB_EE(("VIDIOC_S_TUNER: %d\n", t->index));
+
+		if( 0 == av7110->has_analog_tuner || av7110->current_input != 1 ) {
+			return -EINVAL;
+		}
+
+
+		switch(t->audmode) {
+			case V4L2_TUNER_MODE_STEREO: {
+				DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n"));
+				break;
+			}
+			case V4L2_TUNER_MODE_LANG1: {
+				DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n"));
+				break;
+			}
+			case V4L2_TUNER_MODE_LANG2: {
+				DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n"));
+				break;
+			}
+			default: { /* case V4L2_TUNER_MODE_MONO: {*/
+				DEB_D(("VIDIOC_S_TUNER: TDA9840_SET_MONO\n"));
+				break;
+			}
+		}
+
+		return 0;
+	}
+	case VIDIOC_G_FREQUENCY:
+	{
+		struct v4l2_frequency *f = arg;
+
+		DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency));
+
+		if( 0 == av7110->has_analog_tuner || av7110->current_input != 1 ) {
+			return -EINVAL;
+		}
+
+		memset(f,0,sizeof(*f));
+		f->type = V4L2_TUNER_ANALOG_TV;
+		f->frequency =  av7110->current_freq;
+
+		return 0;
+	}
+	case VIDIOC_S_FREQUENCY:
+	{
+		struct v4l2_frequency *f = arg;
+
+		DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n",f->frequency));
+
+		if( 0 == av7110->has_analog_tuner || av7110->current_input != 1 ) {
+			return -EINVAL;
+		}
+
+		if (V4L2_TUNER_ANALOG_TV != f->type)
+			return -EINVAL;
+
+		/* tune in desired frequency */			
+		tuner_set_tv_freq(dev, f->frequency);
+		av7110->current_freq = f->frequency;
+
+		return 0;
+	}
 	case VIDIOC_ENUMINPUT:
 	{
 		struct v4l2_input *i = arg;
 		
+		DEB_EE(("VIDIOC_ENUMINPUT: %d\n", i->index));
+
+		if( 0 != av7110->has_analog_tuner ) {
+			if( i->index < 0 || i->index >= 2) {
+				return -EINVAL;
+			}
+		} else {
 		if( i->index != 0 ) {
 			return -EINVAL;
 		}
+		}		
 
-		memset(i,0,sizeof(*i));
-		i->index = 0;
-		strcpy(i->name, "DVB");
-		i->type = V4L2_INPUT_TYPE_CAMERA;
-		i->audioset = 1;
+		memcpy(i, &inputs[i->index], sizeof(struct v4l2_input));
 		
 		return 0;
 	}
 	case VIDIOC_G_INPUT:
 	{
 		int *input = (int *)arg;
-		*input = 0;
+		*input = av7110->current_input;
+		DEB_EE(("VIDIOC_G_INPUT: %d\n", *input));
 		return 0;		
 	}	
 	case VIDIOC_S_INPUT:
 	{
+		int input = *(int *)arg;
+
+		DEB_EE(("VIDIOC_S_INPUT: %d\n", input));
+
+		if( 0 == av7110->has_analog_tuner ) {
 		return 0;		
 	}	
+		
+		if( input < 0 || input >= 2) {
+			return -EINVAL;
+		}
+		
+		/* fixme: switch inputs here */
+		av7110->current_input = input;
+		return av7110_dvb_c_switch(fh);
+	}	
 	default:
+		printk("no such ioctl\n");
 		return -ENOIOCTLCMD;
 	}
 	return 0;
@@ -2997,7 +3257,7 @@
 	DEB_EE(("av7110: fwstc = %04hx %04hx %04hx %04hx\n",
 			fwstc[0], fwstc[1], fwstc[2], fwstc[3]));
 
-	*stc =  (((uint64_t)fwstc[2] & 1) << 32) |
+	*stc =  (((uint64_t)(~fwstc[2]) & 1) << 32) |
 		(((uint64_t)fwstc[1])     << 16) | ((uint64_t)fwstc[0]);
 	*base = 1;
 
@@ -4006,7 +4266,6 @@
 #endif
 //        }
         
-        av7110->dvb_net.card_num=av7110->dvb_adapter->num;
         dvb_net_init(av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
 
 	return 0;
@@ -4061,9 +4320,16 @@
 	{ VIDIOC_ENUMINPUT, 	SAA7146_EXCLUSIVE },
 	{ VIDIOC_G_INPUT,	SAA7146_EXCLUSIVE },
 	{ VIDIOC_S_INPUT,	SAA7146_EXCLUSIVE },
+	{ VIDIOC_G_FREQUENCY,	SAA7146_EXCLUSIVE },
+	{ VIDIOC_S_FREQUENCY, 	SAA7146_EXCLUSIVE },
+	{ VIDIOC_G_TUNER, 	SAA7146_EXCLUSIVE },
+	{ VIDIOC_S_TUNER, 	SAA7146_EXCLUSIVE },
 	{ 0, 0 }
 };
 
+static struct saa7146_ext_vv av7110_vv_data_st;
+static struct saa7146_ext_vv av7110_vv_data_c;
+
 static int av7110_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *pci_ext)
 {
 	struct av7110 *av7110 = NULL;
@@ -4081,7 +4347,16 @@
 
 	DEB_EE(("dev: %p, av7110: %p\n",dev,av7110));
 
-	if (saa7146_vv_init(dev)) {
+	/* special case DVB-C: these cards have an analog tuner
+	   plus need some special handling, so we have separate
+	   saa7146_ext_vv data for these... */
+	if (dev->pci->subsystem_vendor == 0x110a) {
+		ret = saa7146_vv_init(dev, &av7110_vv_data_c);
+	} else {
+		ret = saa7146_vv_init(dev, &av7110_vv_data_st);
+	}
+	
+	if ( 0 != ret) {
 		ERR(("cannot init capture device. skipping.\n"));
 		kfree(av7110);
 		return -1;
@@ -4114,6 +4389,8 @@
 		return -ENOMEM;
 	}
 
+	ttpci_eeprom_parse_mac(av7110->i2c_bus);
+
 	saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
 	saa7146_write(dev, BCS_CTRL, 0x80400040);
 
@@ -4186,9 +4463,9 @@
 	bootarm(av7110);
 	firmversion(av7110);
 
-	if ((av7110->arm_app&0xffff)<0x2501)
+	if (FW_VERSION(av7110->arm_app)<0x2501)
 		printk ("av7110: Warning, firmware version 0x%04x is too old. "
-			"System might be unstable!\n", av7110->arm_app&0xffff);
+			"System might be unstable!\n", FW_VERSION(av7110->arm_app));
 
 	kernel_thread(arm_thread, (void *) av7110, 0);
 
@@ -4199,6 +4476,8 @@
 	VidMode(av7110, vidmode);
 
 	/* remaining inits according to card and frontend type */
+	av7110->has_analog_tuner = 0;
+	av7110->current_input = 0;
 	if (i2c_writereg(av7110, 0x20, 0x00, 0x00)==1) {
 		printk ("av7110(%d): Crystal audio DAC detected\n",
 			av7110->dvb_adapter->num);
@@ -4225,6 +4504,31 @@
 			msp_writereg(av7110, 0x12, 0x000a, 0x0220); // SCART 1 source
 			msp_writereg(av7110, 0x12, 0x0007, 0x7f00); // SCART 1 volume
 			msp_writereg(av7110, 0x12, 0x000d, 0x4800); // prescale SCART
+		
+		if (i2c_writereg(av7110, 0x48, 0x01, 0x00)!=1) {
+			INFO(("saa7113 not accessible.\n"));
+		} else {
+			av7110->has_analog_tuner = 1;
+			/* init the saa7113 */
+			i2c_writereg(av7110, 0x48, 0x02, 0xd0); i2c_writereg(av7110, 0x48, 0x03, 0x23); i2c_writereg(av7110, 0x48, 0x04, 0x00);
+			i2c_writereg(av7110, 0x48, 0x05, 0x00); i2c_writereg(av7110, 0x48, 0x06, 0xe9); i2c_writereg(av7110, 0x48, 0x07, 0x0d);
+			i2c_writereg(av7110, 0x48, 0x08, 0x98); i2c_writereg(av7110, 0x48, 0x09, 0x02); i2c_writereg(av7110, 0x48, 0x0a, 0x80);
+			i2c_writereg(av7110, 0x48, 0x0b, 0x40); i2c_writereg(av7110, 0x48, 0x0c, 0x40); i2c_writereg(av7110, 0x48, 0x0d, 0x00);
+			i2c_writereg(av7110, 0x48, 0x0e, 0x01);	i2c_writereg(av7110, 0x48, 0x0f, 0x7c); i2c_writereg(av7110, 0x48, 0x10, 0x48);
+			i2c_writereg(av7110, 0x48, 0x11, 0x0c);	i2c_writereg(av7110, 0x48, 0x12, 0x8b);	i2c_writereg(av7110, 0x48, 0x13, 0x10);
+			i2c_writereg(av7110, 0x48, 0x14, 0x00);	i2c_writereg(av7110, 0x48, 0x15, 0x00);	i2c_writereg(av7110, 0x48, 0x16, 0x00);
+			i2c_writereg(av7110, 0x48, 0x17, 0x00);	i2c_writereg(av7110, 0x48, 0x18, 0x00);	i2c_writereg(av7110, 0x48, 0x19, 0x00);
+			i2c_writereg(av7110, 0x48, 0x1a, 0x00);	i2c_writereg(av7110, 0x48, 0x1b, 0x00);	i2c_writereg(av7110, 0x48, 0x1c, 0x00);
+			i2c_writereg(av7110, 0x48, 0x1d, 0x00);	i2c_writereg(av7110, 0x48, 0x1e, 0x00);
+		}	
+
+		memcpy(standard,dvb_standard,sizeof(struct saa7146_standard)*2);
+		/* set dd1 stream a & b */
+      		saa7146_write(dev, DD1_STREAM_B, 0x00000000);
+		saa7146_write(dev, DD1_INIT, 0x0200700);
+		saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
+
+
 	} else if (dev->pci->subsystem_vendor == 0x110a) {
 		printk("av7110(%d): DVB-C w/o analog module detected\n",
 			av7110->dvb_adapter->num);
@@ -4330,6 +4634,16 @@
 	{ "NTSC", V4L2_STD_NTSC, 0x10, 244, 480, 0x40, 708, 709, 480, 640 },
 };
 
+static struct saa7146_standard analog_standard[] = {
+	{ "PAL", V4L2_STD_PAL, 0x18, 288, 576, 0x08, 708, 709, 576, 768 },
+	{ "NTSC", V4L2_STD_NTSC, 0x10, 244, 480, 0x40, 708, 709, 480, 640 },
+};
+
+static struct saa7146_standard dvb_standard[] = {
+	{ "PAL", V4L2_STD_PAL, 0x14, 288, 576, 0x4a, 708, 709, 576, 768 },
+	{ "NTSC", V4L2_STD_NTSC, 0x10, 244, 480, 0x40, 708, 709, 480, 640 },
+};
+
 static struct saa7146_extension av7110_extension;
 
 #define MAKE_AV7110_INFO(x_var,x_name) \
@@ -4387,7 +4701,7 @@
 }
 
 
-static struct saa7146_ext_vv av7110_vv_data = {
+static struct saa7146_ext_vv av7110_vv_data_st = {
 	.inputs		= 1,
 	.audios 	= 1,
 	.capabilities	= 0,
@@ -4401,9 +4715,23 @@
 	.ioctl		= av7110_ioctl,
 };
 
+static struct saa7146_ext_vv av7110_vv_data_c = {
+	.inputs		= 1,
+	.audios 	= 1,
+	.capabilities	= V4L2_CAP_TUNER,
+	.flags		= 0,
+
+	.stds		= &standard[0],
+	.num_stds	= sizeof(standard)/sizeof(struct saa7146_standard),
+	.std_callback	= &std_callback, 
+
+	.ioctls		= &ioctls[0],
+	.ioctl		= av7110_ioctl,
+};
+
+
 static struct saa7146_extension av7110_extension = {
 	.name		= "dvb\0",
-	.ext_vv_data	= &av7110_vv_data,
 
 	.module		= THIS_MODULE,
 	.pci_tbl	= &pci_tbl[0],
@@ -4442,7 +4770,11 @@
 
 MODULE_PARM(av7110_debug,"i");
 MODULE_PARM(vidmode,"i");
+MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC");
 MODULE_PARM(pids_off,"i");
+MODULE_PARM_DESC(pids_off,"clear video/audio/PCR PID filters when demux is closed");
 MODULE_PARM(adac,"i");
+MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)");
 MODULE_PARM(hw_sections, "i");
+MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware");
 
diff -Nru a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
--- a/drivers/media/dvb/ttpci/av7110.h	Sat Jul 19 12:54:21 2003
+++ b/drivers/media/dvb/ttpci/av7110.h	Sat Jul 19 12:54:21 2003
@@ -153,7 +153,8 @@
 	BlitBmp,
 	ReleaseBmp,
 	SetWTrans,
-	SetWNoTrans
+        SetWNoTrans,
+        Set_Palette
 };
 
 enum av7110_pid_command { 
@@ -405,6 +406,11 @@
 	struct dvb_i2c_bus	*i2c_bus;	
 	char			*card_name;
 
+	/* support for analog module of dvb-c */
+	int			has_analog_tuner;
+	int			current_input;
+	u32			current_freq;
+				
 	struct tasklet_struct   debi_tasklet;
 	struct tasklet_struct   gpio_tasklet;
 
@@ -571,6 +577,9 @@
 
 #define DATA_BUFF2_BASE	(DATA_BUFF1_BASE+DATA_BUFF1_SIZE)
 #define DATA_BUFF2_SIZE	0x0800
+
+#define DATA_BUFF3_BASE (DATA_BUFF2_BASE+DATA_BUFF2_SIZE)
+#define DATA_BUFF3_SIZE 0x0400
 
 #define Reserved	(DPRAM_BASE + 0x1E00)
 #define Reserved_SIZE	0x1C0
diff -Nru a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
--- a/drivers/media/dvb/ttpci/budget-av.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/media/dvb/ttpci/budget-av.c	Sat Jul 19 12:54:26 2003
@@ -170,6 +170,7 @@
 	return err;
 }
 
+static struct saa7146_ext_vv vv_data;
 
 static int budget_av_attach (struct saa7146_dev* dev,
 		      struct saa7146_pci_extension_data *info)
@@ -207,16 +208,22 @@
 	dvb_delay(500);
 
 	if ((err = saa7113_init (budget_av))) {
-		budget_av_detach(dev);
+		/* fixme: proper cleanup here */
+		ERR(("cannot init saa7113.\n"));
+		return err;
+	}
+
+	if ( 0 != saa7146_vv_init(dev,&vv_data)) {
+		/* fixme: proper cleanup here */
+		ERR(("cannot init vv subsystem.\n"));
 		return err;
 	}
 
-	saa7146_vv_init(dev);
 	if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1",
 					   VFL_TYPE_GRABBER)))
 	{
+		/* fixme: proper cleanup here */
 		ERR(("cannot register capture v4l2 device.\n"));
-		budget_av_detach(dev);
 		return err;
 	}
 
@@ -256,8 +263,9 @@
 };
 
 
-static int av_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) 
+static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) 
 {
+	struct saa7146_dev *dev = fh->dev;
 	struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
 /*
 	struct saa7146_vv *vv = dev->vv_data; 
@@ -299,11 +307,19 @@
 }
 
 static struct saa7146_standard standard[] = {
-	{ "PAL",	V4L2_STD_PAL,	SAA7146_PAL_VALUES },
-	{ "NTSC",	V4L2_STD_NTSC,	SAA7146_NTSC_VALUES },
+	{
+		.name	= "PAL", 	.id	= V4L2_STD_PAL,
+		.v_offset	= 0x17,	.v_field 	= 288,	.v_calc		= 576,
+		.h_offset	= 0x14,	.h_pixels 	= 680,	.h_calc		= 680+1,
+		.v_max_out	= 576,	.h_max_out	= 768,
+	}, {
+		.name	= "NTSC", 	.id	= V4L2_STD_NTSC,
+		.v_offset	= 0x16,	.v_field 	= 240,	.v_calc		= 480,
+		.h_offset	= 0x06,	.h_pixels 	= 708,	.h_calc		= 708+1,
+		.v_max_out	= 480,	.h_max_out	= 640,
+	}
 };
 
-
 static struct saa7146_ext_vv vv_data = {
 	.inputs		= 2,
 	.capabilities	= 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
@@ -337,8 +353,6 @@
 	.module		= THIS_MODULE,
 	.attach		= budget_av_attach,
 	.detach		= budget_av_detach,
-
-	.ext_vv_data	= &vv_data,
 
 	.irq_mask	= MASK_10,
 	.irq_func	= ttpci_budget_irq10_handler,
diff -Nru a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
--- a/drivers/media/dvb/ttpci/budget-ci.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/media/dvb/ttpci/budget-ci.c	Sat Jul 19 12:54:23 2003
@@ -371,7 +371,6 @@
 static struct saa7146_extension budget_extension = {
 	.name		= "budget_ci dvb\0",
 	.flags	 	= 0,
-	.ext_vv_data	= NULL,
 
 	.module		= THIS_MODULE,
 	.pci_tbl	= &pci_tbl[0],
diff -Nru a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
--- a/drivers/media/dvb/ttpci/budget-core.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/media/dvb/ttpci/budget-core.c	Sat Jul 19 12:54:24 2003
@@ -1,4 +1,5 @@
 #include "budget.h"
+#include "ttpci-eeprom.h"
 
 int budget_debug = 0;
 
@@ -165,7 +166,6 @@
         if (ret < 0)
                 return ret;
 
-        budget->dvb_net.card_num = budget->dvb_adapter->num;
         dvb_net_init(budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx);
 
 	return 0;
@@ -222,7 +222,7 @@
            get recognized before the main driver is loaded */
         saa7146_write(dev, GPIO_CTRL, 0x500000);
 	
-	saa7146_i2c_adapter_prepare(dev, NULL, SAA7146_I2C_BUS_BIT_RATE_3200);
+	saa7146_i2c_adapter_prepare(dev, NULL, SAA7146_I2C_BUS_BIT_RATE_120);
 
 	budget->i2c_bus = dvb_register_i2c_bus (master_xfer, dev,
 						budget->dvb_adapter, 0);
@@ -231,6 +231,8 @@
 		dvb_unregister_adapter (budget->dvb_adapter);
 		return -ENOMEM;
 	}
+
+	ttpci_eeprom_parse_mac(budget->i2c_bus);
 
 	if( NULL == (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci,length,&budget->pt))) {
 		ret = -ENOMEM;
diff -Nru a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
--- a/drivers/media/dvb/ttpci/budget-patch.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/media/dvb/ttpci/budget-patch.c	Sat Jul 19 12:54:23 2003
@@ -165,6 +165,7 @@
 {
         struct budget_patch *budget;
         int err;
+	int count = 0;
 
         if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL)))
                 return -ENOMEM;
@@ -263,7 +264,6 @@
 static struct saa7146_extension budget_extension = {
         .name           = "budget_patch dvb\0",
         .flags          = 0,
-        .ext_vv_data    = NULL,
         
         .module         = THIS_MODULE,
         .pci_tbl        = pci_tbl,
diff -Nru a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
--- a/drivers/media/dvb/ttpci/budget.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/media/dvb/ttpci/budget.c	Sat Jul 19 12:54:25 2003
@@ -192,6 +192,7 @@
 MAKE_BUDGET_INFO(ttbs,	"TT-Budget/WinTV-NOVA-S  PCI",	BUDGET_TT);
 MAKE_BUDGET_INFO(ttbc,	"TT-Budget/WinTV-NOVA-C  PCI",	BUDGET_TT);
 MAKE_BUDGET_INFO(ttbt,	"TT-Budget/WinTV-NOVA-T  PCI",	BUDGET_TT);
+MAKE_BUDGET_INFO(ttbt2,	"TT-Budget/WinTV-NOVA-T  PCI",	BUDGET_TT);
 MAKE_BUDGET_INFO(satel,	"SATELCO Multimedia PCI",	BUDGET_TT_HW_DISEQC);
 /* Uncomment for Budget Patch */
 /*MAKE_BUDGET_INFO(fs_1_3,"Siemens/Technotrend/Hauppauge PCI rev1.3+Budget_Patch", BUDGET_PATCH);*/
@@ -202,6 +203,7 @@
 	MAKE_EXTENSION_PCI(ttbs,  0x13c2, 0x1003),
 	MAKE_EXTENSION_PCI(ttbc,  0x13c2, 0x1004),
 	MAKE_EXTENSION_PCI(ttbt,  0x13c2, 0x1005),
+	MAKE_EXTENSION_PCI(ttbt2,  0x13c2, 0x1011),	
 	MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
 	{
 		.vendor    = 0,
@@ -213,7 +215,6 @@
 static struct saa7146_extension budget_extension = {
 	.name		= "budget dvb\0",
 	.flags	 	= 0,
-	.ext_vv_data	= NULL,
 	
 	.module		= THIS_MODULE,
 	.pci_tbl	= pci_tbl,
diff -Nru a/drivers/media/dvb/ttpci/ttpci-eeprom.c b/drivers/media/dvb/ttpci/ttpci-eeprom.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/ttpci/ttpci-eeprom.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,120 @@
+/*
+    Retrieve encoded MAC address from 24C16 serial 2-wire EEPROM,
+    decode it and store it in the associated adapter struct for
+    use by dvb_net.c
+
+    This code was tested on TT-Budget/WinTV-NOVA-CI PCI boards with
+    Atmel and ST Microelectronics EEPROMs.
+
+    This card appear to have the 24C16 write protect held to ground,
+    thus permitting normal read/write operation. Theoretically it
+    would be possible to write routines to burn a different (encoded)
+    MAC address into the EEPROM.
+
+    Robert Schlabbach	GMX
+    Michael Glaum	KVH Industries
+    Holger Waechtler	Convergence
+
+    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 <asm/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include "dvb_i2c.h"
+#include "dvb_functions.h"
+
+#if 1
+#define dprintk(x...) printk(x)
+#else
+#define dprintk(x...)
+#endif
+
+
+static int ttpci_eeprom_read_encodedMAC(struct dvb_i2c_bus *i2c, u8 * encodedMAC)
+{
+	int ret;
+	u8 b0[] = { 0xd4 };
+
+	struct i2c_msg msg[] = {
+		{.addr = 0x50,.flags = 0,.buf = b0,.len = 1},
+		{.addr = 0x50,.flags = I2C_M_RD,.buf = encodedMAC,.len = 6}
+	};
+
+	dprintk("%s\n", __FUNCTION__);
+
+	ret = i2c->xfer(i2c, msg, 2);
+
+	if (ret != 2)		/* Assume EEPROM isn't there */
+		return (-ENODEV);
+
+	return 0;
+}
+
+static void decodeMAC(u8 * decodedMAC, const u8 * encodedMAC)
+{
+	u8 ormask0[3] = { 0x54, 0x7B, 0x9E };
+	u8 ormask1[3] = { 0xD3, 0xF1, 0x23 };
+	u8 low;
+	u8 high;
+	u8 shift;
+	int i;
+
+	decodedMAC[0] = 0x00;
+	decodedMAC[1] = 0xD0;
+	decodedMAC[2] = 0x5C;
+
+	for (i = 0; i < 3; i++) {
+		low = encodedMAC[2 * i] ^ ormask0[i];
+		high = encodedMAC[2 * i + 1] ^ ormask1[i];
+		shift = (high >> 6) & 0x3;
+
+		decodedMAC[5 - i] = ((high << 8) | low) >> shift;
+	}
+
+}
+
+
+int ttpci_eeprom_parse_mac(struct dvb_i2c_bus *i2c)
+{
+	int ret;
+	u8 encodedMAC[6];
+	u8 decodedMAC[6];
+
+	ret = ttpci_eeprom_read_encodedMAC(i2c, encodedMAC);
+
+	if (ret != 0) {		/* Will only be -ENODEV */
+		dprintk("Couldn't read from EEPROM: not there?\n");
+		memset(i2c->adapter->proposed_mac, 0, 6);
+		return ret;
+	}
+
+	decodeMAC(decodedMAC, encodedMAC);
+	memcpy(i2c->adapter->proposed_mac, decodedMAC, 6);
+
+	dprintk("%s adapter %i has MAC addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
+		i2c->adapter->name, i2c->adapter->num,
+		decodedMAC[0], decodedMAC[1], decodedMAC[2],
+		decodedMAC[3], decodedMAC[4], decodedMAC[5]);
+	dprintk("encoded MAC was %02x:%02x:%02x:%02x:%02x:%02x\n",
+		encodedMAC[0], encodedMAC[1], encodedMAC[2],
+		encodedMAC[3], encodedMAC[4], encodedMAC[5]);
+	return 0;
+}
+
+EXPORT_SYMBOL(ttpci_eeprom_parse_mac);
diff -Nru a/drivers/media/dvb/ttpci/ttpci-eeprom.h b/drivers/media/dvb/ttpci/ttpci-eeprom.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/ttpci/ttpci-eeprom.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,32 @@
+/*
+    Retrieve encoded MAC address from ATMEL ttpci_eeprom serial 2-wire EEPROM,
+    decode it and store it in associated adapter net device
+
+    Robert Schlabbach	GMX
+    Michael Glaum	KVH Industries
+    Holger Waechtler	Convergence
+
+    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 __TTPCI_EEPROM_H__
+#define __TTPCI_EEPROM_H__
+
+#include "dvb_i2c.h"
+
+extern int ttpci_eeprom_parse_mac(struct dvb_i2c_bus *i2c);
+
+#endif
diff -Nru a/drivers/media/dvb/ttusb-budget/Kconfig b/drivers/media/dvb/ttusb-budget/Kconfig
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/ttusb-budget/Kconfig	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,11 @@
+config DVB_TTUSB_BUDGET
+	tristate "Technotrend/Hauppauge Nova-USB devices"
+	depends on DVB_CORE && USB
+	help
+	  Support for external USB adapters designed by Technotrend and
+	  produced by Hauppauge, shipped under the brand name 'Nova-USB'.
+
+          These devices don't have a MPEG decoder built in, so you need
+	  an external software decoder to watch TV.	  
+
+	  Say Y if you own such a device and want to use it.
diff -Nru a/drivers/media/dvb/ttusb-budget/Makefile b/drivers/media/dvb/ttusb-budget/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/ttusb-budget/Makefile	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,3 @@
+obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o
+
+EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
diff -Nru a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,1271 @@
+/*
+ * TTUSB DVB driver
+ *
+ * Copyright (c) 2002 Holger Waechtler <holger@convergence.de>
+ * Copyright (c) 2003 Felix Domke <tmbinc@gmx.net>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License as
+ *	published by the Free Software Foundation; either version 2 of
+ *	the License, or (at your option) any later version.
+ */
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <linux/errno.h>
+#include <asm/semaphore.h>
+
+#include "dvb_frontend.h"
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_net.h"
+
+#include <linux/dvb/frontend.h>
+#include <linux/dvb/dmx.h>
+#include <linux/pci.h>
+#include <linux/usb.h>
+
+#include "dvb_functions.h"
+
+/*
+  TTUSB_HWSECTIONS:
+    the DSP supports filtering in hardware, however, since the "muxstream"
+    is a bit braindead (no matching channel masks or no matching filter mask),
+    we won't support this - yet. it doesn't event support negative filters,
+    so the best way is maybe to keep TTUSB_HWSECTIONS undef'd and just
+    parse TS data. USB bandwith will be a problem when having large
+    datastreams, especially for dvb-net, but hey, that's not my problem.
+	
+  TTUSB_DISEQC, TTUSB_TONE:
+    let the STC do the diseqc/tone stuff. this isn't supported at least with
+    my TTUSB, so let it undef'd unless you want to implement another
+    frontend. never tested.
+		
+  DEBUG:
+    define it to > 3 for really hardcore debugging. you probably don't want
+    this unless the device doesn't load at all. > 2 for bandwidth statistics.
+*/
+
+static int debug = 0;
+
+#define dprintk(x...) do { if (debug) printk(KERN_DEBUG x); } while (0)
+
+#define ISO_BUF_COUNT      4
+#define FRAMES_PER_ISO_BUF 4
+#define ISO_FRAME_SIZE     912
+#define TTUSB_MAXCHANNEL   32
+#ifdef TTUSB_HWSECTIONS
+#define TTUSB_MAXFILTER    16	/* ??? */
+#endif
+
+#define TTUSB_BUDGET_NAME "ttusb_stc_fw"
+
+/**
+ *  since we're casting (struct ttusb*) <-> (struct dvb_demux*) around
+ *  the dvb_demux field must be the first in struct!!
+ */
+struct ttusb {
+	struct dvb_demux dvb_demux;
+	struct dmxdev dmxdev;
+	struct dvb_net dvbnet;
+
+	/* our semaphore, for channel allocation/deallocation */
+	struct semaphore sem;
+	/* and one for USB access. */
+	struct semaphore semusb;
+
+	struct dvb_adapter *adapter;
+	struct usb_device *dev;
+
+	int disconnecting;
+	int iso_streaming;
+
+	unsigned int bulk_out_pipe;
+	unsigned int bulk_in_pipe;
+	unsigned int isoc_in_pipe;
+
+	void *iso_buffer;
+	dma_addr_t iso_dma_handle;
+
+	struct urb *iso_urb[ISO_BUF_COUNT];
+
+	int running_feed_count;
+	int last_channel;
+	int last_filter;
+
+	u8 c;			/* transaction counter, wraps around...  */
+	fe_sec_tone_mode_t tone;
+	fe_sec_voltage_t voltage;
+
+	int mux_state;		// 0..2 - MuxSyncWord, 3 - nMuxPacks,    4 - muxpack
+	u8 mux_npacks;
+	u8 muxpack[256 + 8];
+	int muxpack_ptr, muxpack_len;
+
+	int insync;
+
+	u16 cc;			/* MuxCounter - will increment on EVERY MUX PACKET */
+	/* (including stuffing. yes. really.) */
+
+	u8 last_result[32];
+
+	struct ttusb_channel {
+		struct ttusb *ttusb;
+		struct dvb_demux_feed *dvbdmxfeed;
+
+		int active;
+		int id;
+		int pid;
+		int type;	/* 1 - TS, 2 - Filter */
+#ifdef TTUSB_HWSECTIONS
+		int filterstate[TTUSB_MAXFILTER];	/* 0: not busy, 1: busy */
+#endif
+	} channel[TTUSB_MAXCHANNEL];
+#if 0
+	devfs_handle_t stc_devfs_handle;
+#endif
+};
+
+/* ugly workaround ... don't know why it's neccessary to read */
+/* all result codes. */
+
+#define DEBUG 0
+static int ttusb_cmd(struct ttusb *ttusb,
+	      const u8 * data, int len, int needresult)
+{
+	int actual_len;
+	int err;
+#if DEBUG >= 3
+	int i;
+
+	printk(">");
+	for (i = 0; i < len; ++i)
+		printk(" %02x", data[i]);
+	printk("\n");
+#endif
+
+	if (down_interruptible(&ttusb->semusb) < 0)
+		return -EAGAIN;
+
+	err = usb_bulk_msg(ttusb->dev, ttusb->bulk_out_pipe,
+			   (u8 *) data, len, &actual_len, HZ);
+	if (err != 0) {
+		dprintk("%s: usb_bulk_msg(send) failed, err == %i!\n",
+			__FUNCTION__, err);
+		up(&ttusb->semusb);
+		return err;
+	}
+	if (actual_len != len) {
+		dprintk("%s: only wrote %d of %d bytes\n", __FUNCTION__,
+			actual_len, len);
+		up(&ttusb->semusb);
+		return -1;
+	}
+
+	err = usb_bulk_msg(ttusb->dev, ttusb->bulk_in_pipe,
+			   ttusb->last_result, 32, &actual_len, HZ);
+
+	if (err != 0) {
+		printk("%s: failed, receive error %d\n", __FUNCTION__,
+		       err);
+		up(&ttusb->semusb);
+		return err;
+	}
+#if DEBUG >= 3
+	actual_len = ttusb->last_result[3] + 4;
+	printk("<");
+	for (i = 0; i < actual_len; ++i)
+		printk(" %02x", ttusb->last_result[i]);
+	printk("\n");
+#endif
+	if (!needresult)
+		up(&ttusb->semusb);
+	return 0;
+}
+
+static int ttusb_result(struct ttusb *ttusb, u8 * data, int len)
+{
+	memcpy(data, ttusb->last_result, len);
+	up(&ttusb->semusb);
+	return 0;
+}
+
+static int ttusb_i2c_msg(struct ttusb *ttusb,
+		  u8 addr, u8 * snd_buf, u8 snd_len, u8 * rcv_buf,
+		  u8 rcv_len)
+{
+	u8 b[0x28];
+	u8 id = ++ttusb->c;
+	int i, err;
+
+	if (snd_len > 0x28 - 7 || rcv_len > 0x20 - 7)
+		return -EINVAL;
+
+	b[0] = 0xaa;
+	b[1] = id;
+	b[2] = 0x31;
+	b[3] = snd_len + 3;
+	b[4] = addr << 1;
+	b[5] = snd_len;
+	b[6] = rcv_len;
+
+	for (i = 0; i < snd_len; i++)
+		b[7 + i] = snd_buf[i];
+
+	err = ttusb_cmd(ttusb, b, snd_len + 7, 1);
+
+	if (err)
+		return -EREMOTEIO;
+
+	err = ttusb_result(ttusb, b, 0x20);
+
+	if (rcv_len > 0) {
+
+		if (err || b[0] != 0x55 || b[1] != id) {
+			dprintk
+			    ("%s: usb_bulk_msg(recv) failed, err == %i, id == %02x, b == ",
+			     __FUNCTION__, err, id);
+			return -EREMOTEIO;
+		}
+
+		for (i = 0; i < rcv_len; i++)
+			rcv_buf[i] = b[7 + i];
+	}
+
+	return rcv_len;
+}
+
+static int ttusb_i2c_xfer(struct dvb_i2c_bus *i2c, const struct i2c_msg msg[],
+		   int num)
+{
+	struct ttusb *ttusb = i2c->data;
+	int i = 0;
+	int inc;
+
+	if (down_interruptible(&ttusb->sem) < 0)
+		return -EAGAIN;
+
+	while (i < num) {
+		u8 addr, snd_len, rcv_len, *snd_buf, *rcv_buf;
+		int err;
+
+		if (num > i + 1 && (msg[i + 1].flags & I2C_M_RD)) {
+			addr = msg[i].addr;
+			snd_buf = msg[i].buf;
+			snd_len = msg[i].len;
+			rcv_buf = msg[i + 1].buf;
+			rcv_len = msg[i + 1].len;
+			inc = 2;
+		} else {
+			addr = msg[i].addr;
+			snd_buf = msg[i].buf;
+			snd_len = msg[i].len;
+			rcv_buf = NULL;
+			rcv_len = 0;
+			inc = 1;
+		}
+
+		err = ttusb_i2c_msg(ttusb, addr,
+				    snd_buf, snd_len, rcv_buf, rcv_len);
+
+		if (err < rcv_len) {
+			printk("%s: i == %i\n", __FUNCTION__, i);
+			break;
+		}
+
+		i += inc;
+	}
+
+	up(&ttusb->sem);
+	return i;
+}
+
+#include "dvb-ttusb-dspbootcode.h"
+
+static int ttusb_boot_dsp(struct ttusb *ttusb)
+{
+	int i, err;
+	u8 b[40];
+
+	/* BootBlock */
+	b[0] = 0xaa;
+	b[2] = 0x13;
+	b[3] = 28;
+
+	/* upload dsp code in 32 byte steps (36 didn't work for me ...) */
+	/* 32 is max packet size, no messages should be splitted. */
+	for (i = 0; i < sizeof(dsp_bootcode); i += 28) {
+		memcpy(&b[4], &dsp_bootcode[i], 28);
+
+		b[1] = ++ttusb->c;
+
+		err = ttusb_cmd(ttusb, b, 32, 0);
+		if (err)
+			goto done;
+	}
+
+	/* last block ... */
+	b[1] = ++ttusb->c;
+	b[2] = 0x13;
+	b[3] = 0;
+
+	err = ttusb_cmd(ttusb, b, 4, 0);
+	if (err)
+		goto done;
+
+	/* BootEnd */
+	b[1] = ++ttusb->c;
+	b[2] = 0x14;
+	b[3] = 0;
+
+	err = ttusb_cmd(ttusb, b, 4, 0);
+
+      done:
+	if (err) {
+		dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
+			__FUNCTION__, err);
+	}
+
+	return err;
+}
+
+static int ttusb_set_channel(struct ttusb *ttusb, int chan_id, int filter_type,
+		      int pid)
+{
+	int err;
+	/* SetChannel */
+	u8 b[] = { 0xaa, ++ttusb->c, 0x22, 4, chan_id, filter_type,
+		(pid >> 8) & 0xff, pid & 0xff
+	};
+
+	err = ttusb_cmd(ttusb, b, sizeof(b), 0);
+	return err;
+}
+
+static int ttusb_del_channel(struct ttusb *ttusb, int channel_id)
+{
+	int err;
+	/* DelChannel */
+	u8 b[] = { 0xaa, ++ttusb->c, 0x23, 1, channel_id };
+
+	err = ttusb_cmd(ttusb, b, sizeof(b), 0);
+	return err;
+}
+
+#ifdef TTUSB_HWSECTIONS
+static int ttusb_set_filter(struct ttusb *ttusb, int filter_id,
+		     int associated_chan, u8 filter[8], u8 mask[8])
+{
+	int err;
+	/* SetFilter */
+	u8 b[] = { 0xaa, 0, 0x24, 0x1a, filter_id, associated_chan,
+		filter[0], filter[1], filter[2], filter[3],
+		filter[4], filter[5], filter[6], filter[7],
+		filter[8], filter[9], filter[10], filter[11],
+		mask[0], mask[1], mask[2], mask[3],
+		mask[4], mask[5], mask[6], mask[7],
+		mask[8], mask[9], mask[10], mask[11]
+	};
+
+	err = ttusb_cmd(ttusb, b, sizeof(b), 0);
+	return err;
+}
+
+static int ttusb_del_filter(struct ttusb *ttusb, int filter_id)
+{
+	int err;
+	/* DelFilter */
+	u8 b[] = { 0xaa, ++ttusb->c, 0x25, 1, filter_id };
+
+	err = ttusb_cmd(ttusb, b, sizeof(b), 0);
+	return err;
+}
+#endif
+
+static int ttusb_init_controller(struct ttusb *ttusb)
+{
+	u8 b0[] = { 0xaa, ++ttusb->c, 0x15, 1, 0 };
+	u8 b1[] = { 0xaa, ++ttusb->c, 0x15, 1, 1 };
+	u8 b2[] = { 0xaa, ++ttusb->c, 0x32, 1, 0 };
+	/* i2c write read: 5 bytes, addr 0x10, 0x02 bytes write, 1 bytes read. */
+	u8 b3[] =
+	    { 0xaa, ++ttusb->c, 0x31, 5, 0x10, 0x02, 0x01, 0x00, 0x1e };
+	u8 b4[] =
+	    { 0x55, ttusb->c, 0x31, 4, 0x10, 0x02, 0x01, 0x00, 0x1e };
+
+	u8 get_version[] = { 0xaa, ++ttusb->c, 0x17, 5, 0, 0, 0, 0, 0 };
+	u8 get_dsp_version[0x20] =
+	    { 0xaa, ++ttusb->c, 0x26, 28, 0, 0, 0, 0, 0 };
+	int err;
+
+	/* reset board */
+	if ((err = ttusb_cmd(ttusb, b0, sizeof(b0), 0)))
+		return err;
+
+	/* reset board (again?) */
+	if ((err = ttusb_cmd(ttusb, b1, sizeof(b1), 0)))
+		return err;
+
+	ttusb_boot_dsp(ttusb);
+
+	/* set i2c bit rate */
+	if ((err = ttusb_cmd(ttusb, b2, sizeof(b2), 0)))
+		return err;
+
+	if ((err = ttusb_cmd(ttusb, b3, sizeof(b3), 1)))
+		return err;
+
+	err = ttusb_result(ttusb, b4, sizeof(b4));
+
+	if ((err = ttusb_cmd(ttusb, get_version, sizeof(get_version), 1)))
+		return err;
+
+	if ((err = ttusb_result(ttusb, get_version, sizeof(get_version))))
+		return err;
+
+	dprintk("%s: stc-version: %c%c%c%c%c\n", __FUNCTION__,
+		get_version[4], get_version[5], get_version[6],
+		get_version[7], get_version[8]);
+
+	if (memcmp(get_version + 4, "V 0.0", 5) &&
+	    memcmp(get_version + 4, "V 1.1", 5)) {
+		printk
+		    ("%s: unknown STC version %c%c%c%c%c, please report!\n",
+		     __FUNCTION__, get_version[4], get_version[5],
+		     get_version[6], get_version[7], get_version[8]);
+	}
+
+	err =
+	    ttusb_cmd(ttusb, get_dsp_version, sizeof(get_dsp_version), 1);
+	if (err)
+		return err;
+
+	err =
+	    ttusb_result(ttusb, get_dsp_version, sizeof(get_dsp_version));
+	if (err)
+		return err;
+	printk("%s: dsp-version: %c%c%c\n", __FUNCTION__,
+	       get_dsp_version[4], get_dsp_version[5], get_dsp_version[6]);
+	return 0;
+}
+
+#ifdef TTUSB_DISEQC
+static int ttusb_send_diseqc(struct ttusb *ttusb,
+		      const struct dvb_diseqc_master_cmd *cmd)
+{
+	u8 b[12] = { 0xaa, ++ttusb->c, 0x18 };
+
+	int err;
+
+	b[3] = 4 + 2 + cmd->msg_len;
+	b[4] = 0xFF;		/* send diseqc master, not burst */
+	b[5] = cmd->msg_len;
+
+	memcpy(b + 5, cmd->msg, cmd->msg_len);
+
+	/* Diseqc */
+	if ((err = ttusb_cmd(ttusb, b, 4 + b[3], 0))) {
+		dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
+			__FUNCTION__, err);
+	}
+
+	return err;
+}
+#endif
+
+static int ttusb_update_lnb(struct ttusb *ttusb)
+{
+	u8 b[] = { 0xaa, ++ttusb->c, 0x16, 5, /*power: */ 1,
+		ttusb->voltage == SEC_VOLTAGE_18 ? 0 : 1,
+		ttusb->tone == SEC_TONE_ON ? 1 : 0, 1, 1
+	};
+	int err;
+
+	/* SetLNB */
+	if ((err = ttusb_cmd(ttusb, b, sizeof(b), 0))) {
+		dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
+			__FUNCTION__, err);
+	}
+
+	return err;
+}
+
+static int ttusb_set_voltage(struct ttusb *ttusb, fe_sec_voltage_t voltage)
+{
+	ttusb->voltage = voltage;
+	return ttusb_update_lnb(ttusb);
+}
+
+#ifdef TTUSB_TONE
+static int ttusb_set_tone(struct ttusb *ttusb, fe_sec_tone_mode_t tone)
+{
+	ttusb->tone = tone;
+	return ttusb_update_lnb(ttusb);
+}
+#endif
+
+static int ttusb_lnb_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
+{
+	struct ttusb *ttusb = fe->i2c->data;
+
+	switch (cmd) {
+	case FE_SET_VOLTAGE:
+		return ttusb_set_voltage(ttusb, (fe_sec_voltage_t) arg);
+#ifdef TTUSB_TONE
+	case FE_SET_TONE:
+		return ttusb_set_tone(ttusb, (fe_sec_tone_mode_t) arg);
+#endif
+#ifdef TTUSB_DISEQC
+	case FE_DISEQC_SEND_MASTER_CMD:
+		return ttusb_send_diseqc(ttusb,
+					 (struct dvb_diseqc_master_cmd *)
+					 arg);
+#endif
+	default:
+		return -EOPNOTSUPP;
+	};
+}
+
+#if 0
+static void ttusb_set_led_freq(struct ttusb *ttusb, u8 freq)
+{
+	u8 b[] = { 0xaa, ++ttusb->c, 0x19, 1, freq };
+	int err, actual_len;
+
+	err = ttusb_cmd(ttusb, b, sizeof(b), 0);
+	if (err) {
+		dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
+			__FUNCTION__, err);
+	}
+}
+#endif
+
+/*****************************************************************************/
+
+#ifdef TTUSB_HWSECTIONS
+static void ttusb_handle_ts_data(struct ttusb_channel *channel,
+				 const u8 * data, int len);
+static void ttusb_handle_sec_data(struct ttusb_channel *channel,
+				  const u8 * data, int len);
+#endif
+
+int numpkt = 0, lastj, numts, numstuff, numsec, numinvalid;
+
+static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
+			   int len)
+{
+	u16 csum = 0, cc;
+	int i;
+	for (i = 0; i < len; i += 2)
+		csum ^= le16_to_cpup((u16 *) (muxpack + i));
+	if (csum) {
+		printk("%s: muxpack with incorrect checksum, ignoring\n",
+		       __FUNCTION__);
+		numinvalid++;
+		return;
+	}
+
+	cc = (muxpack[len - 4] << 8) | muxpack[len - 3];
+	cc &= 0x7FFF;
+	if (cc != ttusb->cc)
+		printk("%s: cc discontinuity (%d frames missing)\n",
+		       __FUNCTION__, (cc - ttusb->cc) & 0x7FFF);
+	ttusb->cc = (cc + 1) & 0x7FFF;
+	if (muxpack[0] & 0x80) {
+#ifdef TTUSB_HWSECTIONS
+		/* section data */
+		int pusi = muxpack[0] & 0x40;
+		int channel = muxpack[0] & 0x1F;
+		int payload = muxpack[1];
+		const u8 *data = muxpack + 2;
+		/* check offset flag */
+		if (muxpack[0] & 0x20)
+			data++;
+
+		ttusb_handle_sec_data(ttusb->channel + channel, data,
+				      payload);
+		data += payload;
+
+		if ((!!(ttusb->muxpack[0] & 0x20)) ^
+		    !!(ttusb->muxpack[1] & 1))
+			data++;
+#warning TODO: pusi
+		printk("cc: %04x\n", (data[0] << 8) | data[1]);
+#endif
+		numsec++;
+	} else if (muxpack[0] == 0x47) {
+#ifdef TTUSB_HWSECTIONS
+		/* we have TS data here! */
+		int pid = ((muxpack[1] & 0x0F) << 8) | muxpack[2];
+		int channel;
+		for (channel = 0; channel < TTUSB_MAXCHANNEL; ++channel)
+			if (ttusb->channel[channel].active
+			    && (pid == ttusb->channel[channel].pid))
+				ttusb_handle_ts_data(ttusb->channel +
+						     channel, muxpack,
+						     188);
+#endif
+		numts++;
+		dvb_dmx_swfilter_packets(&ttusb->dvb_demux, muxpack, 1);
+	} else if (muxpack[0] != 0) {
+		numinvalid++;
+		printk("illegal muxpack type %02x\n", muxpack[0]);
+	} else
+		numstuff++;
+}
+
+static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
+{
+	int maxwork = 1024;
+	while (len) {
+		if (!(maxwork--)) {
+			printk("%s: too much work\n", __FUNCTION__);
+			break;
+		}
+
+		switch (ttusb->mux_state) {
+		case 0:
+		case 1:
+		case 2:
+			len--;
+			if (*data++ == 0xAA)
+				++ttusb->mux_state;
+			else {
+				ttusb->mux_state = 0;
+#if DEBUG > 3
+				if (ttusb->insync)
+					printk("%02x ", data[-1]);
+#else
+				if (ttusb->insync) {
+					printk("%s: lost sync.\n",
+					       __FUNCTION__);
+					ttusb->insync = 0;
+				}
+#endif
+			}
+			break;
+		case 3:
+			ttusb->insync = 1;
+			len--;
+			ttusb->mux_npacks = *data++;
+			++ttusb->mux_state;
+			ttusb->muxpack_ptr = 0;
+			/* maximum bytes, until we know the length */
+			ttusb->muxpack_len = 2;
+			break;
+		case 4:
+			{
+				int avail;
+				avail = len;
+				if (avail >
+				    (ttusb->muxpack_len -
+				     ttusb->muxpack_ptr))
+					avail =
+					    ttusb->muxpack_len -
+					    ttusb->muxpack_ptr;
+				memcpy(ttusb->muxpack + ttusb->muxpack_ptr,
+				       data, avail);
+				ttusb->muxpack_ptr += avail;
+				if (ttusb->muxpack_ptr > 264)
+					BUG();
+				data += avail;
+				len -= avail;
+				/* determine length */
+				if (ttusb->muxpack_ptr == 2) {
+					if (ttusb->muxpack[0] & 0x80) {
+						ttusb->muxpack_len =
+						    ttusb->muxpack[1] + 2;
+						if (ttusb->
+						    muxpack[0] & 0x20)
+							ttusb->
+							    muxpack_len++;
+						if ((!!
+						     (ttusb->
+						      muxpack[0] & 0x20)) ^
+						    !!(ttusb->
+						       muxpack[1] & 1))
+							ttusb->
+							    muxpack_len++;
+						ttusb->muxpack_len += 4;
+					} else if (ttusb->muxpack[0] ==
+						   0x47)
+						ttusb->muxpack_len =
+						    188 + 4;
+					else if (ttusb->muxpack[0] == 0x00)
+						ttusb->muxpack_len =
+						    ttusb->muxpack[1] + 2 +
+						    4;
+					else {
+						dprintk
+						    ("%s: invalid state: first byte is %x\n",
+						     __FUNCTION__,
+						     ttusb->muxpack[0]);
+						ttusb->mux_state = 0;
+					}
+				}
+
+			/**
+			 * if length is valid and we reached the end:
+			 * goto next muxpack
+			 */
+				if ((ttusb->muxpack_ptr >= 2) &&
+				    (ttusb->muxpack_ptr ==
+				     ttusb->muxpack_len)) {
+					ttusb_process_muxpack(ttusb,
+							      ttusb->
+							      muxpack,
+							      ttusb->
+							      muxpack_ptr);
+					ttusb->muxpack_ptr = 0;
+					/* maximum bytes, until we know the length */
+					ttusb->muxpack_len = 2;
+
+				/**
+				 * no muxpacks left?
+				 * return to search-sync state
+				 */
+					if (!ttusb->mux_npacks--) {
+						ttusb->mux_state = 0;
+						break;
+					}
+				}
+				break;
+			}
+		default:
+			BUG();
+			break;
+		}
+	}
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+static void ttusb_iso_irq(struct urb *urb)
+#else
+static void ttusb_iso_irq(struct urb *urb, struct pt_regs *ptregs)
+#endif
+{
+	struct ttusb *ttusb = urb->context;
+
+	if (!ttusb->iso_streaming)
+		return;
+
+#if 0
+	printk("%s: status %d, errcount == %d, length == %i\n",
+	       __FUNCTION__,
+	       urb->status, urb->error_count, urb->actual_length);
+#endif
+
+	if (!urb->status) {
+		int i;
+		for (i = 0; i < urb->number_of_packets; ++i) {
+			struct usb_iso_packet_descriptor *d;
+			u8 *data;
+			int len;
+			numpkt++;
+			if ((jiffies - lastj) >= HZ) {
+#if DEBUG > 2
+				printk
+				    ("frames/s: %d (ts: %d, stuff %d, sec: %d, invalid: %d, all: %d)\n",
+				     numpkt * HZ / (jiffies - lastj),
+				     numts, numstuff, numsec, numinvalid,
+				     numts + numstuff + numsec +
+				     numinvalid);
+#endif
+				numts = numstuff = numsec = numinvalid = 0;
+				lastj = jiffies;
+				numpkt = 0;
+			}
+			d = &urb->iso_frame_desc[i];
+			data = urb->transfer_buffer + d->offset;
+			len = d->actual_length;
+			d->actual_length = 0;
+			d->status = 0;
+			ttusb_process_frame(ttusb, data, len);
+		}
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	usb_submit_urb(urb, GFP_KERNEL);
+#endif
+}
+
+static void ttusb_free_iso_urbs(struct ttusb *ttusb)
+{
+	int i;
+
+	for (i = 0; i < ISO_BUF_COUNT; i++)
+		if (ttusb->iso_urb[i])
+			usb_free_urb(ttusb->iso_urb[i]);
+
+	pci_free_consistent(NULL,
+			    ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF *
+			    ISO_BUF_COUNT, ttusb->iso_buffer,
+			    ttusb->iso_dma_handle);
+}
+
+static int ttusb_alloc_iso_urbs(struct ttusb *ttusb)
+{
+	int i;
+
+	ttusb->iso_buffer = pci_alloc_consistent(NULL,
+						 ISO_FRAME_SIZE *
+						 FRAMES_PER_ISO_BUF *
+						 ISO_BUF_COUNT,
+						 &ttusb->iso_dma_handle);
+
+	memset(ttusb->iso_buffer, 0,
+	       ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT);
+
+	for (i = 0; i < ISO_BUF_COUNT; i++) {
+		struct urb *urb;
+
+		if (!
+		    (urb =
+		     usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_KERNEL))) {
+			ttusb_free_iso_urbs(ttusb);
+			return -ENOMEM;
+		}
+
+		ttusb->iso_urb[i] = urb;
+	}
+
+	return 0;
+}
+
+static void ttusb_stop_iso_xfer(struct ttusb *ttusb)
+{
+	int i;
+
+	for (i = 0; i < ISO_BUF_COUNT; i++)
+		usb_unlink_urb(ttusb->iso_urb[i]);
+
+	ttusb->iso_streaming = 0;
+}
+
+static int ttusb_start_iso_xfer(struct ttusb *ttusb)
+{
+	int i, j, err, buffer_offset = 0;
+
+	if (ttusb->iso_streaming) {
+		printk("%s: iso xfer already running!\n", __FUNCTION__);
+		return 0;
+	}
+
+	ttusb->insync = 0;
+	ttusb->mux_state = 0;
+
+	for (i = 0; i < ISO_BUF_COUNT; i++) {
+		int frame_offset = 0;
+		struct urb *urb = ttusb->iso_urb[i];
+
+		urb->dev = ttusb->dev;
+		urb->context = ttusb;
+		urb->complete = ttusb_iso_irq;
+		urb->pipe = ttusb->isoc_in_pipe;
+		urb->transfer_flags = URB_ISO_ASAP;
+		urb->number_of_packets = FRAMES_PER_ISO_BUF;
+		urb->transfer_buffer_length =
+		    ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF;
+		urb->transfer_buffer = ttusb->iso_buffer + buffer_offset;
+		buffer_offset += ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF;
+
+		for (j = 0; j < FRAMES_PER_ISO_BUF; j++) {
+			urb->iso_frame_desc[j].offset = frame_offset;
+			urb->iso_frame_desc[j].length = ISO_FRAME_SIZE;
+			frame_offset += ISO_FRAME_SIZE;
+		}
+	}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	for (i = 0; i < ISO_BUF_COUNT; i++) {
+		int next = (i + 1) % ISO_BUF_COUNT;
+		ttusb->iso_urb[i]->next = ttusb->iso_urb[next];
+	}
+#endif
+
+	for (i = 0; i < ISO_BUF_COUNT; i++) {
+		if ((err = usb_submit_urb(ttusb->iso_urb[i], GFP_KERNEL))) {
+			ttusb_stop_iso_xfer(ttusb);
+			printk
+			    ("%s: failed urb submission (%i: err = %i)!\n",
+			     __FUNCTION__, i, err);
+			return err;
+		}
+	}
+
+	ttusb->iso_streaming = 1;
+
+	return 0;
+}
+
+#ifdef TTUSB_HWSECTIONS
+static void ttusb_handle_ts_data(struct ttusb_channel *channel, const u8 * data,
+			  int len)
+{
+	struct dvb_demux_feed *dvbdmxfeed = channel->dvbdmxfeed;
+
+	dvbdmxfeed->cb.ts(data, len, 0, 0, &dvbdmxfeed->feed.ts, 0);
+}
+
+static void ttusb_handle_sec_data(struct ttusb_channel *channel, const u8 * data,
+			   int len)
+{
+//      struct dvb_demux_feed *dvbdmxfeed = channel->dvbdmxfeed;
+#error TODO: handle ugly stuff
+//      dvbdmxfeed->cb.sec(data, len, 0, 0, &dvbdmxfeed->feed.sec, 0);
+}
+#endif
+
+static struct ttusb_channel *ttusb_channel_allocate(struct ttusb *ttusb)
+{
+	int i;
+
+	if (down_interruptible(&ttusb->sem))
+		return NULL;
+
+	/* lock! */
+	for (i = 0; i < TTUSB_MAXCHANNEL; ++i) {
+		if (!ttusb->channel[i].active) {
+			ttusb->channel[i].active = 1;
+			up(&ttusb->sem);
+			return ttusb->channel + i;
+		}
+	}
+
+	up(&ttusb->sem);
+
+	return NULL;
+}
+
+static int ttusb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct ttusb *ttusb = (struct ttusb *) dvbdmxfeed->demux;
+	struct ttusb_channel *channel;
+
+	printk("ttusb_start_feed\n");
+
+	switch (dvbdmxfeed->type) {
+	case DMX_TYPE_TS:
+		break;
+	case DMX_TYPE_SEC:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (dvbdmxfeed->type == DMX_TYPE_TS) {
+		switch (dvbdmxfeed->pes_type) {
+		case DMX_TS_PES_VIDEO:
+		case DMX_TS_PES_AUDIO:
+		case DMX_TS_PES_TELETEXT:
+		case DMX_TS_PES_PCR:
+		case DMX_TS_PES_OTHER:
+			channel = ttusb_channel_allocate(ttusb);
+			break;
+		default:
+			return -EINVAL;
+		}
+	} else {
+		channel = ttusb_channel_allocate(ttusb);
+	}
+
+	if (!channel)
+		return -EBUSY;
+
+	dvbdmxfeed->priv = channel;
+	channel->dvbdmxfeed = dvbdmxfeed;
+
+	channel->pid = dvbdmxfeed->pid;
+
+#ifdef TTUSB_HWSECTIONS
+	if (dvbdmxfeed->type == DMX_TYPE_TS) {
+		channel->type = 1;
+	} else if (dvbdmxfeed->type == DMX_TYPE_SEC) {
+		channel->type = 2;
+#error TODO: allocate filters
+	}
+#else
+	channel->type = 1;
+#endif
+
+	ttusb_set_channel(ttusb, channel->id, channel->type, channel->pid);
+
+	if (0 == ttusb->running_feed_count++)
+		ttusb_start_iso_xfer(ttusb);
+
+	return 0;
+}
+
+static int ttusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct ttusb_channel *channel =
+	    (struct ttusb_channel *) dvbdmxfeed->priv;
+	struct ttusb *ttusb = (struct ttusb *) dvbdmxfeed->demux;
+
+	ttusb_del_channel(channel->ttusb, channel->id);
+
+	if (--ttusb->running_feed_count == 0)
+		ttusb_stop_iso_xfer(ttusb);
+
+	channel->active = 0;
+
+	return 0;
+}
+
+static int ttusb_setup_interfaces(struct ttusb *ttusb)
+{
+	usb_set_configuration(ttusb->dev, 1);
+	usb_set_interface(ttusb->dev, 1, 1);
+
+	ttusb->bulk_out_pipe = usb_sndbulkpipe(ttusb->dev, 1);
+	ttusb->bulk_in_pipe = usb_rcvbulkpipe(ttusb->dev, 1);
+	ttusb->isoc_in_pipe = usb_rcvisocpipe(ttusb->dev, 2);
+
+	return 0;
+}
+
+#if 0
+static u8 stc_firmware[8192];
+
+static int stc_open(struct inode *inode, struct file *file)
+{
+	struct ttusb *ttusb = file->private_data;
+	int addr;
+
+	for (addr = 0; addr < 8192; addr += 16) {
+		u8 snd_buf[2] = { addr >> 8, addr & 0xFF };
+		ttusb_i2c_msg(ttusb, 0x50, snd_buf, 2, stc_firmware + addr,
+			      16);
+	}
+
+	return 0;
+}
+
+static ssize_t stc_read(struct file *file, char *buf, size_t count,
+		 loff_t * offset)
+{
+	int tc = count;
+
+	if ((tc + *offset) > 8192)
+		tc = 8192 - *offset;
+
+	if (tc < 0)
+		return 0;
+
+	copy_to_user(buf, stc_firmware + *offset, tc);
+
+	*offset += tc;
+
+	return tc;
+}
+
+static int stc_release(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static struct file_operations stc_fops = {
+	.owner = THIS_MODULE,
+	.read = stc_read,
+	.open = stc_open,
+	.release = stc_release,
+};
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+static void *ttusb_probe(struct usb_device *udev, unsigned int ifnum,
+		  const struct usb_device_id *id)
+{
+	struct ttusb *ttusb;
+	int result, channel;
+
+	if (ifnum != 0)
+		return NULL;
+
+	dprintk("%s: TTUSB DVB connected\n", __FUNCTION__);
+
+	if (!(ttusb = kmalloc(sizeof(struct ttusb), GFP_KERNEL)))
+		return NULL;
+
+#else
+static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	struct usb_device *udev;
+	struct ttusb *ttusb;
+	int result, channel;
+
+	dprintk("%s: TTUSB DVB connected\n", __FUNCTION__);
+
+	udev = interface_to_usbdev(intf);
+
+	if (!(ttusb = kmalloc(sizeof(struct ttusb), GFP_KERNEL)))
+		return -ENOMEM;
+
+#endif
+
+	memset(ttusb, 0, sizeof(struct ttusb));
+
+	for (channel = 0; channel < TTUSB_MAXCHANNEL; ++channel) {
+		ttusb->channel[channel].id = channel;
+		ttusb->channel[channel].ttusb = ttusb;
+	}
+
+	ttusb->dev = udev;
+	ttusb->c = 0;
+	ttusb->mux_state = 0;
+	sema_init(&ttusb->sem, 0);
+	sema_init(&ttusb->semusb, 1);
+
+	ttusb_setup_interfaces(ttusb);
+
+	ttusb_alloc_iso_urbs(ttusb);
+	if (ttusb_init_controller(ttusb))
+		printk("ttusb_init_controller: error\n");
+
+	up(&ttusb->sem);
+
+	dvb_register_adapter(&ttusb->adapter,
+			     "Technotrend/Hauppauge Nova-USB");
+
+	dvb_register_i2c_bus(ttusb_i2c_xfer, ttusb, ttusb->adapter, 0);
+	dvb_add_frontend_ioctls(ttusb->adapter, ttusb_lnb_ioctl, NULL,
+				ttusb);
+
+	memset(&ttusb->dvb_demux, 0, sizeof(ttusb->dvb_demux));
+
+	ttusb->dvb_demux.dmx.capabilities =
+	    DMX_TS_FILTERING | DMX_SECTION_FILTERING;
+	ttusb->dvb_demux.priv = 0;
+#ifdef TTUSB_HWSECTIONS
+	ttusb->dvb_demux.filternum = TTUSB_MAXFILTER;
+#else
+	ttusb->dvb_demux.filternum = 32;
+#endif
+	ttusb->dvb_demux.feednum = TTUSB_MAXCHANNEL;
+	ttusb->dvb_demux.start_feed = ttusb_start_feed;
+	ttusb->dvb_demux.stop_feed = ttusb_stop_feed;
+	ttusb->dvb_demux.write_to_decoder = 0;
+
+	if ((result = dvb_dmx_init(&ttusb->dvb_demux)) < 0) {
+		printk("ttusb_dvb: dvb_dmx_init failed (errno = %d)\n",
+		       result);
+		goto err;
+	}
+//FIXME dmxdev (nur WAS?)
+	ttusb->dmxdev.filternum = ttusb->dvb_demux.filternum;
+	ttusb->dmxdev.demux = &ttusb->dvb_demux.dmx;
+	ttusb->dmxdev.capabilities = 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);
+		goto err;
+	}
+
+	if (dvb_net_init
+	    (ttusb->adapter, &ttusb->dvbnet, &ttusb->dvb_demux.dmx)) {
+		printk("ttusb_dvb: dvb_net_init failed!\n");
+	}
+
+      err:
+#if 0
+	ttusb->stc_devfs_handle =
+	    devfs_register(ttusb->adapter->devfs_handle, TTUSB_BUDGET_NAME,
+			   DEVFS_FL_DEFAULT, 0, 192,
+			   S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP
+			   | S_IROTH | S_IWOTH, &stc_fops, ttusb);
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	return (void *) ttusb;
+#else
+	usb_set_intfdata(intf, (void *) ttusb);
+
+	return 0;
+#endif
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+static void ttusb_disconnect(struct usb_device *udev, void *data)
+{
+	struct ttusb *ttusb = data;
+#else
+static void ttusb_disconnect(struct usb_interface *intf)
+{
+	struct ttusb *ttusb = usb_get_intfdata(intf);
+
+	usb_set_intfdata(intf, NULL);
+#endif
+
+	ttusb->disconnecting = 1;
+
+	ttusb_stop_iso_xfer(ttusb);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,69))
+#undef devfs_remove
+#define devfs_remove(x)	devfs_unregister(ttusb->stc_devfs_handle);
+#endif
+#if 0
+	devfs_remove(TTUSB_BUDGET_NAME);
+#endif
+	ttusb->dvb_demux.dmx.close(&ttusb->dvb_demux.dmx);
+	dvb_net_release(&ttusb->dvbnet);
+	dvb_dmxdev_release(&ttusb->dmxdev);
+	dvb_dmx_release(&ttusb->dvb_demux);
+
+	dvb_unregister_i2c_bus(ttusb_i2c_xfer, ttusb->adapter, 0);
+	dvb_unregister_adapter(ttusb->adapter);
+
+	ttusb_free_iso_urbs(ttusb);
+
+	kfree(ttusb);
+
+	dprintk("%s: TTUSB DVB disconnected\n", __FUNCTION__);
+}
+
+static struct usb_device_id ttusb_table[] = {
+	{USB_DEVICE(0xb48, 0x1003)},
+	{USB_DEVICE(0xb48, 0x1004)},	/* to be confirmed ????  */
+	{USB_DEVICE(0xb48, 0x1005)},	/* to be confirmed ????  */
+	{}
+};
+
+MODULE_DEVICE_TABLE(usb, ttusb_table);
+
+static struct usb_driver ttusb_driver = {
+      .name 		= "Technotrend/Hauppauge USB-Nova",
+      .probe 		= ttusb_probe,
+      .disconnect 	= ttusb_disconnect,
+      .id_table 	= ttusb_table,
+};
+
+static int __init ttusb_init(void)
+{
+	int err;
+
+	if ((err = usb_register(&ttusb_driver)) < 0) {
+		printk("%s: usb_register failed! Error number %d",
+		       __FILE__, err);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void __exit ttusb_exit(void)
+{
+	usb_deregister(&ttusb_driver);
+}
+
+module_init(ttusb_init);
+module_exit(ttusb_exit);
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug or not");
+
+MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>");
+MODULE_DESCRIPTION("TTUSB DVB Driver");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h b/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,1644 @@
+
+#include <asm/types.h>
+
+u8 dsp_bootcode [] __initdata = {
+	0x08, 0xaa, 0x00, 0x18, 0x00, 0x03, 0x08, 0x00, 
+	0x00, 0x10, 0x00, 0x00, 0x01, 0x80, 0x18, 0x5f, 
+	0x00, 0x00, 0x01, 0x80, 0x77, 0x18, 0x2a, 0xeb, 
+	0x6b, 0xf8, 0x00, 0x18, 0x03, 0xff, 0x68, 0xf8, 
+	0x00, 0x18, 0xff, 0xfe, 0xf7, 0xb8, 0xf7, 0xbe, 
+	0xf6, 0xb9, 0xf4, 0xa0, 0xf6, 0xb7, 0xf6, 0xb5, 
+	0xf6, 0xb6, 0xf0, 0x20, 0x19, 0xdf, 0xf1, 0x00, 
+	0x00, 0x01, 0xf8, 0x4d, 0x01, 0xab, 0xf6, 0xb8, 
+	0xf0, 0x20, 0x19, 0xdf, 0xf0, 0x73, 0x01, 0xa5, 
+	0x7e, 0xf8, 0x00, 0x12, 0xf0, 0x00, 0x00, 0x01, 
+	0x47, 0xf8, 0x00, 0x11, 0x7e, 0x92, 0x00, 0xf8, 
+	0x00, 0x11, 0xf0, 0x00, 0x00, 0x01, 0x7e, 0xf8, 
+	0x00, 0x11, 0xf0, 0x00, 0x00, 0x01, 0x6c, 0x89, 
+	0x01, 0x9a, 0xf7, 0xb8, 0xee, 0xfc, 0xf0, 0x20, 
+	0xff, 0xff, 0xf1, 0x00, 0x00, 0x01, 0xf8, 0x4d, 
+	0x01, 0xbf, 0xf2, 0x73, 0x01, 0xb9, 0x4e, 0x02, 
+	0xf4, 0x95, 0xf5, 0xe3, 0x56, 0x02, 0x7e, 0x00, 
+	0x11, 0x00, 0xfa, 0x4c, 0x01, 0xb7, 0x6b, 0x03, 
+	0x00, 0x01, 0xf6, 0xb8, 0xee, 0x04, 0xf0, 0x74, 
+	0x0d, 0xa7, 0xf0, 0x74, 0x01, 0xc5, 0x4a, 0x11, 
+	0x4a, 0x16, 0x72, 0x11, 0x2a, 0xe6, 0x10, 0xf8, 
+	0x00, 0x11, 0xfa, 0x45, 0x01, 0xdb, 0xf4, 0x95, 
+	0xee, 0xff, 0x48, 0x11, 0xf0, 0x00, 0x2a, 0xc6, 
+	0x88, 0x16, 0xf4, 0x95, 0xf4, 0x95, 0x10, 0xee, 
+	0xff, 0xff, 0xf4, 0xe3, 0x6c, 0xe9, 0xff, 0xff, 
+	0x01, 0xd5, 0x10, 0xf8, 0x2a, 0xe7, 0xf8, 0x45, 
+	0x01, 0xe2, 0x10, 0xf8, 0x2a, 0xe7, 0xf4, 0xe3, 
+	0xf0, 0x74, 0x01, 0xff, 0xee, 0x01, 0x8a, 0x16, 
+	0x8a, 0x11, 0xfc, 0x00, 0xf7, 0xb8, 0xe9, 0x20, 
+	0x4a, 0x11, 0x09, 0xf8, 0x2a, 0xe6, 0xf8, 0x4e, 
+	0x01, 0xf3, 0xf2, 0x73, 0x01, 0xfd, 0xf4, 0x95, 
+	0xe8, 0x01, 0x72, 0x11, 0x2a, 0xe6, 0x49, 0x11, 
+	0x80, 0xe1, 0x2a, 0xc6, 0xf3, 0x00, 0x00, 0x01, 
+	0xe8, 0x00, 0x81, 0xf8, 0x2a, 0xe6, 0x8a, 0x11, 
+	0xfc, 0x00, 0xf4, 0x95, 0xf0, 0x73, 0x02, 0x00, 
+	0x10, 0xf8, 0x2a, 0x0f, 0xfc, 0x00, 0x4a, 0x11, 
+	0xf0, 0x74, 0x02, 0x02, 0x80, 0xf8, 0x2a, 0x10, 
+	0x73, 0x08, 0x00, 0x09, 0x40, 0xf8, 0x2a, 0x15, 
+	0x82, 0xf8, 0x00, 0x11, 0xf4, 0x95, 0x77, 0x10, 
+	0x03, 0xe8, 0xf5, 0xa9, 0xf8, 0x30, 0x02, 0x21, 
+	0x71, 0xf8, 0x2a, 0x10, 0x2a, 0x15, 0x56, 0xf8, 
+	0x2a, 0x0c, 0xf0, 0xe3, 0x4e, 0xf8, 0x2a, 0x16, 
+	0xe8, 0x00, 0x4e, 0xf8, 0x2a, 0x0c, 0x8a, 0x11, 
+	0xfc, 0x00, 0x4a, 0x06, 0x4a, 0x07, 0x4a, 0x1d, 
+	0x68, 0xf8, 0x00, 0x07, 0x7d, 0x3f, 0x69, 0xf8, 
+	0x00, 0x07, 0x40, 0x00, 0x68, 0xf8, 0x00, 0x1d, 
+	0xff, 0xfc, 0x6b, 0xf8, 0x2a, 0x0f, 0x00, 0x01, 
+	0x8a, 0x1d, 0x8a, 0x07, 0x8a, 0x06, 0xf4, 0xeb, 
+	0xee, 0xfd, 0x76, 0xf8, 0x2a, 0x0f, 0x00, 0x00, 
+	0x76, 0x00, 0x00, 0x00, 0xfb, 0x80, 0x19, 0x4c, 
+	0xf4, 0x95, 0xe8, 0x00, 0x80, 0xf8, 0x2a, 0x11, 
+	0xf9, 0x80, 0x19, 0x07, 0x80, 0xf8, 0x2a, 0x0e, 
+	0xf9, 0x80, 0x16, 0x66, 0x76, 0x00, 0x2a, 0x12, 
+	0x10, 0xf8, 0x2a, 0x11, 0xf9, 0x80, 0x18, 0xe3, 
+	0x10, 0xf8, 0x2a, 0x0e, 0xf9, 0x80, 0x16, 0x66, 
+	0x10, 0xf8, 0x2a, 0x0e, 0xf9, 0x80, 0x16, 0x87, 
+	0xee, 0x03, 0xfc, 0x00, 0x4a, 0x11, 0xf6, 0xb8, 
+	0xf4, 0x95, 0xf0, 0x20, 0x80, 0x00, 0x11, 0xf8, 
+	0x2a, 0x5a, 0xf8, 0x4d, 0x02, 0x93, 0x11, 0xf8, 
+	0x2a, 0x9f, 0xf8, 0x4c, 0x02, 0x7c, 0x77, 0x12, 
+	0x2a, 0x39, 0x49, 0x12, 0x01, 0xf8, 0x2a, 0x9f, 
+	0x89, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x71, 0x81, 
+	0x00, 0x11, 0x6c, 0xe1, 0xff, 0xab, 0x02, 0x93, 
+	0x6b, 0xf8, 0x2a, 0x9f, 0x00, 0x01, 0xe9, 0x05, 
+	0x01, 0xe2, 0x00, 0x03, 0x81, 0xf8, 0x2a, 0xa0, 
+	0xf0, 0x73, 0x02, 0x95, 0x72, 0x11, 0x2a, 0x9f, 
+	0xf4, 0x95, 0x10, 0xe1, 0x2a, 0x39, 0x6b, 0xf8, 
+	0x2a, 0x9f, 0x00, 0x01, 0x11, 0xf8, 0x2a, 0x9f, 
+	0x09, 0xf8, 0x2a, 0xa0, 0xf8, 0x4c, 0x02, 0x93, 
+	0x76, 0xf8, 0x2a, 0x5a, 0x00, 0x00, 0x76, 0xf8, 
+	0x2a, 0x9f, 0x00, 0x00, 0x76, 0xf8, 0x2a, 0xa0, 
+	0x00, 0x00, 0x88, 0x11, 0xf4, 0x95, 0x48, 0x11, 
+	0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe, 
+	0x10, 0xf8, 0x2a, 0x5a, 0xf8, 0x44, 0x02, 0xb2, 
+	0x76, 0xf8, 0x2a, 0x5a, 0x00, 0x01, 0xf0, 0x74, 
+	0x02, 0x58, 0x88, 0x11, 0xf4, 0x95, 0x77, 0x10, 
+	0x80, 0x00, 0xf4, 0xa9, 0xf8, 0x30, 0x02, 0xb2, 
+	0x48, 0x11, 0xf0, 0x30, 0x00, 0xff, 0x80, 0x00, 
+	0x10, 0xf8, 0x2a, 0x5b, 0xf9, 0x80, 0x18, 0xd6, 
+	0xee, 0x02, 0x8a, 0x11, 0xfc, 0x00, 0xf4, 0x95, 
+	0x4a, 0x08, 0x4a, 0x09, 0x4a, 0x0a, 0x4a, 0x0b, 
+	0x4a, 0x0c, 0x4a, 0x0d, 0x4a, 0x10, 0x4a, 0x11, 
+	0x4a, 0x12, 0x4a, 0x13, 0x4a, 0x14, 0x4a, 0x15, 
+	0x4a, 0x16, 0x4a, 0x17, 0x4a, 0x17, 0x4a, 0x19, 
+	0x4a, 0x0e, 0x4a, 0x06, 0x4a, 0x07, 0x4a, 0x1a, 
+	0x4a, 0x1d, 0x4a, 0x1b, 0x4a, 0x1c, 0x68, 0xf8, 
+	0x00, 0x07, 0x7d, 0x3f, 0x69, 0xf8, 0x00, 0x07, 
+	0x40, 0x00, 0x68, 0xf8, 0x00, 0x1d, 0xff, 0xfc, 
+	0x48, 0x18, 0x68, 0xf8, 0x00, 0x18, 0xff, 0xfe, 
+	0xf4, 0x95, 0xf4, 0x95, 0x4a, 0x08, 0xee, 0xfd, 
+	0xf0, 0x74, 0x02, 0x58, 0x88, 0x11, 0xf4, 0x95, 
+	0x77, 0x10, 0x80, 0x00, 0xf4, 0xa9, 0xf8, 0x30, 
+	0x02, 0xef, 0x48, 0x11, 0xf0, 0x30, 0x00, 0xff, 
+	0x80, 0x00, 0x10, 0xf8, 0x2a, 0x5b, 0xf9, 0x80, 
+	0x18, 0xd6, 0xee, 0x03, 0x8a, 0x18, 0xf4, 0x95, 
+	0x8a, 0x1c, 0x8a, 0x1b, 0x8a, 0x1d, 0x8a, 0x1a, 
+	0x8a, 0x07, 0x8a, 0x06, 0x8a, 0x0e, 0x8a, 0x19, 
+	0x8a, 0x17, 0x8a, 0x17, 0x8a, 0x16, 0x8a, 0x15, 
+	0x8a, 0x14, 0x8a, 0x13, 0x8a, 0x12, 0x8a, 0x11, 
+	0x8a, 0x10, 0x8a, 0x0d, 0x8a, 0x0c, 0x8a, 0x0b, 
+	0x8a, 0x0a, 0x8a, 0x09, 0x8a, 0x08, 0xf4, 0xeb, 
+	0x4a, 0x11, 0x77, 0x11, 0x2a, 0x39, 0x76, 0x81, 
+	0x00, 0x55, 0x77, 0x12, 0x2a, 0x18, 0x10, 0xe2, 
+	0x00, 0x01, 0x80, 0xe1, 0x00, 0x01, 0x10, 0xe2, 
+	0x00, 0x02, 0x80, 0xe1, 0x00, 0x02, 0x76, 0xe1, 
+	0x00, 0x03, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x04, 
+	0x00, 0xaa, 0xf0, 0x74, 0x02, 0x98, 0x8a, 0x11, 
+	0xfc, 0x00, 0x4a, 0x11, 0x88, 0x11, 0xf4, 0x95, 
+	0xf4, 0x95, 0x10, 0x81, 0x6f, 0xf8, 0x2a, 0x9e, 
+	0x0c, 0x88, 0xe8, 0xff, 0x18, 0xe1, 0x00, 0x01, 
+	0x1a, 0xf8, 0x2a, 0x9e, 0xf0, 0x30, 0x1f, 0xff, 
+	0x80, 0xf8, 0x2a, 0x9e, 0x8a, 0x11, 0xfc, 0x00, 
+	0x4a, 0x11, 0x77, 0x11, 0x2a, 0x39, 0x76, 0x81, 
+	0x00, 0x55, 0x77, 0x12, 0x2a, 0x18, 0x11, 0xe2, 
+	0x00, 0x01, 0x81, 0xe1, 0x00, 0x01, 0x11, 0xe2, 
+	0x00, 0x02, 0x81, 0xe1, 0x00, 0x02, 0x76, 0xe1, 
+	0x00, 0x03, 0x00, 0x02, 0x48, 0x08, 0x6f, 0xe1, 
+	0x00, 0x04, 0x0c, 0x98, 0xf0, 0x30, 0x00, 0xff, 
+	0x80, 0xe1, 0x00, 0x05, 0x76, 0xe1, 0x00, 0x06, 
+	0x00, 0xaa, 0xf0, 0x74, 0x02, 0x98, 0x8a, 0x11, 
+	0xfc, 0x00, 0x4a, 0x11, 0x77, 0x11, 0x2a, 0x39, 
+	0x76, 0x81, 0x00, 0x55, 0x77, 0x12, 0x2a, 0x18, 
+	0x10, 0xe2, 0x00, 0x01, 0x80, 0xe1, 0x00, 0x01, 
+	0x10, 0xe2, 0x00, 0x02, 0x80, 0xe1, 0x00, 0x02, 
+	0x76, 0xe1, 0x00, 0x03, 0x00, 0x04, 0x48, 0x11, 
+	0xf0, 0x00, 0x00, 0x04, 0x88, 0x12, 0xf4, 0x95, 
+	0x77, 0x13, 0x2a, 0x76, 0xe9, 0x00, 0xe5, 0x98, 
+	0xf3, 0x00, 0x00, 0x01, 0xf6, 0xb8, 0x48, 0x0b, 
+	0x08, 0xf8, 0x2a, 0x3c, 0xf8, 0x43, 0x03, 0x71, 
+	0x76, 0x82, 0x00, 0xaa, 0xf0, 0x74, 0x02, 0x98, 
+	0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xf0, 
+	0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x71, 0x81, 
+	0x00, 0x14, 0x71, 0xe1, 0x00, 0x01, 0x00, 0x15, 
+	0x49, 0x11, 0xf3, 0x00, 0x00, 0x02, 0x89, 0x11, 
+	0xe7, 0x82, 0x6d, 0xea, 0x00, 0x04, 0xe7, 0x83, 
+	0x6d, 0xeb, 0x00, 0x0a, 0x77, 0x1a, 0x00, 0x05, 
+	0xf0, 0x72, 0x03, 0xaa, 0x11, 0x81, 0xf2, 0xe8, 
+	0x80, 0x82, 0xe9, 0xff, 0x19, 0xe1, 0x00, 0x01, 
+	0xf1, 0xa0, 0x81, 0x92, 0x11, 0xe1, 0x00, 0x0c, 
+	0xf2, 0xe8, 0x80, 0x83, 0xe9, 0xff, 0x19, 0xe1, 
+	0x00, 0x0d, 0xf1, 0xa0, 0x81, 0x93, 0x6d, 0xe9, 
+	0x00, 0x02, 0x48, 0x18, 0x49, 0x18, 0x70, 0x00, 
+	0x00, 0x15, 0xf0, 0x00, 0x00, 0x04, 0xf3, 0x00, 
+	0x00, 0x0a, 0x80, 0x01, 0x81, 0x02, 0xf2, 0x74, 
+	0x0e, 0x54, 0xf4, 0x95, 0x48, 0x14, 0xee, 0x10, 
+	0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xf0, 0x74, 
+	0x0c, 0x5e, 0x80, 0xf8, 0x2a, 0x5c, 0x77, 0x12, 
+	0x2a, 0x39, 0x76, 0x82, 0x00, 0x55, 0x77, 0x11, 
+	0x2a, 0x18, 0x10, 0xe1, 0x00, 0x01, 0x80, 0xe2, 
+	0x00, 0x01, 0x10, 0xe1, 0x00, 0x02, 0x80, 0xe2, 
+	0x00, 0x02, 0x76, 0xe2, 0x00, 0x03, 0x00, 0x1c, 
+	0xf6, 0xb8, 0x56, 0xf8, 0x2a, 0x16, 0xf0, 0xf0, 
+	0xf0, 0xf8, 0x80, 0xe2, 0x00, 0x07, 0x56, 0xf8, 
+	0x2a, 0x16, 0xf1, 0xf0, 0xe8, 0xff, 0xf2, 0x80, 
+	0x80, 0xe2, 0x00, 0x06, 0x56, 0xf8, 0x2a, 0x16, 
+	0xf1, 0xf8, 0xe8, 0xff, 0xf2, 0x80, 0x80, 0xe2, 
+	0x00, 0x05, 0x57, 0xf8, 0x2a, 0x16, 0xe8, 0xff, 
+	0xf2, 0x80, 0x80, 0xe2, 0x00, 0x04, 0x56, 0xf8, 
+	0x27, 0x6c, 0xf0, 0xf0, 0xf0, 0xf8, 0x80, 0xe2, 
+	0x00, 0x0b, 0x56, 0xf8, 0x27, 0x6c, 0xf1, 0xf0, 
+	0xe8, 0xff, 0xf2, 0x80, 0x80, 0xe2, 0x00, 0x0a, 
+	0x56, 0xf8, 0x27, 0x6c, 0xf1, 0xf8, 0xe8, 0xff, 
+	0xf2, 0x80, 0x80, 0xe2, 0x00, 0x09, 0xe8, 0xff, 
+	0x57, 0xf8, 0x27, 0x6c, 0xf2, 0x80, 0x80, 0xe2, 
+	0x00, 0x08, 0x56, 0xf8, 0x27, 0x6a, 0xf0, 0xf0, 
+	0xf0, 0xf8, 0x80, 0xe2, 0x00, 0x0f, 0x56, 0xf8, 
+	0x27, 0x6a, 0xf1, 0xf0, 0xe8, 0xff, 0xf2, 0x80, 
+	0x80, 0xe2, 0x00, 0x0e, 0x56, 0xf8, 0x27, 0x6a, 
+	0xf1, 0xf8, 0xe8, 0xff, 0xf2, 0x80, 0x80, 0xe2, 
+	0x00, 0x0d, 0x57, 0xf8, 0x27, 0x6a, 0xe8, 0xff, 
+	0xf2, 0x80, 0x80, 0xe2, 0x00, 0x0c, 0x76, 0xe2, 
+	0x00, 0x13, 0x00, 0x00, 0x76, 0xe2, 0x00, 0x12, 
+	0x00, 0x00, 0x6f, 0xf8, 0x2a, 0x5c, 0x0c, 0x58, 
+	0x80, 0xe2, 0x00, 0x11, 0xe8, 0xff, 0x18, 0xf8, 
+	0x2a, 0x5c, 0x80, 0xe2, 0x00, 0x10, 0x76, 0xe2, 
+	0x00, 0x17, 0x00, 0x00, 0x76, 0xe2, 0x00, 0x16, 
+	0x00, 0x00, 0x6f, 0xf8, 0x2a, 0x9e, 0x0c, 0x58, 
+	0x80, 0xe2, 0x00, 0x15, 0xe8, 0xff, 0x18, 0xf8, 
+	0x2a, 0x9e, 0x80, 0xe2, 0x00, 0x14, 0x76, 0xe2, 
+	0x00, 0x1b, 0x00, 0x00, 0x76, 0xe2, 0x00, 0x1a, 
+	0x00, 0x00, 0x76, 0xe2, 0x00, 0x19, 0x00, 0x00, 
+	0x70, 0xe2, 0x00, 0x18, 0x27, 0x6e, 0x76, 0xe2, 
+	0x00, 0x1f, 0x00, 0x00, 0x76, 0xe2, 0x00, 0x1e, 
+	0x00, 0x00, 0x76, 0xe2, 0x00, 0x1d, 0x00, 0x00, 
+	0x76, 0xe2, 0x00, 0x1c, 0x00, 0x00, 0x76, 0xe2, 
+	0x00, 0x20, 0x00, 0xaa, 0xf0, 0x74, 0x02, 0x98, 
+	0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe, 
+	0x10, 0xf8, 0x2a, 0x38, 0xf8, 0x45, 0x04, 0xed, 
+	0x77, 0x12, 0x2a, 0x18, 0x10, 0xe2, 0x00, 0x02, 
+	0x88, 0x11, 0xf4, 0x95, 0x77, 0x10, 0x00, 0x08, 
+	0x6d, 0xe9, 0xff, 0xdf, 0xf6, 0xa9, 0xf8, 0x20, 
+	0x04, 0x75, 0xf0, 0x73, 0x04, 0x7d, 0xf0, 0x10, 
+	0x00, 0x21, 0xf0, 0x00, 0x1a, 0x83, 0x48, 0x08, 
+	0x7e, 0xf8, 0x00, 0x08, 0xf4, 0xe2, 0xf0, 0x74, 
+	0x03, 0x0a, 0xf0, 0x73, 0x04, 0xea, 0x48, 0x12, 
+	0xf2, 0x74, 0x03, 0x23, 0xf0, 0x00, 0x00, 0x04, 
+	0xf2, 0x74, 0x03, 0x36, 0xf4, 0x95, 0xe8, 0x00, 
+	0xf0, 0x73, 0x04, 0xea, 0x77, 0x11, 0x2a, 0x18, 
+	0xe8, 0xff, 0x6f, 0xe1, 0x00, 0x04, 0x0d, 0x48, 
+	0x18, 0xe1, 0x00, 0x05, 0xf2, 0x74, 0x09, 0x69, 
+	0xf4, 0x95, 0xf2, 0xa0, 0xf0, 0x74, 0x03, 0x36, 
+	0xf0, 0x73, 0x04, 0xea, 0x77, 0x11, 0x2a, 0x18, 
+	0xe8, 0xff, 0x6f, 0xe1, 0x00, 0x04, 0x0d, 0x48, 
+	0x18, 0xe1, 0x00, 0x05, 0xf2, 0x74, 0x09, 0x41, 
+	0xf4, 0x95, 0xf2, 0xa0, 0xf0, 0x74, 0x03, 0x36, 
+	0xf0, 0x73, 0x04, 0xea, 0xf0, 0x74, 0x03, 0x57, 
+	0xf0, 0x73, 0x04, 0xea, 0x10, 0xf8, 0x2a, 0x1c, 
+	0xf0, 0x74, 0x12, 0xa4, 0xf2, 0x74, 0x03, 0x36, 
+	0xf4, 0x95, 0xe8, 0x00, 0xf0, 0x73, 0x04, 0xea, 
+	0x48, 0x12, 0xf2, 0x74, 0x03, 0x80, 0xf0, 0x00, 
+	0x00, 0x04, 0xf2, 0x74, 0x03, 0x36, 0xf4, 0x95, 
+	0xe8, 0x00, 0xf0, 0x73, 0x04, 0xea, 0x10, 0xf8, 
+	0x2a, 0x1c, 0xf0, 0x74, 0x12, 0xc5, 0xf2, 0x74, 
+	0x03, 0x36, 0xf4, 0x95, 0xe8, 0x00, 0xf0, 0x73, 
+	0x04, 0xea, 0x77, 0x11, 0x2a, 0x18, 0xe8, 0xff, 
+	0x6f, 0xe1, 0x00, 0x06, 0x0d, 0x48, 0x18, 0xe1, 
+	0x00, 0x07, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 
+	0xf2, 0xa0, 0x70, 0x00, 0x00, 0x12, 0x80, 0x01, 
+	0x10, 0xe1, 0x00, 0x04, 0xf0, 0x74, 0x0e, 0x7a, 
+	0xf2, 0x74, 0x03, 0x36, 0xf4, 0x95, 0xe8, 0x00, 
+	0xf0, 0x73, 0x04, 0xea, 0xf0, 0x74, 0x03, 0xbc, 
+	0x76, 0xf8, 0x2a, 0x38, 0x00, 0x00, 0xee, 0x02, 
+	0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x77, 0x11, 
+	0x2a, 0x39, 0x76, 0x81, 0x00, 0x55, 0x77, 0x12, 
+	0x2a, 0x18, 0x10, 0xe2, 0x00, 0x01, 0x80, 0xe1, 
+	0x00, 0x01, 0x10, 0xe2, 0x00, 0x02, 0x80, 0xe1, 
+	0x00, 0x02, 0x76, 0xe1, 0x00, 0x03, 0x00, 0x09, 
+	0x48, 0x11, 0xf0, 0x00, 0x00, 0x04, 0x88, 0x12, 
+	0xf4, 0x95, 0x77, 0x13, 0x2a, 0x86, 0xe9, 0x00, 
+	0xe5, 0x98, 0xf3, 0x00, 0x00, 0x01, 0xf6, 0xb8, 
+	0x48, 0x0b, 0x08, 0xf8, 0x2a, 0x3c, 0xf8, 0x43, 
+	0x05, 0x0a, 0x76, 0x82, 0x00, 0xaa, 0xf0, 0x74, 
+	0x02, 0x98, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 
+	0x77, 0x11, 0x2a, 0x39, 0x76, 0x81, 0x00, 0x55, 
+	0x77, 0x13, 0x2a, 0x18, 0x10, 0xe3, 0x00, 0x01, 
+	0x80, 0xe1, 0x00, 0x01, 0x10, 0xe3, 0x00, 0x02, 
+	0x80, 0xe1, 0x00, 0x02, 0x13, 0xe3, 0x00, 0x03, 
+	0x81, 0xe1, 0x00, 0x03, 0x48, 0x11, 0x77, 0x11, 
+	0x00, 0x00, 0xf8, 0x4d, 0x05, 0x44, 0xf0, 0x00, 
+	0x00, 0x04, 0x88, 0x12, 0x48, 0x13, 0xf0, 0x00, 
+	0x00, 0x04, 0x88, 0x13, 0xf4, 0x95, 0xf4, 0x95, 
+	0xe5, 0x98, 0x6d, 0x91, 0xf6, 0xb8, 0x48, 0x11, 
+	0x08, 0xf8, 0x2a, 0x3c, 0xf8, 0x43, 0x05, 0x3a, 
+	0xf0, 0x20, 0x2a, 0x39, 0x49, 0x11, 0xf5, 0x00, 
+	0x89, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x76, 0xe1, 
+	0x00, 0x04, 0x00, 0xaa, 0xf0, 0x74, 0x02, 0x98, 
+	0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x77, 0x11, 
+	0x2a, 0x39, 0x76, 0x81, 0x00, 0x55, 0x77, 0x12, 
+	0x2a, 0x18, 0x10, 0xe2, 0x00, 0x01, 0x80, 0xe1, 
+	0x00, 0x01, 0x10, 0xe2, 0x00, 0x02, 0x80, 0xe1, 
+	0x00, 0x02, 0x76, 0xe1, 0x00, 0x03, 0x00, 0x0c, 
+	0x48, 0x11, 0xf0, 0x00, 0x00, 0x04, 0x88, 0x12, 
+	0xf4, 0x95, 0x77, 0x13, 0x2a, 0x7a, 0xe9, 0x00, 
+	0xe5, 0x98, 0xf3, 0x00, 0x00, 0x01, 0xf6, 0xb8, 
+	0x48, 0x0b, 0x08, 0xf8, 0x2a, 0x3c, 0xf8, 0x43, 
+	0x05, 0x6a, 0x76, 0x82, 0x00, 0xaa, 0xf0, 0x74, 
+	0x02, 0x98, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 
+	0x77, 0x11, 0x2a, 0x39, 0x76, 0x81, 0x00, 0x55, 
+	0x77, 0x12, 0x2a, 0x18, 0x10, 0xe2, 0x00, 0x01, 
+	0x80, 0xe1, 0x00, 0x01, 0x10, 0xe2, 0x00, 0x02, 
+	0x80, 0xe1, 0x00, 0x02, 0x76, 0xe1, 0x00, 0x03, 
+	0x00, 0x19, 0x48, 0x11, 0xf0, 0x00, 0x00, 0x04, 
+	0x88, 0x12, 0xf4, 0x95, 0x77, 0x13, 0x2a, 0x5d, 
+	0xe9, 0x00, 0xe5, 0x98, 0xf3, 0x00, 0x00, 0x01, 
+	0xf6, 0xb8, 0x48, 0x0b, 0x08, 0xf8, 0x2a, 0x3c, 
+	0xf8, 0x43, 0x05, 0x93, 0x76, 0x82, 0x00, 0xaa, 
+	0xf0, 0x74, 0x02, 0x98, 0x8a, 0x11, 0xfc, 0x00, 
+	0x4a, 0x11, 0x88, 0x11, 0x10, 0xf8, 0x2a, 0x38, 
+	0xf8, 0x44, 0x05, 0xe3, 0x10, 0xf8, 0x2a, 0xa1, 
+	0xf8, 0x44, 0x05, 0xba, 0x6c, 0xe1, 0xff, 0x56, 
+	0x05, 0xe3, 0x72, 0x12, 0x2a, 0xa1, 0xf4, 0x95, 
+	0x70, 0xe2, 0x2a, 0x18, 0x00, 0x11, 0x6b, 0xf8, 
+	0x2a, 0xa1, 0x00, 0x01, 0xf0, 0x73, 0x05, 0xe3, 
+	0x72, 0x12, 0x2a, 0xa1, 0xf4, 0x95, 0x70, 0xe2, 
+	0x2a, 0x18, 0x00, 0x11, 0x10, 0xf8, 0x2a, 0xa1, 
+	0xf0, 0x00, 0x00, 0x01, 0x88, 0x12, 0xf4, 0x95, 
+	0xf4, 0x95, 0x6e, 0xe2, 0xff, 0xfc, 0x05, 0xd1, 
+	0x73, 0x12, 0x2a, 0xa1, 0x48, 0x11, 0xf0, 0x00, 
+	0x00, 0x05, 0x80, 0xf8, 0x2a, 0xa2, 0x10, 0xf8, 
+	0x2a, 0xa1, 0x08, 0xf8, 0x2a, 0xa2, 0xf8, 0x44, 
+	0x05, 0xe3, 0x6c, 0xe1, 0xff, 0xab, 0x05, 0xdd, 
+	0x76, 0xf8, 0x2a, 0x38, 0x00, 0x01, 0x76, 0xf8, 
+	0x2a, 0xa1, 0x00, 0x00, 0x76, 0xf8, 0x2a, 0xa2, 
+	0x00, 0x00, 0x8a, 0x11, 0xfc, 0x00, 0xf4, 0x95, 
+	0x4a, 0x08, 0x4a, 0x09, 0x4a, 0x0a, 0x4a, 0x0b, 
+	0x4a, 0x0c, 0x4a, 0x0d, 0x4a, 0x10, 0x4a, 0x11, 
+	0x4a, 0x12, 0x4a, 0x13, 0x4a, 0x14, 0x4a, 0x15, 
+	0x4a, 0x16, 0x4a, 0x17, 0x4a, 0x17, 0x4a, 0x19, 
+	0x4a, 0x0e, 0x4a, 0x06, 0x4a, 0x07, 0x4a, 0x1a, 
+	0x4a, 0x1d, 0x4a, 0x1b, 0x4a, 0x1c, 0x68, 0xf8, 
+	0x00, 0x07, 0x7d, 0x3f, 0x69, 0xf8, 0x00, 0x07, 
+	0x40, 0x00, 0x68, 0xf8, 0x00, 0x1d, 0xff, 0xfc, 
+	0x48, 0x18, 0x68, 0xf8, 0x00, 0x18, 0xff, 0xfe, 
+	0xf4, 0x95, 0xf4, 0x95, 0x4a, 0x08, 0xee, 0xff, 
+	0x10, 0xf8, 0x2a, 0x5b, 0xf9, 0x80, 0x18, 0x04, 
+	0xf0, 0x74, 0x05, 0xa2, 0xee, 0x01, 0x8a, 0x18, 
+	0xf4, 0x95, 0x8a, 0x1c, 0x8a, 0x1b, 0x8a, 0x1d, 
+	0x8a, 0x1a, 0x8a, 0x07, 0x8a, 0x06, 0x8a, 0x0e, 
+	0x8a, 0x19, 0x8a, 0x17, 0x8a, 0x17, 0x8a, 0x16, 
+	0x8a, 0x15, 0x8a, 0x14, 0x8a, 0x13, 0x8a, 0x12, 
+	0x8a, 0x11, 0x8a, 0x10, 0x8a, 0x0d, 0x8a, 0x0c, 
+	0x8a, 0x0b, 0x8a, 0x0a, 0x8a, 0x09, 0x8a, 0x08, 
+	0xf4, 0xeb, 0xee, 0xfd, 0x76, 0xf8, 0x2a, 0x38, 
+	0x00, 0x00, 0x76, 0xf8, 0x2a, 0x5a, 0x00, 0x00, 
+	0xe8, 0x01, 0x4e, 0x00, 0xfb, 0x80, 0x17, 0xd6, 
+	0xf4, 0x95, 0xe8, 0x01, 0x80, 0xf8, 0x2a, 0x5b, 
+	0x76, 0x00, 0x2a, 0x8f, 0xf9, 0x80, 0x16, 0xaa, 
+	0x10, 0xf8, 0x2a, 0x5b, 0xf9, 0x80, 0x17, 0x5c, 
+	0x10, 0xf8, 0x2a, 0x5b, 0xf9, 0x80, 0x17, 0x6f, 
+	0xfb, 0x80, 0x16, 0x66, 0xf4, 0x95, 0xe8, 0x1a, 
+	0xfb, 0x80, 0x16, 0x87, 0xf4, 0x95, 0xe8, 0x1a, 
+	0xfb, 0x80, 0x16, 0x66, 0xf4, 0x95, 0xe8, 0x1b, 
+	0xfb, 0x80, 0x16, 0x87, 0xf4, 0x95, 0xe8, 0x1b, 
+	0xee, 0x03, 0xfc, 0x00, 0x4a, 0x11, 0xf4, 0x95, 
+	0x13, 0x02, 0x88, 0x11, 0xe8, 0x00, 0xf8, 0x4d, 
+	0x06, 0x6a, 0xf3, 0x10, 0x00, 0x01, 0x89, 0x1a, 
+	0xf4, 0x95, 0xf0, 0x72, 0x06, 0x69, 0x1c, 0x91, 
+	0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x88, 0x11, 
+	0x12, 0x03, 0x11, 0x02, 0xf8, 0x45, 0x06, 0x79, 
+	0xf0, 0x10, 0x00, 0x01, 0x88, 0x1a, 0xf4, 0x95, 
+	0xf0, 0x72, 0x06, 0x78, 0x81, 0x91, 0x8a, 0x11, 
+	0xfc, 0x00, 0x4a, 0x11, 0xf4, 0x95, 0x71, 0x02, 
+	0x00, 0x11, 0x11, 0x03, 0x61, 0xf8, 0x00, 0x11, 
+	0x00, 0x01, 0xf8, 0x30, 0x06, 0x91, 0xf6, 0xb8, 
+	0x6f, 0xf8, 0x00, 0x11, 0x0c, 0x1f, 0x88, 0x11, 
+	0xf3, 0xe8, 0xe8, 0xff, 0x18, 0x81, 0xf1, 0xa0, 
+	0x81, 0x81, 0xf0, 0x73, 0x06, 0x9d, 0xf6, 0xb8, 
+	0x6f, 0xf8, 0x00, 0x11, 0x0c, 0x1f, 0x88, 0x11, 
+	0xf3, 0x30, 0x00, 0xff, 0xf0, 0x20, 0xff, 0x00, 
+	0x18, 0x81, 0xf1, 0xa0, 0x81, 0x81, 0x8a, 0x11, 
+	0xfc, 0x00, 0x4a, 0x11, 0xf4, 0x95, 0x11, 0x02, 
+	0x61, 0xf8, 0x00, 0x0b, 0x00, 0x01, 0xf8, 0x20, 
+	0x06, 0xb1, 0x49, 0x0b, 0xf6, 0x1f, 0x88, 0x11, 
+	0xf4, 0x95, 0xf4, 0x95, 0x10, 0x81, 0xf2, 0x73, 
+	0x06, 0xb8, 0xf0, 0x30, 0x00, 0xff, 0x49, 0x0b, 
+	0xf6, 0x1f, 0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 
+	0x12, 0x81, 0xf4, 0x78, 0x8a, 0x11, 0xfc, 0x00, 
+	0x4a, 0x11, 0xf4, 0x95, 0x71, 0x02, 0x00, 0x12, 
+	0x13, 0x03, 0x88, 0x11, 0xe8, 0x00, 0xf8, 0x4d, 
+	0x06, 0xcc, 0xf3, 0x10, 0x00, 0x01, 0x89, 0x1a, 
+	0xf4, 0x95, 0xf0, 0x72, 0x06, 0xcb, 0x11, 0x92, 
+	0xf2, 0xc0, 0x81, 0x91, 0x8a, 0x11, 0xfc, 0x00, 
+	0x88, 0x12, 0x12, 0x02, 0x71, 0x01, 0x00, 0x13, 
+	0xf8, 0x45, 0x06, 0xdb, 0xf0, 0x10, 0x00, 0x01, 
+	0x88, 0x1a, 0xf4, 0x95, 0xf0, 0x72, 0x06, 0xda, 
+	0xe5, 0x98, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe, 
+	0x88, 0x11, 0x11, 0x04, 0x10, 0x06, 0x71, 0x05, 
+	0x00, 0x12, 0x61, 0xf8, 0x00, 0x12, 0x00, 0x01, 
+	0xf8, 0x20, 0x06, 0xea, 0xf0, 0x00, 0x00, 0x01, 
+	0xf6, 0xb8, 0xf0, 0x00, 0x00, 0x01, 0x6f, 0xf8, 
+	0x00, 0x12, 0x0f, 0x1f, 0x48, 0x08, 0x81, 0x00, 
+	0xf4, 0x7f, 0x80, 0x01, 0xf2, 0x74, 0x06, 0xba, 
+	0xf4, 0x95, 0x48, 0x11, 0xee, 0x02, 0x8a, 0x11, 
+	0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe, 0x88, 0x12, 
+	0x11, 0x04, 0x10, 0x06, 0x71, 0x05, 0x00, 0x13, 
+	0x61, 0xf8, 0x00, 0x13, 0x00, 0x01, 0xf8, 0x20, 
+	0x07, 0x09, 0xf0, 0x00, 0x00, 0x01, 0xf0, 0x00, 
+	0x00, 0x01, 0x88, 0x11, 0xf6, 0xb8, 0x6f, 0xf8, 
+	0x00, 0x13, 0x0f, 0x1f, 0x81, 0x00, 0x48, 0x11, 
+	0xf4, 0x7f, 0x80, 0x01, 0xf2, 0x74, 0x06, 0xce, 
+	0xf4, 0x95, 0x48, 0x12, 0x48, 0x11, 0xf0, 0x30, 
+	0xff, 0xfe, 0xee, 0x02, 0x8a, 0x11, 0xfc, 0x00, 
+	0x4a, 0x11, 0x4a, 0x16, 0x4a, 0x17, 0xee, 0xfc, 
+	0xf4, 0x95, 0x80, 0x02, 0x71, 0x08, 0x00, 0x16, 
+	0x10, 0x09, 0x71, 0x0b, 0x00, 0x17, 0x80, 0x03, 
+	0x71, 0x0a, 0x00, 0x11, 0x48, 0x17, 0xf8, 0x45, 
+	0x07, 0x3f, 0x70, 0x00, 0x00, 0x11, 0x10, 0x03, 
+	0xf0, 0x74, 0x06, 0x9f, 0x80, 0x01, 0x70, 0x00, 
+	0x00, 0x16, 0x10, 0x02, 0xf0, 0x74, 0x06, 0x7b, 
+	0x6d, 0x91, 0x6d, 0x96, 0x6c, 0xef, 0xff, 0xff, 
+	0x07, 0x2f, 0xee, 0x04, 0x8a, 0x17, 0x8a, 0x16, 
+	0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe, 
+	0x10, 0xf8, 0x2a, 0xe8, 0x08, 0xf8, 0x2a, 0xe9, 
+	0xf8, 0x45, 0x07, 0x64, 0x76, 0x00, 0x00, 0x01, 
+	0x62, 0xf8, 0x2a, 0xe9, 0x00, 0x5e, 0xf2, 0x74, 
+	0x12, 0x0b, 0xf0, 0x00, 0x30, 0x40, 0x72, 0x11, 
+	0x2a, 0xe9, 0x77, 0x10, 0x00, 0x0f, 0xf5, 0xa9, 
+	0xf8, 0x20, 0x07, 0x61, 0x6b, 0xf8, 0x2a, 0xe9, 
+	0x00, 0x01, 0xf0, 0x73, 0x07, 0x64, 0x76, 0xf8, 
+	0x2a, 0xe9, 0x00, 0x00, 0xee, 0x02, 0x8a, 0x11, 
+	0xfc, 0x00, 0x4a, 0x11, 0x88, 0x11, 0xe8, 0x00, 
+	0x75, 0xf8, 0x00, 0x08, 0x00, 0x08, 0xe8, 0x00, 
+	0x75, 0xf8, 0x00, 0x08, 0x00, 0x09, 0xf6, 0xb8, 
+	0xf4, 0x95, 0xf0, 0x20, 0xfc, 0x3f, 0x75, 0xf8, 
+	0x00, 0x08, 0x00, 0x0d, 0xf0, 0x20, 0x0c, 0x30, 
+	0x75, 0xf8, 0x00, 0x08, 0x00, 0x0c, 0x76, 0xf8, 
+	0x2a, 0xe8, 0x00, 0x00, 0x76, 0xf8, 0x2a, 0xe9, 
+	0x00, 0x00, 0x6c, 0x81, 0x07, 0x92, 0x76, 0xf8, 
+	0x2a, 0xea, 0x00, 0x00, 0xfb, 0x80, 0x16, 0x76, 
+	0xf4, 0x95, 0xe8, 0x10, 0xe8, 0x00, 0x75, 0xf8, 
+	0x00, 0x08, 0x00, 0x00, 0xf0, 0x73, 0x07, 0xa8, 
+	0x76, 0xf8, 0x2a, 0xea, 0x00, 0x01, 0xfb, 0x80, 
+	0x16, 0x66, 0xf4, 0x95, 0xe8, 0x10, 0xfb, 0x80, 
+	0x16, 0x87, 0xf4, 0x95, 0xe8, 0x10, 0xe8, 0x00, 
+	0x75, 0xf8, 0x00, 0x08, 0x00, 0x00, 0xf6, 0xb8, 
+	0xf4, 0x95, 0xf0, 0x20, 0xff, 0xff, 0x75, 0xf8, 
+	0x00, 0x08, 0x00, 0x00, 0x8a, 0x11, 0xfc, 0x00, 
+	0xf4, 0x95, 0x4a, 0x08, 0x4a, 0x09, 0x4a, 0x0a, 
+	0x4a, 0x06, 0x4a, 0x07, 0x4a, 0x1d, 0x68, 0xf8, 
+	0x00, 0x07, 0x7d, 0x3f, 0x69, 0xf8, 0x00, 0x07, 
+	0x40, 0x00, 0x68, 0xf8, 0x00, 0x1d, 0xff, 0xfc, 
+	0x10, 0xf8, 0x2a, 0xea, 0xf8, 0x45, 0x07, 0xe1, 
+	0x10, 0xf8, 0x2a, 0xe8, 0xf0, 0x00, 0x00, 0x01, 
+	0xf0, 0x30, 0x00, 0x0f, 0x80, 0xf8, 0x2a, 0xe8, 
+	0x10, 0xf8, 0x2a, 0xe8, 0xf8, 0x44, 0x07, 0xd6, 
+	0xf6, 0xb8, 0xf4, 0x95, 0xf0, 0x20, 0xfc, 0x3f, 
+	0x75, 0xf8, 0x00, 0x08, 0x00, 0x0d, 0xf0, 0x20, 
+	0x0c, 0x30, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x0c, 
+	0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x00, 
+	0xf6, 0xb8, 0xf4, 0x95, 0xf0, 0x20, 0xff, 0xff, 
+	0x75, 0xf8, 0x00, 0x08, 0x00, 0x00, 0x8a, 0x1d, 
+	0x8a, 0x07, 0x8a, 0x06, 0x8a, 0x0a, 0x8a, 0x09, 
+	0x8a, 0x08, 0xf4, 0xeb, 0xee, 0xff, 0xf2, 0x74, 
+	0x07, 0x67, 0xf4, 0x95, 0xe8, 0x01, 0xee, 0x01, 
+	0xfc, 0x00, 0x4a, 0x07, 0x4a, 0x1d, 0x68, 0xf8, 
+	0x00, 0x07, 0x7d, 0x3f, 0x69, 0xf8, 0x00, 0x07, 
+	0x40, 0x00, 0x68, 0xf8, 0x00, 0x1d, 0xff, 0xfc, 
+	0x8a, 0x1d, 0x8a, 0x07, 0xf4, 0xeb, 0x4a, 0x11, 
+	0x77, 0x11, 0x00, 0x28, 0x76, 0x81, 0x24, 0x00, 
+	0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, 
+	0xf2, 0x74, 0x07, 0x67, 0xf4, 0x95, 0xe8, 0x00, 
+	0x77, 0x11, 0x00, 0x1d, 0x68, 0x81, 0x00, 0x7f, 
+	0xf6, 0xb8, 0xf4, 0x95, 0xf0, 0x20, 0xff, 0x80, 
+	0x77, 0x11, 0x00, 0x1d, 0xf0, 0x30, 0x01, 0x00, 
+	0x1a, 0x81, 0x80, 0x81, 0xf0, 0x74, 0x0a, 0x33, 
+	0xf0, 0x74, 0x11, 0xac, 0xf9, 0x80, 0x13, 0x25, 
+	0xf9, 0x80, 0x16, 0x53, 0xf9, 0x80, 0x17, 0x82, 
+	0xf0, 0x74, 0x06, 0x2f, 0xf9, 0x80, 0x14, 0xb2, 
+	0xf9, 0x80, 0x19, 0x10, 0xf0, 0x74, 0x0d, 0xe3, 
+	0xf0, 0x74, 0x07, 0xe8, 0xf0, 0x74, 0x02, 0x36, 
+	0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x60, 0xf8, 
+	0x27, 0x7b, 0xff, 0xff, 0xf8, 0x30, 0x08, 0x39, 
+	0x71, 0xf8, 0x27, 0x7b, 0x27, 0x79, 0x60, 0xf8, 
+	0x27, 0x79, 0xff, 0xff, 0xf8, 0x30, 0x08, 0xb2, 
+	0x10, 0xf8, 0x29, 0x86, 0x08, 0xf8, 0x27, 0x79, 
+	0xf0, 0x30, 0x7f, 0xff, 0x88, 0x11, 0xf4, 0x95, 
+	0x77, 0x10, 0x40, 0x00, 0xf6, 0xa9, 0xf8, 0x30, 
+	0x08, 0x58, 0x10, 0xf8, 0x27, 0x79, 0x08, 0xf8, 
+	0x27, 0x7a, 0xf0, 0x30, 0x7f, 0xff, 0x88, 0x11, 
+	0xf4, 0x95, 0x77, 0x10, 0x40, 0x00, 0xf6, 0xa9, 
+	0xf8, 0x20, 0x08, 0x63, 0x76, 0xf8, 0x27, 0x79, 
+	0xff, 0xff, 0x76, 0xf8, 0x27, 0x7b, 0xff, 0xff, 
+	0xf7, 0xb8, 0xf2, 0x73, 0x08, 0xd9, 0xf0, 0x20, 
+	0xff, 0xff, 0xf6, 0xb8, 0x56, 0xf8, 0x27, 0x74, 
+	0xf0, 0xf9, 0x88, 0x11, 0x56, 0xf8, 0x27, 0x72, 
+	0xf0, 0xf9, 0x88, 0x12, 0xf4, 0x95, 0xf4, 0x95, 
+	0xe7, 0x20, 0xf4, 0xa9, 0xf8, 0x30, 0x08, 0x8f, 
+	0xf1, 0x20, 0x27, 0x7c, 0x48, 0x11, 0xf6, 0x00, 
+	0x88, 0x13, 0xf4, 0x95, 0xf4, 0x95, 0x10, 0x83, 
+	0x08, 0xf8, 0x27, 0x79, 0xf0, 0x30, 0x7f, 0xff, 
+	0x88, 0x13, 0xf4, 0x95, 0x77, 0x10, 0x40, 0x00, 
+	0xf5, 0xab, 0xf8, 0x30, 0x08, 0x8f, 0x6d, 0x91, 
+	0x48, 0x11, 0xf0, 0x30, 0x01, 0xff, 0x88, 0x11, 
+	0xf4, 0x95, 0xe7, 0x20, 0xf7, 0xa9, 0xf8, 0x30, 
+	0x08, 0x74, 0x6d, 0x89, 0x48, 0x11, 0xf0, 0x30, 
+	0x01, 0xff, 0xf0, 0xe7, 0xf4, 0x95, 0x48, 0x08, 
+	0x4e, 0xf8, 0x27, 0x74, 0x48, 0x08, 0xf1, 0xf9, 
+	0x89, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x71, 0xe1, 
+	0x27, 0x7c, 0x27, 0x7a, 0x60, 0xf8, 0x27, 0x7b, 
+	0xff, 0xff, 0xf8, 0x30, 0x08, 0xab, 0x48, 0x08, 
+	0x4e, 0xf8, 0x27, 0x72, 0x76, 0xf8, 0x27, 0x7b, 
+	0xff, 0xff, 0x76, 0xf8, 0x27, 0x79, 0xff, 0xff, 
+	0xf2, 0x73, 0x08, 0xd9, 0xf4, 0x95, 0xe8, 0x00, 
+	0x44, 0xf8, 0x27, 0x73, 0x40, 0xf8, 0x27, 0x75, 
+	0x82, 0xf8, 0x00, 0x11, 0xf4, 0x95, 0x77, 0x10, 
+	0x80, 0x00, 0xf6, 0xa9, 0xf8, 0x20, 0x08, 0xd8, 
+	0xf6, 0xb8, 0x10, 0xf8, 0x27, 0x73, 0xf0, 0x00, 
+	0x80, 0x00, 0x48, 0x08, 0x4e, 0xf8, 0x27, 0x74, 
+	0x48, 0x08, 0xf0, 0xf9, 0x88, 0x11, 0xf4, 0x95, 
+	0xf4, 0x95, 0x71, 0xe1, 0x27, 0x7c, 0x27, 0x7a, 
+	0xf7, 0xb8, 0x57, 0xf8, 0x27, 0x74, 0xf0, 0x62, 
+	0xff, 0xff, 0xf0, 0x40, 0xff, 0x80, 0xf2, 0x80, 
+	0x4e, 0xf8, 0x27, 0x74, 0xe8, 0x00, 0x8a, 0x11, 
+	0xfc, 0x00, 0x4a, 0x11, 0x4a, 0x16, 0xee, 0xfb, 
+	0x11, 0xf8, 0x27, 0x71, 0x09, 0xf8, 0x27, 0x73, 
+	0x89, 0x11, 0x88, 0x10, 0xf4, 0x95, 0xf4, 0x95, 
+	0xf6, 0xa9, 0xf8, 0x20, 0x08, 0xed, 0xf2, 0x73, 
+	0x09, 0x0e, 0xf4, 0x95, 0xe8, 0x00, 0xf6, 0x20, 
+	0x76, 0x00, 0x00, 0x41, 0xf0, 0x74, 0x12, 0xee, 
+	0x88, 0x16, 0xf4, 0x95, 0xf7, 0xb8, 0x6d, 0x96, 
+	0x10, 0xf8, 0x00, 0x16, 0xf8, 0x47, 0x09, 0x0a, 
+	0xe7, 0x61, 0x76, 0x00, 0x00, 0x00, 0x76, 0x01, 
+	0x00, 0x80, 0x76, 0x02, 0x00, 0xff, 0x76, 0x03, 
+	0x00, 0x00, 0xf2, 0x74, 0x0c, 0xb9, 0xf4, 0x95, 
+	0xe8, 0x00, 0x6c, 0xe9, 0xff, 0xff, 0x08, 0xfb, 
+	0x73, 0x16, 0x00, 0x0e, 0xf0, 0x66, 0x00, 0x41, 
+	0xee, 0x05, 0x8a, 0x16, 0x8a, 0x11, 0xfc, 0x00, 
+	0x4a, 0x11, 0xf4, 0x95, 0x71, 0x02, 0x00, 0x13, 
+	0xf6, 0xb8, 0x77, 0x11, 0x7f, 0xff, 0x57, 0xf8, 
+	0x27, 0x72, 0x48, 0x11, 0xf2, 0x80, 0xf0, 0x00, 
+	0x80, 0x00, 0x88, 0x11, 0xf6, 0x40, 0xf0, 0xe0, 
+	0xf1, 0xf1, 0xe8, 0x01, 0xf2, 0x80, 0x80, 0xf8, 
+	0x27, 0x78, 0x77, 0x12, 0x80, 0x00, 0x57, 0xf8, 
+	0x27, 0x72, 0x48, 0x12, 0xf2, 0x80, 0x88, 0x12, 
+	0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x82, 0x09, 0x38, 
+	0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, 
+	0xf0, 0x73, 0x09, 0x3d, 0xf0, 0x20, 0x80, 0x01, 
+	0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, 0x70, 0x81, 
+	0x00, 0x13, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 
+	0xf0, 0x30, 0x7f, 0xff, 0x11, 0xf8, 0x29, 0x86, 
+	0xf5, 0x20, 0xf3, 0x30, 0x7f, 0xff, 0x89, 0x11, 
+	0xf4, 0x95, 0x77, 0x10, 0x40, 0x00, 0xf6, 0xa9, 
+	0xf8, 0x20, 0x09, 0x54, 0xf2, 0x73, 0x09, 0x67, 
+	0xf4, 0x95, 0xe8, 0x02, 0x6f, 0xf8, 0x27, 0x7a, 
+	0x0d, 0x20, 0xf3, 0x30, 0x7f, 0xff, 0x89, 0x11, 
+	0xf4, 0x95, 0x77, 0x10, 0x40, 0x00, 0xf6, 0xa9, 
+	0xf8, 0x20, 0x09, 0x64, 0xf2, 0x73, 0x09, 0x67, 
+	0xf4, 0x95, 0xe8, 0x01, 0x80, 0xf8, 0x27, 0x7b, 
+	0xe8, 0x00, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 
+	0x11, 0xf8, 0x29, 0x86, 0xf5, 0x20, 0xf3, 0x30, 
+	0x7f, 0xff, 0x89, 0x11, 0xf4, 0x95, 0x77, 0x10, 
+	0x40, 0x00, 0xf6, 0xa9, 0xf8, 0x20, 0x09, 0x7a, 
+	0xf2, 0x73, 0x09, 0x8d, 0xf4, 0x95, 0xe8, 0x02, 
+	0x6f, 0xf8, 0x27, 0x7a, 0x0d, 0x20, 0xf3, 0x30, 
+	0x7f, 0xff, 0x89, 0x11, 0xf4, 0x95, 0x77, 0x10, 
+	0x40, 0x00, 0xf6, 0xa9, 0xf8, 0x20, 0x09, 0x8a, 
+	0xf2, 0x73, 0x09, 0x8d, 0xf4, 0x95, 0xe8, 0x01, 
+	0x80, 0xf8, 0x27, 0x79, 0xe8, 0x00, 0x8a, 0x11, 
+	0xfc, 0x00, 0x4a, 0x11, 0xf4, 0x95, 0x71, 0x02, 
+	0x00, 0x12, 0x88, 0x11, 0xf6, 0xb8, 0x57, 0xf8, 
+	0x27, 0x72, 0xf0, 0x20, 0x7f, 0xff, 0xf2, 0x80, 
+	0xf0, 0x00, 0x80, 0x00, 0x80, 0x81, 0x57, 0xf8, 
+	0x27, 0x72, 0xe8, 0x01, 0xf3, 0xf1, 0xf2, 0x80, 
+	0x80, 0xf8, 0x27, 0x78, 0x77, 0x11, 0x80, 0x00, 
+	0x48, 0x11, 0x57, 0xf8, 0x27, 0x72, 0xf2, 0x80, 
+	0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x81, 
+	0x09, 0xb5, 0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08, 
+	0x00, 0x01, 0xf0, 0x73, 0x09, 0xba, 0xf0, 0x20, 
+	0x80, 0x01, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, 
+	0x45, 0xf8, 0x27, 0x71, 0x43, 0xf8, 0x27, 0x73, 
+	0x83, 0xf8, 0x00, 0x11, 0xf4, 0x95, 0xe7, 0x20, 
+	0xf6, 0xa9, 0xf8, 0x30, 0x09, 0xc9, 0xf2, 0x73, 
+	0x09, 0xe4, 0x77, 0x12, 0x00, 0x00, 0x57, 0xf8, 
+	0x27, 0x72, 0xf0, 0x20, 0x7f, 0xff, 0xf2, 0x80, 
+	0x49, 0x12, 0xf5, 0x00, 0xf3, 0x00, 0x80, 0x00, 
+	0x61, 0xf8, 0x00, 0x0b, 0x80, 0x00, 0xf8, 0x30, 
+	0x09, 0xdc, 0xf1, 0x20, 0x80, 0x00, 0xf5, 0x20, 
+	0x89, 0x12, 0xf4, 0x95, 0x48, 0x12, 0x6f, 0xf8, 
+	0x27, 0x73, 0x0d, 0x00, 0xf4, 0x95, 0x49, 0x0b, 
+	0x4f, 0xf8, 0x27, 0x72, 0x8a, 0x11, 0xfe, 0x00, 
+	0x48, 0x12, 0xf4, 0x95, 0x4a, 0x11, 0x4a, 0x16, 
+	0x4a, 0x17, 0xee, 0xfc, 0xf4, 0x95, 0x71, 0x08, 
+	0x00, 0x16, 0x88, 0x17, 0xf0, 0x74, 0x08, 0x30, 
+	0x48, 0x18, 0x70, 0x00, 0x00, 0x16, 0xf2, 0x74, 
+	0x09, 0x8f, 0xf0, 0x00, 0x00, 0x02, 0x88, 0x11, 
+	0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x81, 0x0a, 0x0a, 
+	0xf2, 0x74, 0x08, 0xdb, 0xf4, 0x95, 0x48, 0x16, 
+	0x48, 0x18, 0x70, 0x00, 0x00, 0x16, 0xf2, 0x74, 
+	0x09, 0x8f, 0xf0, 0x00, 0x00, 0x02, 0x88, 0x11, 
+	0x10, 0x02, 0x70, 0x01, 0x00, 0x11, 0x80, 0x00, 
+	0xf2, 0x74, 0x06, 0xce, 0xf4, 0x95, 0x48, 0x17, 
+	0x49, 0x11, 0x48, 0x17, 0xf6, 0x00, 0x88, 0x17, 
+	0xe7, 0x60, 0xf5, 0xa9, 0xf8, 0x20, 0x0a, 0x2d, 
+	0x48, 0x16, 0xf6, 0x20, 0x88, 0x11, 0x48, 0x18, 
+	0x70, 0x00, 0x00, 0x11, 0xf2, 0x74, 0x09, 0x8f, 
+	0xf0, 0x00, 0x00, 0x02, 0x88, 0x11, 0x70, 0x01, 
+	0x00, 0x11, 0x10, 0x02, 0x80, 0x00, 0xf2, 0x74, 
+	0x06, 0xce, 0xf4, 0x95, 0x48, 0x17, 0xee, 0x04, 
+	0x48, 0x16, 0x8a, 0x17, 0x8a, 0x16, 0x8a, 0x11, 
+	0xfc, 0x00, 0xee, 0xfd, 0xe8, 0x00, 0x4e, 0xf8, 
+	0x27, 0x70, 0xe8, 0x00, 0x4e, 0xf8, 0x27, 0x72, 
+	0xe8, 0x00, 0x4e, 0xf8, 0x27, 0x74, 0xe8, 0x00, 
+	0x4e, 0xf8, 0x27, 0x76, 0x76, 0xf8, 0x27, 0x79, 
+	0xff, 0xff, 0x76, 0xf8, 0x27, 0x7a, 0x00, 0x00, 
+	0x76, 0xf8, 0x27, 0x7b, 0xff, 0xff, 0x76, 0xf8, 
+	0x27, 0x78, 0x00, 0x00, 0xe8, 0x00, 0x75, 0xf8, 
+	0x00, 0x08, 0x00, 0x01, 0x76, 0x00, 0x00, 0x00, 
+	0x76, 0x01, 0x02, 0x00, 0xf2, 0x74, 0x12, 0xdc, 
+	0xf0, 0x20, 0x27, 0x7c, 0xee, 0x03, 0xfc, 0x00, 
+	0x4a, 0x11, 0xee, 0xfc, 0xf4, 0x95, 0x4e, 0x00, 
+	0x77, 0x12, 0x7f, 0xff, 0xf6, 0xb8, 0x49, 0x12, 
+	0xf1, 0x80, 0xf3, 0x00, 0x80, 0x00, 0x89, 0x12, 
+	0xf0, 0xe0, 0xf1, 0xf1, 0x4f, 0x02, 0xe9, 0x01, 
+	0xf4, 0x95, 0x48, 0x0b, 0xf5, 0x40, 0x56, 0x02, 
+	0xf1, 0x80, 0x81, 0xf8, 0x27, 0x78, 0x77, 0x11, 
+	0x80, 0x00, 0x56, 0x00, 0x49, 0x11, 0xf1, 0x80, 
+	0x89, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x81, 
+	0x0a, 0x81, 0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08, 
+	0x00, 0x01, 0xf0, 0x73, 0x0a, 0x86, 0xf0, 0x20, 
+	0x80, 0x01, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, 
+	0x10, 0x82, 0xee, 0x04, 0x8a, 0x11, 0xfc, 0x00, 
+	0x4a, 0x11, 0xee, 0xfe, 0xf4, 0x95, 0x4e, 0x00, 
+	0x77, 0x11, 0x7f, 0xff, 0xf6, 0xb8, 0x49, 0x11, 
+	0xf1, 0x80, 0xf3, 0x00, 0x80, 0x00, 0x89, 0x11, 
+	0xf0, 0xe0, 0xf1, 0xf1, 0xe8, 0x01, 0xf2, 0x80, 
+	0x80, 0xf8, 0x27, 0x78, 0x56, 0x00, 0xf1, 0x20, 
+	0x80, 0x00, 0xf1, 0x80, 0xf4, 0x95, 0x49, 0x0b, 
+	0xf8, 0x4d, 0x0a, 0xab, 0xf0, 0x20, 0x80, 0x01, 
+	0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, 0xf0, 0x73, 
+	0x0a, 0xaf, 0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08, 
+	0x00, 0x01, 0xee, 0x02, 0x48, 0x11, 0x8a, 0x11, 
+	0xfc, 0x00, 0x4a, 0x11, 0x88, 0x12, 0x13, 0x02, 
+	0x77, 0x11, 0x00, 0x00, 0xf8, 0x4d, 0x0a, 0xcb, 
+	0xf3, 0x10, 0x00, 0x01, 0x89, 0x1a, 0xf4, 0x95, 
+	0xf0, 0x72, 0x0a, 0xca, 0x48, 0x11, 0x1c, 0xf8, 
+	0x29, 0x7e, 0x88, 0x11, 0x11, 0xf8, 0x29, 0x7e, 
+	0xf2, 0x00, 0x00, 0x01, 0x80, 0xf8, 0x29, 0x7e, 
+	0x81, 0x92, 0x48, 0x11, 0x8a, 0x11, 0xfc, 0x00, 
+	0x4a, 0x11, 0xf4, 0x95, 0x71, 0x02, 0x00, 0x11, 
+	0x88, 0x12, 0xf6, 0xb8, 0xf0, 0x20, 0x7f, 0xff, 
+	0x57, 0xf8, 0x27, 0x70, 0xf2, 0x80, 0xf0, 0x00, 
+	0x80, 0x00, 0x80, 0x82, 0x57, 0xf8, 0x27, 0x70, 
+	0xe8, 0x01, 0xf3, 0xf1, 0xf2, 0x80, 0x80, 0xf8, 
+	0x27, 0x78, 0x77, 0x12, 0x80, 0x00, 0x48, 0x12, 
+	0x57, 0xf8, 0x27, 0x70, 0xf2, 0x80, 0x88, 0x12, 
+	0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x82, 0x0a, 0xf4, 
+	0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, 
+	0xf0, 0x73, 0x0a, 0xf9, 0xf0, 0x20, 0x80, 0x01, 
+	0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, 0x45, 0xf8, 
+	0x27, 0x75, 0xe7, 0x10, 0x43, 0xf8, 0x27, 0x71, 
+	0x83, 0xf8, 0x00, 0x12, 0x6d, 0xe8, 0x00, 0x04, 
+	0x6d, 0x8a, 0xf6, 0xaa, 0xf8, 0x30, 0x0b, 0x0a, 
+	0xf2, 0x73, 0x0b, 0x25, 0x77, 0x11, 0x00, 0x00, 
+	0x57, 0xf8, 0x27, 0x70, 0xf0, 0x20, 0x7f, 0xff, 
+	0xf2, 0x80, 0x49, 0x11, 0xf5, 0x00, 0xf3, 0x00, 
+	0x80, 0x00, 0x61, 0xf8, 0x00, 0x0b, 0x80, 0x00, 
+	0xf8, 0x30, 0x0b, 0x1d, 0xf1, 0x20, 0x80, 0x00, 
+	0xf5, 0x20, 0x89, 0x11, 0xf4, 0x95, 0x48, 0x11, 
+	0x6f, 0xf8, 0x27, 0x71, 0x0d, 0x00, 0xf4, 0x95, 
+	0x49, 0x0b, 0x4f, 0xf8, 0x27, 0x70, 0x48, 0x11, 
+	0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x4a, 0x16, 
+	0x4a, 0x17, 0xee, 0xf0, 0x88, 0x17, 0x10, 0x17, 
+	0x80, 0x05, 0x10, 0x16, 0x80, 0x06, 0x10, 0x15, 
+	0x80, 0x07, 0x71, 0x14, 0x00, 0x11, 0x10, 0x05, 
+	0xf0, 0x30, 0x00, 0x01, 0x88, 0x10, 0x10, 0x06, 
+	0xf0, 0x30, 0x00, 0x01, 0x80, 0x08, 0x49, 0x11, 
+	0x10, 0x05, 0xf6, 0x01, 0x80, 0x09, 0x10, 0x06, 
+	0x61, 0xf8, 0x00, 0x08, 0x00, 0x01, 0xf8, 0x20, 
+	0x0b, 0x4b, 0x10, 0x09, 0xf0, 0x00, 0x00, 0x01, 
+	0x80, 0x09, 0x71, 0x08, 0x00, 0x12, 0xf4, 0xaa, 
+	0xf8, 0x30, 0x0b, 0x54, 0x10, 0x09, 0xf0, 0x00, 
+	0x00, 0x01, 0x80, 0x09, 0x12, 0x09, 0x49, 0x11, 
+	0xf4, 0x7f, 0x80, 0x09, 0xf6, 0x20, 0x80, 0x0a, 
+	0x56, 0xf8, 0x27, 0x70, 0x4e, 0x0c, 0x10, 0x09, 
+	0x80, 0x00, 0x48, 0x18, 0xf2, 0x74, 0x0a, 0xce, 
+	0xf0, 0x00, 0x00, 0x04, 0x88, 0x16, 0xf4, 0x95, 
+	0xf4, 0x95, 0x6c, 0x86, 0x0b, 0x6d, 0xf2, 0x73, 
+	0x0c, 0x59, 0xf4, 0x95, 0xe8, 0x00, 0xf6, 0xb8, 
+	0xf4, 0x95, 0x56, 0x0c, 0xf0, 0xf9, 0x88, 0x12, 
+	0xf4, 0x95, 0xf4, 0x95, 0x70, 0xe2, 0x27, 0x7c, 
+	0x29, 0x86, 0xe8, 0x00, 0x80, 0x0e, 0x48, 0x11, 
+	0xf8, 0x45, 0x0b, 0xcc, 0x77, 0x10, 0x00, 0x01, 
+	0xf4, 0xa9, 0xf8, 0x30, 0x0b, 0x89, 0x6c, 0xe1, 
+	0xff, 0xfd, 0x0b, 0x8b, 0x10, 0xe7, 0x00, 0x02, 
+	0x80, 0x0e, 0xf0, 0x73, 0x0b, 0x8b, 0x10, 0x87, 
+	0x80, 0x0e, 0xe7, 0x10, 0xf5, 0xae, 0xf8, 0x20, 
+	0x0b, 0xb2, 0x70, 0x00, 0x00, 0x17, 0x70, 0x01, 
+	0x00, 0x16, 0x10, 0x04, 0xf0, 0x74, 0x06, 0xce, 
+	0x48, 0x17, 0x49, 0x16, 0xf6, 0x00, 0x88, 0x17, 
+	0x48, 0x11, 0xf6, 0x20, 0x88, 0x11, 0x10, 0x09, 
+	0xf6, 0x20, 0x80, 0x00, 0x48, 0x18, 0xf2, 0x74, 
+	0x0a, 0xce, 0xf0, 0x00, 0x00, 0x04, 0x88, 0x16, 
+	0x10, 0x04, 0x70, 0x00, 0x00, 0x17, 0x70, 0x01, 
+	0x00, 0x11, 0xf0, 0x74, 0x06, 0xce, 0x48, 0x11, 
+	0x00, 0x04, 0x80, 0x04, 0xf0, 0x73, 0x0b, 0xbc, 
+	0x70, 0x00, 0x00, 0x17, 0x70, 0x01, 0x00, 0x11, 
+	0x10, 0x04, 0xf0, 0x74, 0x06, 0xce, 0x48, 0x11, 
+	0x00, 0x04, 0x80, 0x04, 0x49, 0x11, 0x48, 0x16, 
+	0xf6, 0x20, 0x88, 0x16, 0xf4, 0x95, 0xf4, 0x95, 
+	0x6c, 0x86, 0x0b, 0xcc, 0x10, 0x0a, 0x80, 0x00, 
+	0x48, 0x18, 0xf2, 0x74, 0x0a, 0xce, 0xf0, 0x00, 
+	0x00, 0x04, 0x88, 0x16, 0x12, 0x0a, 0xf8, 0x45, 
+	0x0c, 0x33, 0x71, 0x0a, 0x00, 0x10, 0xf4, 0xae, 
+	0xf8, 0x30, 0x0c, 0x1c, 0x48, 0x16, 0xf0, 0xe1, 
+	0x88, 0x11, 0x12, 0x08, 0xf8, 0x45, 0x0b, 0xdb, 
+	0x6d, 0x89, 0x12, 0x07, 0xf8, 0x45, 0x0b, 0xe9, 
+	0x10, 0x07, 0x80, 0x00, 0x70, 0x02, 0x00, 0x11, 
+	0x10, 0x06, 0x80, 0x01, 0x10, 0x04, 0xf0, 0x74, 
+	0x06, 0xdc, 0xf0, 0x73, 0x0b, 0xef, 0x48, 0x11, 
+	0x6f, 0x00, 0x0c, 0x9f, 0x10, 0x04, 0xf0, 0x74, 
+	0x0a, 0xb3, 0x11, 0x0e, 0xf1, 0xc0, 0x81, 0x0e, 
+	0x10, 0x06, 0x49, 0x11, 0xf6, 0x00, 0x80, 0x06, 
+	0x10, 0x05, 0xf6, 0x20, 0x88, 0x11, 0xf0, 0x00, 
+	0x00, 0x01, 0x48, 0x08, 0x6f, 0x00, 0x0c, 0x9f, 
+	0x48, 0x18, 0xf2, 0x74, 0x0a, 0xce, 0xf0, 0x00, 
+	0x00, 0x04, 0x12, 0x07, 0xf8, 0x45, 0x0c, 0x11, 
+	0x10, 0x07, 0x80, 0x00, 0x70, 0x02, 0x00, 0x11, 
+	0x10, 0x06, 0x80, 0x01, 0x10, 0x04, 0xf0, 0x74, 
+	0x06, 0xdc, 0xf0, 0x73, 0x0c, 0x17, 0x48, 0x11, 
+	0x6f, 0x00, 0x0c, 0x9f, 0x10, 0x04, 0xf0, 0x74, 
+	0x0a, 0xb3, 0x11, 0x0e, 0xf1, 0xc0, 0x81, 0x0e, 
+	0xf0, 0x73, 0x0c, 0x33, 0x12, 0x07, 0xf8, 0x45, 
+	0x0c, 0x2a, 0x10, 0x07, 0x80, 0x00, 0x10, 0x06, 
+	0x80, 0x01, 0x10, 0x05, 0x80, 0x02, 0x10, 0x04, 
+	0xf0, 0x74, 0x06, 0xdc, 0xf0, 0x73, 0x0c, 0x30, 
+	0x12, 0x05, 0x6f, 0x00, 0x0c, 0x9f, 0x10, 0x04, 
+	0xf0, 0x74, 0x0a, 0xb3, 0x11, 0x0e, 0xf1, 0xc0, 
+	0x81, 0x0e, 0x76, 0x00, 0x00, 0x01, 0x48, 0x18, 
+	0xf2, 0x74, 0x0a, 0xce, 0xf0, 0x00, 0x00, 0x04, 
+	0x71, 0x04, 0x00, 0x11, 0x70, 0x81, 0x29, 0x86, 
+	0x10, 0x0e, 0x1c, 0xf8, 0x29, 0x86, 0x80, 0x0e, 
+	0x76, 0x00, 0x00, 0x01, 0x48, 0x18, 0xf2, 0x74, 
+	0x0a, 0xce, 0xf0, 0x00, 0x00, 0x04, 0x10, 0x0e, 
+	0x71, 0x04, 0x00, 0x11, 0x80, 0x81, 0x10, 0xf8, 
+	0x29, 0x86, 0xf0, 0x00, 0x00, 0x01, 0xf0, 0x30, 
+	0x7f, 0xff, 0x80, 0xf8, 0x29, 0x86, 0x10, 0x09, 
+	0xf0, 0x00, 0x00, 0x02, 0x80, 0x09, 0xee, 0x10, 
+	0x8a, 0x17, 0x8a, 0x16, 0x8a, 0x11, 0xfc, 0x00, 
+	0x10, 0xf8, 0x27, 0x75, 0x08, 0xf8, 0x27, 0x71, 
+	0xf0, 0x10, 0x00, 0x01, 0x48, 0x08, 0xfc, 0x00, 
+	0x4a, 0x11, 0x4a, 0x16, 0xee, 0xff, 0xf4, 0x95, 
+	0x71, 0x04, 0x00, 0x16, 0xf0, 0x00, 0x00, 0x01, 
+	0x48, 0x08, 0x4e, 0xf8, 0x29, 0x7c, 0x6d, 0xee, 
+	0xff, 0xfd, 0x48, 0x16, 0xf8, 0x45, 0x0c, 0x99, 
+	0x56, 0xf8, 0x29, 0x7c, 0xf0, 0x74, 0x0a, 0x5a, 
+	0x88, 0x11, 0x10, 0xf8, 0x29, 0x7d, 0xf0, 0x00, 
+	0x00, 0x01, 0x48, 0x08, 0x4e, 0xf8, 0x29, 0x7c, 
+	0x10, 0xf8, 0x29, 0x82, 0xf0, 0x00, 0x00, 0x01, 
+	0x88, 0x10, 0xf4, 0x95, 0xf4, 0x95, 0xf4, 0xa9, 
+	0xfa, 0x30, 0x0c, 0x96, 0x80, 0xf8, 0x29, 0x82, 
+	0x56, 0xf8, 0x29, 0x80, 0xf0, 0x00, 0x00, 0x01, 
+	0x4e, 0xf8, 0x29, 0x80, 0x73, 0x11, 0x29, 0x82, 
+	0x6c, 0xee, 0xff, 0xff, 0x0c, 0x76, 0xee, 0x01, 
+	0x8a, 0x16, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 
+	0x76, 0xf8, 0x29, 0x84, 0x00, 0x00, 0x76, 0xf8, 
+	0x29, 0x85, 0x00, 0x01, 0xe8, 0x00, 0x4e, 0xf8, 
+	0x2a, 0x0c, 0x76, 0xf8, 0x29, 0x86, 0x00, 0x00, 
+	0x76, 0xf8, 0x29, 0x87, 0x00, 0x00, 0x77, 0x11, 
+	0x29, 0x88, 0x76, 0x81, 0xaa, 0xaa, 0x76, 0xe1, 
+	0x00, 0x01, 0xaa, 0xaa, 0x76, 0xe1, 0x00, 0x02, 
+	0x00, 0x00, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 
+	0xee, 0xfc, 0xf4, 0x95, 0x71, 0x06, 0x00, 0x14, 
+	0x71, 0x07, 0x00, 0x13, 0x71, 0x08, 0x00, 0x12, 
+	0x71, 0x09, 0x00, 0x15, 0x77, 0x10, 0x00, 0xff, 
+	0xf4, 0xaa, 0xf8, 0x30, 0x0d, 0x44, 0x49, 0x13, 
+	0x53, 0xf8, 0x2a, 0x0c, 0x4f, 0xf8, 0x2a, 0x0c, 
+	0x73, 0x12, 0x00, 0x0e, 0xf1, 0x66, 0x00, 0x0d, 
+	0x89, 0x11, 0xf4, 0x95, 0x77, 0x10, 0x00, 0x01, 
+	0x71, 0xe1, 0x24, 0x00, 0x00, 0x11, 0xf4, 0xa9, 
+	0xf8, 0x30, 0x0d, 0x17, 0x77, 0x10, 0x00, 0x02, 
+	0xf4, 0xa9, 0xf8, 0x30, 0x0c, 0xec, 0x77, 0x11, 
+	0x29, 0x8a, 0x76, 0x81, 0x00, 0x00, 0xe8, 0x00, 
+	0x77, 0x14, 0x00, 0x00, 0x77, 0x13, 0x00, 0x00, 
+	0xf0, 0x73, 0x0d, 0x48, 0x6c, 0x83, 0x0c, 0xfa, 
+	0x77, 0x11, 0x29, 0x8a, 0x48, 0x12, 0xf0, 0xe8, 
+	0xf0, 0x40, 0x80, 0x00, 0x80, 0x81, 0xe8, 0x00, 
+	0x77, 0x14, 0x00, 0x00, 0xf0, 0x73, 0x0d, 0x48, 
+	0x49, 0x13, 0xf3, 0x40, 0x80, 0x00, 0x81, 0xf8, 
+	0x29, 0x8a, 0x61, 0xf8, 0x00, 0x15, 0x00, 0x01, 
+	0xf8, 0x20, 0x0d, 0x07, 0x69, 0xf8, 0x29, 0x8a, 
+	0x40, 0x00, 0x61, 0xf8, 0x00, 0x14, 0x00, 0x01, 
+	0xf8, 0x20, 0x0d, 0x0f, 0x69, 0xf8, 0x29, 0x8a, 
+	0x20, 0x00, 0x77, 0x11, 0x29, 0x8a, 0x49, 0x12, 
+	0xf3, 0xe8, 0x1b, 0x81, 0x81, 0x81, 0xf0, 0x73, 
+	0x0d, 0x48, 0x11, 0xf8, 0x29, 0x84, 0xf8, 0x4c, 
+	0x0d, 0x37, 0x77, 0x11, 0x29, 0x88, 0x76, 0x81, 
+	0xaa, 0xaa, 0x11, 0xf8, 0x29, 0x85, 0xf3, 0x10, 
+	0x00, 0x01, 0xf3, 0x40, 0xaa, 0x00, 0x81, 0xe1, 
+	0x00, 0x01, 0x76, 0x00, 0x00, 0x02, 0x80, 0x01, 
+	0x70, 0x02, 0x00, 0x14, 0x70, 0x03, 0x00, 0x13, 
+	0xf2, 0x74, 0x0b, 0x28, 0xf4, 0x95, 0x48, 0x11, 
+	0x71, 0xf8, 0x29, 0x85, 0x29, 0x84, 0xf0, 0x73, 
+	0x0d, 0x73, 0x76, 0x00, 0x00, 0x00, 0x80, 0x01, 
+	0x76, 0x02, 0x00, 0x00, 0x70, 0x03, 0x00, 0x13, 
+	0xf2, 0x74, 0x0b, 0x28, 0xf4, 0x95, 0xe8, 0x00, 
+	0xf0, 0x73, 0x0d, 0x73, 0x77, 0x11, 0x29, 0x8a, 
+	0x70, 0x81, 0x00, 0x13, 0x11, 0xf8, 0x29, 0x84, 
+	0xf8, 0x4c, 0x0d, 0x68, 0x77, 0x11, 0x29, 0x88, 
+	0x76, 0x81, 0xaa, 0xaa, 0x11, 0xf8, 0x29, 0x85, 
+	0xf3, 0x10, 0x00, 0x01, 0xf3, 0x40, 0xaa, 0x00, 
+	0x81, 0xe1, 0x00, 0x01, 0x76, 0x00, 0x00, 0x03, 
+	0x80, 0x01, 0x70, 0x02, 0x00, 0x14, 0x70, 0x03, 
+	0x00, 0x13, 0xf2, 0x74, 0x0b, 0x28, 0xf4, 0x95, 
+	0x48, 0x11, 0x71, 0xf8, 0x29, 0x85, 0x29, 0x84, 
+	0xf0, 0x73, 0x0d, 0x73, 0x76, 0x00, 0x00, 0x01, 
+	0x80, 0x01, 0x70, 0x02, 0x00, 0x14, 0x70, 0x03, 
+	0x00, 0x13, 0xf2, 0x74, 0x0b, 0x28, 0xf4, 0x95, 
+	0x48, 0x11, 0x6b, 0xf8, 0x29, 0x84, 0xff, 0xff, 
+	0xee, 0x04, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 
+	0xf5, 0x40, 0xf4, 0x95, 0x48, 0x0b, 0xf4, 0x78, 
+	0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0xe1, 
+	0xff, 0xb9, 0x0d, 0x88, 0xf2, 0x73, 0x0d, 0xa5, 
+	0xf4, 0x95, 0xe8, 0x60, 0xf2, 0x00, 0x00, 0x06, 
+	0x61, 0xf8, 0x00, 0x11, 0x00, 0x20, 0xf8, 0x30, 
+	0x0d, 0x98, 0x61, 0xf8, 0x00, 0x0b, 0x00, 0x01, 
+	0xf8, 0x20, 0x0d, 0xa3, 0xf2, 0x00, 0x00, 0x07, 
+	0xf0, 0x73, 0x0d, 0xa3, 0x61, 0xf8, 0x00, 0x0b, 
+	0x00, 0x01, 0xf8, 0x20, 0x0d, 0xa1, 0xf2, 0x73, 
+	0x0d, 0xa3, 0xf0, 0x00, 0x00, 0x01, 0xf0, 0x00, 
+	0x00, 0x02, 0x48, 0x08, 0xf4, 0x7f, 0x8a, 0x11, 
+	0xfc, 0x00, 0xee, 0xff, 0xf0, 0x74, 0x07, 0xfd, 
+	0xf0, 0x74, 0x07, 0x44, 0xf0, 0x74, 0x0d, 0xb4, 
+	0xf0, 0x74, 0x02, 0x05, 0xf0, 0x74, 0x04, 0x60, 
+	0xf0, 0x73, 0x0d, 0xaa, 0xee, 0xfd, 0x10, 0xf8, 
+	0x2a, 0xa3, 0xf8, 0x44, 0x0d, 0xcb, 0x10, 0xf8, 
+	0x2a, 0xa4, 0xf8, 0x45, 0x0d, 0xd7, 0x76, 0x00, 
+	0x02, 0x00, 0xf2, 0x74, 0x09, 0xe8, 0xf0, 0x20, 
+	0x22, 0x00, 0x76, 0xf8, 0x2a, 0xa4, 0x00, 0x00, 
+	0x76, 0xf8, 0x2a, 0xa7, 0x00, 0x00, 0xf0, 0x73, 
+	0x0d, 0xd7, 0x76, 0x00, 0x02, 0x00, 0xf2, 0x74, 
+	0x09, 0xe8, 0xf0, 0x20, 0x20, 0x00, 0x76, 0xf8, 
+	0x2a, 0xa3, 0x00, 0x00, 0x76, 0xf8, 0x2a, 0xa7, 
+	0x00, 0x01, 0xf0, 0x74, 0x0c, 0x5e, 0xf0, 0xe0, 
+	0xf0, 0x10, 0x3a, 0x98, 0xf8, 0x47, 0x0d, 0xe1, 
+	0x76, 0xf8, 0x27, 0x6e, 0x00, 0x00, 0xee, 0x03, 
+	0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe, 0x77, 0x11, 
+	0x20, 0x00, 0x76, 0x00, 0xaa, 0xaa, 0x76, 0x01, 
+	0x02, 0x00, 0xf2, 0x74, 0x06, 0x6c, 0xf4, 0x95, 
+	0x48, 0x11, 0x76, 0x00, 0x55, 0x55, 0x76, 0x01, 
+	0x02, 0x00, 0x48, 0x11, 0xf2, 0x74, 0x06, 0x6c, 
+	0xf0, 0x00, 0x02, 0x00, 0x76, 0xf8, 0x2a, 0xa3, 
+	0x00, 0x00, 0x76, 0xf8, 0x2a, 0xa4, 0x00, 0x00, 
+	0xe8, 0x00, 0x4e, 0x00, 0xfb, 0x80, 0x15, 0x3e, 
+	0xf4, 0x95, 0xe8, 0x04, 0x80, 0xf8, 0x2a, 0xa5, 
+	0x76, 0x00, 0x2a, 0xa8, 0xf9, 0x80, 0x14, 0x87, 
+	0x76, 0x00, 0x2a, 0xad, 0xfb, 0x80, 0x13, 0x62, 
+	0xf4, 0x95, 0xe8, 0x02, 0x10, 0xf8, 0x2a, 0xa5, 
+	0xf9, 0x80, 0x14, 0x63, 0xfb, 0x80, 0x16, 0x66, 
+	0xf4, 0x95, 0xe8, 0x1c, 0xfb, 0x80, 0x16, 0x87, 
+	0xf4, 0x95, 0xe8, 0x1c, 0xe8, 0x01, 0x4e, 0x00, 
+	0xfb, 0x80, 0x17, 0xd6, 0xf4, 0x95, 0xe8, 0x00, 
+	0x80, 0xf8, 0x2a, 0xa6, 0x76, 0x00, 0x2a, 0xb7, 
+	0xf9, 0x80, 0x16, 0xaa, 0x10, 0xf8, 0x2a, 0xa6, 
+	0xf9, 0x80, 0x17, 0x5c, 0x10, 0xf8, 0x2a, 0xa6, 
+	0xf9, 0x80, 0x17, 0x6f, 0xee, 0x02, 0x8a, 0x11, 
+	0xfc, 0x00, 0xf4, 0x95, 0x4a, 0x08, 0x4a, 0x09, 
+	0x4a, 0x0a, 0x4a, 0x07, 0x4a, 0x1d, 0x68, 0xf8, 
+	0x00, 0x07, 0x7d, 0x3f, 0x69, 0xf8, 0x00, 0x07, 
+	0x40, 0x00, 0x68, 0xf8, 0x00, 0x1d, 0xff, 0xfc, 
+	0x10, 0xf8, 0x2a, 0xa7, 0xf8, 0x44, 0x0e, 0x4b, 
+	0x76, 0xf8, 0x2a, 0xa3, 0x00, 0x01, 0xf0, 0x73, 
+	0x0e, 0x4e, 0x76, 0xf8, 0x2a, 0xa4, 0x00, 0x01, 
+	0x8a, 0x1d, 0x8a, 0x07, 0x8a, 0x0a, 0x8a, 0x09, 
+	0x8a, 0x08, 0xf4, 0xeb, 0x4a, 0x11, 0x4a, 0x16, 
+	0x4a, 0x17, 0xee, 0xfe, 0x88, 0x0e, 0x71, 0x08, 
+	0x00, 0x16, 0x71, 0x06, 0x00, 0x17, 0x11, 0x07, 
+	0xf0, 0x66, 0x00, 0x0d, 0xf0, 0x00, 0x25, 0xa0, 
+	0x88, 0x11, 0x76, 0x01, 0x00, 0x06, 0x81, 0x00, 
+	0xf2, 0x74, 0x06, 0xce, 0xf0, 0x00, 0x00, 0x01, 
+	0x76, 0x01, 0x00, 0x06, 0x70, 0x00, 0x00, 0x16, 
+	0x48, 0x11, 0xf2, 0x74, 0x06, 0xce, 0xf0, 0x00, 
+	0x00, 0x07, 0x70, 0x81, 0x00, 0x17, 0xee, 0x02, 
+	0x8a, 0x17, 0x8a, 0x16, 0x8a, 0x11, 0xfc, 0x00, 
+	0x4a, 0x11, 0x88, 0x0e, 0x71, 0x02, 0x00, 0x12, 
+	0x11, 0x03, 0xf0, 0x66, 0x00, 0x0d, 0xf0, 0x00, 
+	0x24, 0x00, 0x88, 0x11, 0xf4, 0x95, 0x70, 0x81, 
+	0x00, 0x12, 0x6e, 0xe2, 0xff, 0xfe, 0x0e, 0x8d, 
+	0xf4, 0x95, 0xe8, 0x00, 0xe8, 0x01, 0x80, 0xe1, 
+	0x00, 0x02, 0x76, 0xe1, 0x00, 0x03, 0x00, 0xff, 
+	0x76, 0xe1, 0x00, 0x04, 0x00, 0x00, 0x76, 0xe1, 
+	0x00, 0x0b, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x0c, 
+	0x00, 0x00, 0x81, 0xe1, 0x00, 0x01, 0x8a, 0x11, 
+	0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfc, 0x88, 0x0e, 
+	0xf4, 0x95, 0xf1, 0x66, 0x00, 0x0d, 0xf3, 0x00, 
+	0x24, 0x00, 0x89, 0x11, 0xf4, 0x95, 0xf4, 0x95, 
+	0x76, 0xe1, 0x00, 0x0c, 0x00, 0x00, 0x76, 0xe1, 
+	0x00, 0x0b, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x02, 
+	0x00, 0x01, 0x76, 0x00, 0x00, 0x00, 0x76, 0x01, 
+	0x00, 0x00, 0x80, 0x02, 0x76, 0x03, 0x00, 0x00, 
+	0xf2, 0x74, 0x0c, 0xb9, 0xf4, 0x95, 0xe8, 0x00, 
+	0xee, 0x04, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 
+	0x88, 0x19, 0xf4, 0x95, 0x73, 0x19, 0x00, 0x0e, 
+	0xf1, 0x66, 0x00, 0x0d, 0xf2, 0x00, 0x24, 0x00, 
+	0x77, 0x15, 0x25, 0xa0, 0x77, 0x14, 0x00, 0x00, 
+	0x77, 0x1a, 0x00, 0x1f, 0xf0, 0x72, 0x0f, 0x14, 
+	0xf6, 0xb8, 0x49, 0x19, 0x09, 0x85, 0xf8, 0x4c, 
+	0x0f, 0x13, 0xf1, 0x00, 0x00, 0x05, 0x89, 0x11, 
+	0x49, 0x15, 0xf3, 0x00, 0x00, 0x01, 0x89, 0x13, 
+	0x49, 0x15, 0xf3, 0x00, 0x00, 0x07, 0x89, 0x12, 
+	0x11, 0x93, 0x1d, 0x91, 0x19, 0x92, 0x89, 0x10, 
+	0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x80, 0x0f, 0x13, 
+	0x11, 0x93, 0x1d, 0x91, 0x19, 0x92, 0x89, 0x10, 
+	0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x80, 0x0f, 0x13, 
+	0x11, 0x93, 0x1d, 0x91, 0x19, 0x92, 0x89, 0x10, 
+	0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x80, 0x0f, 0x13, 
+	0x11, 0x93, 0x1d, 0x91, 0x19, 0x92, 0x89, 0x10, 
+	0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x80, 0x0f, 0x13, 
+	0x11, 0x93, 0x1d, 0x91, 0x19, 0x92, 0x89, 0x10, 
+	0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x80, 0x0f, 0x13, 
+	0x11, 0x93, 0x1d, 0x91, 0x19, 0x92, 0x89, 0x11, 
+	0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x81, 0x0f, 0x13, 
+	0x6d, 0x94, 0x6d, 0xed, 0x00, 0x0d, 0x48, 0x14, 
+	0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x4a, 0x16, 
+	0x4a, 0x17, 0xee, 0xf8, 0x88, 0x17, 0x10, 0x0d, 
+	0x80, 0x04, 0x10, 0x0c, 0x80, 0x05, 0x71, 0x0e, 
+	0x00, 0x16, 0x73, 0x17, 0x00, 0x0e, 0xf0, 0x66, 
+	0x00, 0x0d, 0xf0, 0x00, 0x24, 0x00, 0x88, 0x11, 
+	0x10, 0xf8, 0x27, 0x63, 0xf8, 0x45, 0x0f, 0x32, 
+	0xf2, 0x74, 0x0e, 0x9f, 0xf4, 0x95, 0x48, 0x17, 
+	0x10, 0xf8, 0x27, 0x60, 0xf8, 0x44, 0x0f, 0x3d, 
+	0x60, 0xe1, 0x00, 0x02, 0x00, 0x01, 0xf8, 0x20, 
+	0x0f, 0x6d, 0xf0, 0x73, 0x11, 0x33, 0x10, 0x04, 
+	0x80, 0x00, 0x10, 0x05, 0xf0, 0x74, 0x06, 0x9f, 
+	0x11, 0x04, 0xf3, 0x00, 0x00, 0x01, 0x81, 0x04, 
+	0x6d, 0x8e, 0x77, 0x10, 0x00, 0x01, 0x71, 0xe1, 
+	0x00, 0x02, 0x00, 0x12, 0xf4, 0xaa, 0xf8, 0x30, 
+	0x0f, 0x62, 0x77, 0x10, 0x00, 0x02, 0xf4, 0xaa, 
+	0xf8, 0x30, 0x0f, 0x6d, 0x45, 0xe1, 0x00, 0x0b, 
+	0x88, 0x10, 0x43, 0xe1, 0x00, 0x0c, 0x83, 0xf8, 
+	0x00, 0x12, 0xf4, 0x95, 0xf4, 0x95, 0xf4, 0xaa, 
+	0xf8, 0x30, 0x0f, 0x6d, 0xf0, 0x73, 0x0f, 0x96, 
+	0xf5, 0x00, 0x81, 0x04, 0x49, 0x16, 0xf5, 0x20, 
+	0x89, 0x16, 0x76, 0xe1, 0x00, 0x0c, 0x00, 0x00, 
+	0x76, 0xe1, 0x00, 0x04, 0x00, 0x00, 0x48, 0x16, 
+	0xf8, 0x45, 0x11, 0x33, 0xf7, 0xb8, 0x71, 0xe1, 
+	0x00, 0x02, 0x00, 0x12, 0x10, 0xf8, 0x00, 0x12, 
+	0xf0, 0x10, 0x00, 0x03, 0xf8, 0x46, 0x0f, 0x8c, 
+	0x10, 0xf8, 0x00, 0x12, 0xf0, 0x10, 0x00, 0x03, 
+	0xf8, 0x45, 0x10, 0x16, 0x77, 0x10, 0x00, 0x01, 
+	0xf4, 0xaa, 0xf8, 0x30, 0x0f, 0x9c, 0x77, 0x10, 
+	0x00, 0x02, 0xf4, 0xaa, 0xf8, 0x30, 0x0f, 0xa8, 
+	0xf0, 0x73, 0x0f, 0x96, 0x77, 0x10, 0x00, 0x04, 
+	0xf4, 0xaa, 0xf8, 0x30, 0x10, 0xb7, 0x77, 0x10, 
+	0x00, 0x05, 0xf4, 0xaa, 0xf8, 0x30, 0x10, 0xbc, 
+	0xf2, 0x74, 0x0e, 0x9f, 0xf4, 0x95, 0x48, 0x17, 
+	0xf0, 0x73, 0x11, 0x31, 0x76, 0xe1, 0x00, 0x0c, 
+	0x00, 0x00, 0x76, 0xe1, 0x00, 0x0b, 0x00, 0x00, 
+	0x76, 0xe1, 0x00, 0x04, 0x00, 0x00, 0x76, 0xe1, 
+	0x00, 0x02, 0x00, 0x02, 0x11, 0xe1, 0x00, 0x0c, 
+	0xe8, 0x03, 0xf6, 0x20, 0x89, 0x12, 0xf4, 0x95, 
+	0x77, 0x10, 0x00, 0x03, 0xf5, 0xaa, 0xf8, 0x30, 
+	0x0f, 0xb6, 0x6b, 0xf8, 0x27, 0x6f, 0x00, 0x01, 
+	0x88, 0x10, 0xf4, 0x95, 0xf4, 0x95, 0xf5, 0xae, 
+	0xf8, 0x20, 0x0f, 0xbd, 0x48, 0x16, 0x80, 0x06, 
+	0x88, 0x13, 0xf4, 0x95, 0x77, 0x10, 0x00, 0x03, 
+	0xf6, 0xab, 0xf8, 0x20, 0x0f, 0xc8, 0x6b, 0xf8, 
+	0x27, 0x6f, 0x00, 0x01, 0x12, 0x06, 0xf8, 0x45, 
+	0x10, 0x00, 0x10, 0xe1, 0x00, 0x04, 0x80, 0x00, 
+	0x10, 0x05, 0x80, 0x01, 0x10, 0x04, 0x80, 0x02, 
+	0x10, 0x06, 0x80, 0x03, 0x48, 0x11, 0xf2, 0x74, 
+	0x07, 0x1e, 0xf0, 0x00, 0x00, 0x05, 0x10, 0x06, 
+	0x00, 0xe1, 0x00, 0x04, 0x80, 0xe1, 0x00, 0x04, 
+	0x10, 0x06, 0x00, 0xe1, 0x00, 0x0c, 0x80, 0xe1, 
+	0x00, 0x0c, 0x88, 0x12, 0x11, 0x06, 0x10, 0x04, 
+	0xf6, 0x00, 0x80, 0x04, 0x48, 0x16, 0xf6, 0x20, 
+	0x88, 0x16, 0x89, 0x13, 0xf4, 0x95, 0x77, 0x10, 
+	0x00, 0x03, 0xf6, 0xab, 0xf8, 0x20, 0x0f, 0xf5, 
+	0x6b, 0xf8, 0x27, 0x6f, 0x00, 0x01, 0x77, 0x10, 
+	0x00, 0x0c, 0x71, 0xe1, 0x00, 0x04, 0x00, 0x13, 
+	0xf6, 0xab, 0xf8, 0x20, 0x10, 0x00, 0x6b, 0xf8, 
+	0x27, 0x6f, 0x00, 0x01, 0x6c, 0xe2, 0xff, 0xfd, 
+	0x11, 0x31, 0xf6, 0xb8, 0x6f, 0xe1, 0x00, 0x05, 
+	0x0c, 0x48, 0x6f, 0xe1, 0x00, 0x06, 0x0c, 0x18, 
+	0xf0, 0x30, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x03, 
+	0x80, 0xe1, 0x00, 0x0b, 0x76, 0xe1, 0x00, 0x02, 
+	0x00, 0x03, 0x48, 0x16, 0xf8, 0x45, 0x11, 0x33, 
+	0x71, 0xe1, 0x00, 0x0c, 0x00, 0x12, 0x10, 0xe1, 
+	0x00, 0x0b, 0x49, 0x12, 0xf6, 0x20, 0x88, 0x13, 
+	0xe8, 0x0c, 0xf6, 0x20, 0x88, 0x10, 0xf4, 0x95, 
+	0xf4, 0x95, 0xf5, 0xab, 0xf8, 0x20, 0x10, 0x27, 
+	0x48, 0x13, 0x80, 0x06, 0x88, 0x10, 0xf4, 0x95, 
+	0xf4, 0x95, 0xf5, 0xae, 0xf8, 0x20, 0x10, 0x30, 
+	0x70, 0x06, 0x00, 0x16, 0x12, 0x06, 0xf8, 0x45, 
+	0x10, 0x5f, 0x10, 0xe1, 0x00, 0x04, 0x80, 0x00, 
+	0x10, 0x05, 0x80, 0x01, 0x10, 0x04, 0x80, 0x02, 
+	0x10, 0x06, 0x80, 0x03, 0x48, 0x11, 0xf2, 0x74, 
+	0x07, 0x1e, 0xf0, 0x00, 0x00, 0x05, 0x10, 0x06, 
+	0x00, 0xe1, 0x00, 0x04, 0x80, 0xe1, 0x00, 0x04, 
+	0x10, 0x06, 0x00, 0xe1, 0x00, 0x0c, 0x80, 0xe1, 
+	0x00, 0x0c, 0x88, 0x12, 0x11, 0x06, 0x10, 0x04, 
+	0xf6, 0x00, 0x80, 0x04, 0x48, 0x16, 0xf6, 0x20, 
+	0x88, 0x16, 0xf4, 0x95, 0x77, 0x10, 0x00, 0x0c, 
+	0x71, 0xe1, 0x00, 0x04, 0x00, 0x13, 0xf6, 0xab, 
+	0xf8, 0x20, 0x10, 0x5f, 0x6b, 0xf8, 0x27, 0x6f, 
+	0x00, 0x01, 0x77, 0x10, 0x00, 0x0c, 0xf6, 0xaa, 
+	0xf8, 0x20, 0x10, 0x6b, 0xf2, 0x74, 0x0e, 0x9f, 
+	0xf4, 0x95, 0x48, 0x17, 0x71, 0xe1, 0x00, 0x0c, 
+	0x00, 0x12, 0x77, 0x10, 0x00, 0x0c, 0xf4, 0xaa, 
+	0xf8, 0x30, 0x10, 0x7c, 0x77, 0x10, 0x00, 0x0c, 
+	0x71, 0xe1, 0x00, 0x0b, 0x00, 0x13, 0xf6, 0xab, 
+	0xf8, 0x30, 0x10, 0xb4, 0xe7, 0x30, 0xf7, 0xaa, 
+	0xf8, 0x30, 0x10, 0xb4, 0xf2, 0x74, 0x0e, 0xc1, 
+	0xf4, 0x95, 0x48, 0x17, 0x88, 0x12, 0xf4, 0x95, 
+	0xf4, 0x95, 0x6c, 0x82, 0x10, 0x8d, 0x76, 0xe1, 
+	0x00, 0x04, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x02, 
+	0x00, 0x05, 0xf0, 0x73, 0x10, 0xb4, 0x76, 0xe1, 
+	0x00, 0x02, 0x00, 0x04, 0x77, 0x10, 0x00, 0x0c, 
+	0x71, 0xe1, 0x00, 0x0b, 0x00, 0x12, 0xf5, 0xaa, 
+	0xf8, 0x20, 0x10, 0x9a, 0xf0, 0x73, 0x10, 0x9c, 
+	0x77, 0x12, 0x00, 0x0c, 0x76, 0x00, 0x00, 0x00, 
+	0x70, 0x01, 0x00, 0x12, 0x70, 0x02, 0x00, 0x17, 
+	0x76, 0x03, 0x00, 0x01, 0x48, 0x11, 0xf2, 0x74, 
+	0x0c, 0xb9, 0xf0, 0x00, 0x00, 0x05, 0x76, 0xe1, 
+	0x00, 0x04, 0x00, 0x00, 0x77, 0x10, 0x00, 0x0c, 
+	0x71, 0xe1, 0x00, 0x0b, 0x00, 0x12, 0xf6, 0xaa, 
+	0xf8, 0x20, 0x11, 0x1c, 0x48, 0x16, 0xf8, 0x45, 
+	0x11, 0x33, 0x60, 0xe1, 0x00, 0x02, 0x00, 0x05, 
+	0xf8, 0x20, 0x10, 0xdf, 0x10, 0xe1, 0x00, 0x0b, 
+	0x08, 0xe1, 0x00, 0x0c, 0x11, 0xe1, 0x00, 0x04, 
+	0xf8, 0x4d, 0x10, 0xc7, 0x6b, 0xf8, 0x27, 0x6f, 
+	0x00, 0x01, 0x88, 0x10, 0xf4, 0x95, 0xf4, 0x95, 
+	0xf5, 0xae, 0xf8, 0x20, 0x10, 0xcf, 0x48, 0x16, 
+	0xf4, 0x95, 0x48, 0x08, 0xf8, 0x45, 0x11, 0x16, 
+	0x6f, 0xe1, 0x00, 0x0c, 0x0d, 0x00, 0x81, 0xe1, 
+	0x00, 0x0c, 0x11, 0x04, 0xf5, 0x00, 0x81, 0x04, 
+	0x49, 0x16, 0xf5, 0x20, 0x89, 0x16, 0xf0, 0x73, 
+	0x11, 0x0e, 0x10, 0xe1, 0x00, 0x0b, 0x71, 0xe1, 
+	0x00, 0x0c, 0x00, 0x12, 0x88, 0x10, 0xf4, 0x95, 
+	0xf4, 0x95, 0xf6, 0xaa, 0xf8, 0x30, 0x11, 0x16, 
+	0x49, 0x12, 0xf6, 0x20, 0x88, 0x10, 0xf4, 0x95, 
+	0xf4, 0x95, 0xf5, 0xae, 0xf8, 0x20, 0x10, 0xf3, 
+	0x48, 0x16, 0x80, 0x06, 0x48, 0x08, 0xf8, 0x45, 
+	0x11, 0x16, 0x10, 0x04, 0x70, 0x02, 0x00, 0x17, 
+	0x80, 0x00, 0x76, 0x03, 0x00, 0x00, 0x10, 0x06, 
+	0x80, 0x01, 0x10, 0x05, 0xf0, 0x74, 0x0c, 0xb9, 
+	0x10, 0x06, 0x00, 0xe1, 0x00, 0x0c, 0x80, 0xe1, 
+	0x00, 0x0c, 0x11, 0x06, 0x10, 0x04, 0xf6, 0x00, 
+	0x80, 0x04, 0x48, 0x16, 0xf6, 0x20, 0x88, 0x16, 
+	0x10, 0xe1, 0x00, 0x0c, 0x08, 0xe1, 0x00, 0x0b, 
+	0xf8, 0x45, 0x11, 0x1c, 0xf0, 0x73, 0x11, 0x31, 
+	0xf2, 0x74, 0x0e, 0x9f, 0xf4, 0x95, 0x48, 0x17, 
+	0xf0, 0x73, 0x11, 0x33, 0x76, 0xe1, 0x00, 0x0c, 
+	0x00, 0x00, 0x76, 0xe1, 0x00, 0x0b, 0x00, 0x00, 
+	0x76, 0xe1, 0x00, 0x02, 0x00, 0x01, 0x10, 0x04, 
+	0x80, 0x00, 0x10, 0x05, 0xf0, 0x74, 0x06, 0x9f, 
+	0x88, 0x12, 0xf4, 0x95, 0x77, 0x10, 0x00, 0xff, 
+	0xf4, 0xaa, 0xf8, 0x30, 0x11, 0x33, 0x6c, 0x86, 
+	0x0f, 0x70, 0xee, 0x08, 0x8a, 0x17, 0x8a, 0x16, 
+	0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfc, 
+	0xf4, 0x95, 0x71, 0x06, 0x00, 0x12, 0x88, 0x11, 
+	0x73, 0x12, 0x00, 0x0e, 0xf1, 0x66, 0x00, 0x0d, 
+	0xf3, 0x00, 0x24, 0x00, 0x89, 0x14, 0x13, 0x81, 
+	0xf7, 0x7a, 0xf3, 0x30, 0x00, 0x01, 0x81, 0xf8, 
+	0x27, 0x60, 0x13, 0xe1, 0x00, 0x01, 0xf7, 0x7c, 
+	0xf3, 0x30, 0x00, 0x03, 0x81, 0xf8, 0x27, 0x61, 
+	0xe9, 0x0f, 0x19, 0xe1, 0x00, 0x01, 0x81, 0xf8, 
+	0x27, 0x62, 0x71, 0xe4, 0x00, 0x03, 0x00, 0x13, 
+	0xf6, 0xb8, 0x49, 0x13, 0xf3, 0x00, 0x00, 0x01, 
+	0xf3, 0x30, 0x00, 0x0f, 0x49, 0x0b, 0x09, 0xf8, 
+	0x27, 0x62, 0xf8, 0x4d, 0x11, 0x75, 0x77, 0x10, 
+	0x00, 0xff, 0xf4, 0xab, 0xf8, 0x30, 0x11, 0x75, 
+	0x57, 0xf8, 0x27, 0x6c, 0xf3, 0x00, 0x00, 0x01, 
+	0x4f, 0xf8, 0x27, 0x6c, 0x76, 0xf8, 0x27, 0x63, 
+	0x00, 0x01, 0xf0, 0x73, 0x11, 0x78, 0x76, 0xf8, 
+	0x27, 0x63, 0x00, 0x00, 0x70, 0xe4, 0x00, 0x03, 
+	0x27, 0x62, 0x76, 0xf8, 0x27, 0x64, 0x00, 0x00, 
+	0x11, 0xf8, 0x27, 0x61, 0x61, 0xf8, 0x00, 0x0b, 
+	0x00, 0x02, 0xf8, 0x20, 0x11, 0x8d, 0xe9, 0x01, 
+	0x6f, 0xe1, 0x00, 0x02, 0x0f, 0x18, 0x81, 0xf8, 
+	0x27, 0x64, 0x11, 0xf8, 0x27, 0x61, 0x61, 0xf8, 
+	0x00, 0x0b, 0x00, 0x01, 0xf8, 0x20, 0x11, 0xa9, 
+	0x10, 0xf8, 0x27, 0x64, 0xf1, 0x00, 0x00, 0x04, 
+	0x89, 0x13, 0xe9, 0xb8, 0xf5, 0x20, 0x81, 0xf8, 
+	0x27, 0x65, 0x60, 0x84, 0x00, 0x02, 0xf8, 0x20, 
+	0x11, 0xa9, 0x70, 0x00, 0x00, 0x11, 0x70, 0x01, 
+	0x00, 0x13, 0x70, 0x02, 0x27, 0x65, 0xf2, 0x74, 
+	0x0f, 0x18, 0xf4, 0x95, 0x48, 0x12, 0xee, 0x04, 
+	0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x4a, 0x16, 
+	0x4a, 0x17, 0xee, 0xfc, 0xe8, 0x00, 0x4e, 0xf8, 
+	0x27, 0x66, 0xe8, 0x00, 0x4e, 0xf8, 0x27, 0x68, 
+	0xe8, 0x00, 0x4e, 0xf8, 0x27, 0x6c, 0xe8, 0x00, 
+	0x4e, 0xf8, 0x27, 0x6a, 0x77, 0x12, 0x27, 0x40, 
+	0x77, 0x11, 0x24, 0x00, 0x77, 0x1a, 0x00, 0x1f, 
+	0xf0, 0x72, 0x11, 0xdb, 0x70, 0x92, 0x00, 0x11, 
+	0x76, 0xe1, 0x00, 0x01, 0xff, 0xff, 0x76, 0x81, 
+	0x00, 0x00, 0x76, 0xe1, 0x00, 0x02, 0x00, 0x00, 
+	0x76, 0xe1, 0x00, 0x03, 0x00, 0xff, 0x76, 0xe1, 
+	0x00, 0x0c, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x0b, 
+	0x00, 0x00, 0x76, 0xe1, 0x00, 0x04, 0x00, 0x00, 
+	0x6d, 0xe9, 0x00, 0x0d, 0xf0, 0x20, 0x25, 0xa0, 
+	0xf1, 0x00, 0x00, 0x07, 0x89, 0x11, 0xf1, 0x00, 
+	0x00, 0x01, 0x81, 0x02, 0x88, 0x16, 0xf4, 0x95, 
+	0x77, 0x17, 0x00, 0x20, 0x76, 0x86, 0x00, 0xff, 
+	0x76, 0x00, 0x00, 0x00, 0x76, 0x01, 0x00, 0x06, 
+	0x10, 0x02, 0xf0, 0x74, 0x06, 0x6c, 0x76, 0x00, 
+	0x00, 0x00, 0x76, 0x01, 0x00, 0x06, 0xf2, 0x74, 
+	0x06, 0x6c, 0xf4, 0x95, 0x48, 0x11, 0x10, 0x02, 
+	0xf0, 0x00, 0x00, 0x0d, 0x80, 0x02, 0x6d, 0xe9, 
+	0x00, 0x0d, 0x6d, 0xee, 0x00, 0x0d, 0x6c, 0xef, 
+	0xff, 0xff, 0x11, 0xe8, 0xf0, 0x74, 0x0c, 0x9d, 
+	0xee, 0x04, 0x8a, 0x17, 0x8a, 0x16, 0x8a, 0x11, 
+	0xfc, 0x00, 0x4a, 0x11, 0x4a, 0x16, 0x4a, 0x17, 
+	0xee, 0xfa, 0x88, 0x11, 0x10, 0x0a, 0x49, 0x11, 
+	0xf8, 0x4d, 0x12, 0x9f, 0x48, 0x08, 0xf8, 0x45, 
+	0x12, 0x9f, 0x80, 0x04, 0x12, 0x81, 0xf5, 0x78, 
+	0x89, 0x12, 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0xe2, 
+	0xff, 0xb9, 0x12, 0x8a, 0x61, 0xf8, 0x00, 0x08, 
+	0x00, 0x80, 0xf8, 0x30, 0x12, 0x8a, 0x13, 0xe1, 
+	0x00, 0x01, 0xf0, 0xe8, 0xf7, 0x78, 0xf1, 0xa0, 
+	0xf2, 0x30, 0x1f, 0xff, 0x88, 0x17, 0xf4, 0x95, 
+	0x77, 0x12, 0x24, 0x00, 0x77, 0x16, 0x00, 0x00, 
+	0x77, 0x13, 0x00, 0x20, 0xf6, 0xb8, 0x48, 0x17, 
+	0x08, 0xe2, 0x00, 0x01, 0xf8, 0x45, 0x12, 0x42, 
+	0x6d, 0xea, 0x00, 0x0d, 0x6d, 0x96, 0x6c, 0xeb, 
+	0xff, 0xff, 0x12, 0x34, 0xf0, 0x73, 0x12, 0x90, 
+	0x56, 0xf8, 0x27, 0x6a, 0xf0, 0x00, 0x00, 0x01, 
+	0x4e, 0xf8, 0x27, 0x6a, 0x60, 0x82, 0x00, 0x01, 
+	0xf8, 0x30, 0x12, 0x54, 0x70, 0x00, 0x00, 0x16, 
+	0xf2, 0x74, 0x11, 0x38, 0xf4, 0x95, 0x48, 0x11, 
+	0xf0, 0x73, 0x12, 0x90, 0x70, 0x00, 0x00, 0x16, 
+	0xf2, 0x74, 0x11, 0x38, 0xf4, 0x95, 0x48, 0x11, 
+	0x72, 0x10, 0x2a, 0x9e, 0xf4, 0x95, 0xf4, 0xaf, 
+	0xf8, 0x30, 0x12, 0x6e, 0x76, 0x00, 0x00, 0x00, 
+	0x76, 0x01, 0x00, 0xbc, 0x70, 0x02, 0x00, 0x16, 
+	0x76, 0x03, 0x00, 0x00, 0xf2, 0x74, 0x0c, 0xb9, 
+	0xf4, 0x95, 0x48, 0x11, 0xf0, 0x73, 0x12, 0x90, 
+	0x10, 0xf8, 0x27, 0x6e, 0xf8, 0x44, 0x12, 0x90, 
+	0x76, 0x00, 0x00, 0x00, 0x76, 0x01, 0x00, 0xbc, 
+	0x70, 0x02, 0x00, 0x16, 0x76, 0x03, 0x00, 0x00, 
+	0xf2, 0x74, 0x0c, 0xb9, 0xf4, 0x95, 0x48, 0x11, 
+	0xf0, 0x74, 0x0c, 0x5e, 0xf0, 0xe0, 0xf0, 0x10, 
+	0x13, 0x88, 0xf8, 0x42, 0x12, 0x90, 0x76, 0xf8, 
+	0x27, 0x6e, 0x00, 0x01, 0xf0, 0x73, 0x12, 0x90, 
+	0x56, 0xf8, 0x27, 0x66, 0xf0, 0x00, 0x00, 0x01, 
+	0x4e, 0xf8, 0x27, 0x66, 0x6d, 0xe9, 0x00, 0x5e, 
+	0x56, 0xf8, 0x27, 0x68, 0xf0, 0x00, 0x00, 0x01, 
+	0x4e, 0xf8, 0x27, 0x68, 0x71, 0x04, 0x00, 0x12, 
+	0x6e, 0xea, 0xff, 0xff, 0x12, 0x18, 0x70, 0x04, 
+	0x00, 0x12, 0xee, 0x06, 0x8a, 0x17, 0x8a, 0x16, 
+	0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe, 
+	0x88, 0x0e, 0xf4, 0x95, 0xf0, 0x66, 0x00, 0x0d, 
+	0xf0, 0x00, 0x25, 0xa0, 0x88, 0x11, 0xf4, 0x95, 
+	0xf4, 0x95, 0x76, 0x81, 0x00, 0xff, 0x76, 0x00, 
+	0x00, 0x00, 0x76, 0x01, 0x00, 0x06, 0xf2, 0x74, 
+	0x06, 0x6c, 0xf0, 0x00, 0x00, 0x01, 0x76, 0x00, 
+	0x00, 0x00, 0x76, 0x01, 0x00, 0x06, 0x48, 0x11, 
+	0xf2, 0x74, 0x06, 0x6c, 0xf0, 0x00, 0x00, 0x07, 
+	0xee, 0x02, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 
+	0x88, 0x0e, 0xf4, 0x95, 0xf0, 0x66, 0x00, 0x0d, 
+	0xf0, 0x00, 0x24, 0x00, 0x88, 0x11, 0xf4, 0x95, 
+	0xf4, 0x95, 0x76, 0xe1, 0x00, 0x01, 0xff, 0xff, 
+	0x76, 0x81, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x02, 
+	0x00, 0x00, 0x76, 0xe1, 0x00, 0x03, 0x00, 0xff, 
+	0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xf4, 0x95, 
+	0x13, 0x03, 0x88, 0x11, 0xfa, 0x4d, 0x12, 0xec, 
+	0x71, 0x02, 0x00, 0x12, 0xf3, 0x10, 0x00, 0x01, 
+	0x89, 0x1a, 0xf4, 0x95, 0xf0, 0x72, 0x12, 0xeb, 
+	0x70, 0x91, 0x00, 0x12, 0x8a, 0x11, 0xfc, 0x00, 
+	0xf4, 0x95, 0x4a, 0x0b, 0x4a, 0x0c, 0x4a, 0x0d, 
+	0xf7, 0xb8, 0xee, 0xfe, 0x10, 0xf8, 0x00, 0x08, 
+	0x11, 0x06, 0xf1, 0xc0, 0x83, 0x00, 0xf4, 0x85, 
+	0x11, 0x06, 0xf7, 0x85, 0x81, 0x06, 0xf6, 0xb8, 
+	0xec, 0x0f, 0x1e, 0x06, 0x61, 0x00, 0x80, 0x00, 
+	0xf8, 0x20, 0x13, 0x05, 0xf4, 0x84, 0xee, 0x02, 
+	0x8a, 0x0d, 0x8a, 0x0c, 0x8a, 0x0b, 0xfc, 0x00, 
+	0xf4, 0x95, 0x4a, 0x0b, 0x4a, 0x0c, 0x4a, 0x0d, 
+	0xee, 0xfe, 0xf7, 0xb8, 0x80, 0x00, 0x10, 0xf8, 
+	0x00, 0x08, 0xf4, 0x85, 0x11, 0x06, 0xf7, 0x85, 
+	0x81, 0x06, 0xf6, 0xb8, 0xec, 0x0f, 0x1e, 0x06, 
+	0xf0, 0xf0, 0x61, 0x00, 0x80, 0x00, 0xf8, 0x20, 
+	0x13, 0x20, 0xf4, 0x84, 0xee, 0x02, 0x8a, 0x0d, 
+	0x8a, 0x0c, 0x8a, 0x0b, 0xfc, 0x00, 0x4a, 0x11, 
+	0x77, 0x11, 0x00, 0x7b, 0x76, 0x81, 0x2e, 0xec, 
+	0x77, 0x11, 0x00, 0x7b, 0xee, 0xff, 0x71, 0x81, 
+	0x00, 0x11, 0xee, 0x01, 0x76, 0xe1, 0x00, 0x01, 
+	0x00, 0x00, 0x76, 0xe1, 0x00, 0x04, 0x00, 0x00, 
+	0x76, 0xe1, 0x00, 0x06, 0x00, 0x00, 0x76, 0xe1, 
+	0x00, 0x62, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x76, 
+	0x00, 0x00, 0x76, 0xe1, 0x00, 0x92, 0x00, 0x00, 
+	0x76, 0xe1, 0x00, 0x94, 0x00, 0x00, 0x76, 0xe1, 
+	0x00, 0xb0, 0x00, 0x00, 0x76, 0xe1, 0x00, 0xb3, 
+	0x00, 0x00, 0x76, 0xe1, 0x00, 0xbe, 0x00, 0x00, 
+	0x76, 0xe1, 0x00, 0xbf, 0x00, 0x00, 0x76, 0xe1, 
+	0x00, 0xc1, 0x00, 0x00, 0x76, 0xe1, 0x00, 0xc3, 
+	0x00, 0x00, 0x76, 0xe1, 0x00, 0xc5, 0x00, 0x00, 
+	0x76, 0xe1, 0x00, 0xc7, 0x00, 0x00, 0x76, 0x81, 
+	0x00, 0x00, 0x8a, 0x11, 0xf4, 0x95, 0xf4, 0xe4, 
+	0x4a, 0x11, 0x4a, 0x16, 0x4a, 0x17, 0xee, 0xff, 
+	0xf4, 0x95, 0x71, 0x06, 0x00, 0x16, 0xfb, 0x80, 
+	0x16, 0xa2, 0x88, 0x17, 0xf4, 0x95, 0xf7, 0xb8, 
+	0x10, 0xf8, 0x00, 0x17, 0xf0, 0x10, 0x00, 0x02, 
+	0xfa, 0x46, 0x13, 0x88, 0x77, 0x11, 0x00, 0x00, 
+	0x10, 0xf8, 0x00, 0x17, 0xf0, 0x10, 0x00, 0x02, 
+	0xf8, 0x45, 0x13, 0xf9, 0x10, 0xf8, 0x00, 0x17, 
+	0xf8, 0x45, 0x14, 0x39, 0x10, 0xf8, 0x00, 0x17, 
+	0xf0, 0x10, 0x00, 0x01, 0xf8, 0x45, 0x14, 0x1f, 
+	0xf0, 0x73, 0x14, 0x52, 0x10, 0xf8, 0x00, 0x17, 
+	0xf0, 0x10, 0x00, 0x03, 0xf8, 0x45, 0x13, 0xd3, 
+	0x10, 0xf8, 0x00, 0x17, 0xf0, 0x10, 0x00, 0x06, 
+	0xf8, 0x44, 0x14, 0x52, 0x77, 0x12, 0x00, 0x7b, 
+	0x71, 0x82, 0x00, 0x14, 0x61, 0xe4, 0x00, 0x07, 
+	0x00, 0x40, 0xf8, 0x30, 0x14, 0x52, 0x49, 0x14, 
+	0x48, 0x17, 0xf6, 0x00, 0x88, 0x12, 0xf4, 0x95, 
+	0x77, 0x13, 0x00, 0x55, 0x77, 0x11, 0x00, 0x57, 
+	0x6d, 0xea, 0x00, 0x3b, 0xe5, 0x01, 0x10, 0xe6, 
+	0x00, 0x06, 0x80, 0x81, 0x48, 0x14, 0x00, 0xf8, 
+	0x00, 0x17, 0x88, 0x12, 0xf4, 0x95, 0x77, 0x11, 
+	0x00, 0x55, 0x10, 0xe2, 0x00, 0x40, 0x80, 0x81, 
+	0x77, 0x11, 0x00, 0x57, 0x10, 0xe6, 0x00, 0x07, 
+	0x80, 0x81, 0x77, 0x11, 0x00, 0x55, 0x10, 0xe2, 
+	0x00, 0x45, 0x80, 0x81, 0x10, 0xe6, 0x00, 0x08, 
+	0x77, 0x11, 0x00, 0x57, 0x80, 0x81, 0x77, 0x11, 
+	0x00, 0x55, 0x10, 0xe2, 0x00, 0x4a, 0x80, 0x81, 
+	0x77, 0x11, 0x00, 0x57, 0x10, 0xe6, 0x00, 0x09, 
+	0x80, 0x81, 0xf2, 0x73, 0x14, 0x52, 0x77, 0x11, 
+	0x03, 0xc0, 0x77, 0x12, 0x00, 0x7b, 0x10, 0x82, 
+	0xf0, 0x00, 0x00, 0x07, 0x88, 0x13, 0xf4, 0x95, 
+	0xf4, 0x95, 0x96, 0x1b, 0xf8, 0x30, 0x14, 0x52, 
+	0x10, 0xe3, 0x00, 0x35, 0x77, 0x12, 0x00, 0x55, 
+	0x80, 0x82, 0x77, 0x12, 0x00, 0x57, 0x10, 0xe6, 
+	0x00, 0x04, 0x80, 0x82, 0x77, 0x12, 0x00, 0x55, 
+	0x10, 0xe3, 0x00, 0x37, 0x80, 0x82, 0x77, 0x12, 
+	0x00, 0x57, 0x10, 0xe6, 0x00, 0x05, 0x80, 0x82, 
+	0x48, 0x11, 0xf0, 0x40, 0x00, 0x10, 0xf2, 0x73, 
+	0x14, 0x50, 0xf0, 0x40, 0x00, 0x20, 0x77, 0x12, 
+	0x00, 0x7b, 0x10, 0x82, 0xf0, 0x00, 0x00, 0x07, 
+	0x88, 0x12, 0xf4, 0x95, 0xf4, 0x95, 0x96, 0x0d, 
+	0xf8, 0x30, 0x14, 0x52, 0x10, 0xe2, 0x00, 0x34, 
+	0x77, 0x13, 0x00, 0x55, 0x80, 0x83, 0x77, 0x13, 
+	0x00, 0x57, 0x10, 0xe6, 0x00, 0x02, 0x80, 0x83, 
+	0x10, 0xe2, 0x00, 0x36, 0x77, 0x12, 0x00, 0x55, 
+	0x80, 0x82, 0x77, 0x12, 0x00, 0x57, 0x10, 0xe6, 
+	0x00, 0x03, 0x80, 0x82, 0x48, 0x11, 0xf0, 0x40, 
+	0x00, 0x04, 0xf2, 0x73, 0x14, 0x50, 0xf0, 0x40, 
+	0x00, 0x08, 0x77, 0x12, 0x00, 0x7b, 0x10, 0x82, 
+	0xf0, 0x00, 0x00, 0x07, 0x88, 0x12, 0xf4, 0x95, 
+	0xf4, 0x95, 0x96, 0x0e, 0xf8, 0x30, 0x14, 0x52, 
+	0x10, 0xe2, 0x00, 0x33, 0x77, 0x12, 0x00, 0x55, 
+	0x80, 0x82, 0x77, 0x12, 0x00, 0x57, 0x10, 0xe6, 
+	0x00, 0x01, 0x80, 0x82, 0x48, 0x11, 0xf2, 0x73, 
+	0x14, 0x50, 0xf0, 0x40, 0x00, 0x02, 0x77, 0x12, 
+	0x00, 0x7b, 0x10, 0x82, 0xf0, 0x00, 0x00, 0x07, 
+	0x88, 0x12, 0xf4, 0x95, 0xf4, 0x95, 0x96, 0x0f, 
+	0xf8, 0x30, 0x14, 0x52, 0x10, 0xe2, 0x00, 0x32, 
+	0x77, 0x12, 0x00, 0x55, 0x77, 0x13, 0x00, 0x57, 
+	0x80, 0x82, 0x48, 0x11, 0xe7, 0x62, 0xf0, 0x40, 
+	0x00, 0x01, 0xe5, 0x01, 0x88, 0x11, 0xf4, 0x95, 
+	0x77, 0x12, 0x00, 0x7b, 0x48, 0x11, 0x71, 0x82, 
+	0x00, 0x12, 0x1a, 0xe2, 0x00, 0x07, 0x80, 0xe2, 
+	0x00, 0x07, 0xf9, 0x80, 0x16, 0x9a, 0xee, 0x01, 
+	0x8a, 0x17, 0x48, 0x11, 0x8a, 0x16, 0x8a, 0x11, 
+	0xf4, 0xe4, 0x4a, 0x11, 0x88, 0x11, 0x77, 0x0e, 
+	0x00, 0x05, 0x77, 0x12, 0x00, 0x55, 0xe8, 0x04, 
+	0xf6, 0xb8, 0x28, 0xe1, 0x00, 0x02, 0xee, 0xff, 
+	0x80, 0x82, 0x77, 0x12, 0x00, 0x57, 0xf0, 0x20, 
+	0x80, 0x00, 0xee, 0x01, 0x1a, 0x82, 0x77, 0x12, 
+	0x00, 0x57, 0x80, 0x82, 0xe8, 0x01, 0x32, 0xe1, 
+	0x00, 0x02, 0xf5, 0x82, 0x77, 0x11, 0x00, 0x54, 
+	0xf6, 0x93, 0x18, 0x81, 0x77, 0x11, 0x00, 0x54, 
+	0xf2, 0xa0, 0x80, 0x81, 0x8a, 0x11, 0xf4, 0x95, 
+	0xf4, 0xe4, 0x4a, 0x11, 0x4a, 0x16, 0xf4, 0x95, 
+	0x71, 0x04, 0x00, 0x11, 0xfb, 0x80, 0x16, 0xa2, 
+	0x88, 0x16, 0xf4, 0x95, 0x77, 0x12, 0x00, 0x55, 
+	0x10, 0xe6, 0x00, 0x03, 0x80, 0x82, 0x77, 0x12, 
+	0x00, 0x56, 0x10, 0xe1, 0x00, 0x02, 0x77, 0x13, 
+	0x00, 0x56, 0x80, 0x82, 0x77, 0x12, 0x00, 0x56, 
+	0x10, 0xe1, 0x00, 0x03, 0x80, 0x82, 0x10, 0xe1, 
+	0x00, 0x04, 0x77, 0x12, 0x00, 0x56, 0x80, 0x82, 
+	0x77, 0x12, 0x00, 0x56, 0x10, 0xe1, 0x00, 0x01, 
+	0x80, 0x82, 0xe7, 0x12, 0xe5, 0x01, 0xf9, 0x80, 
+	0x16, 0x9a, 0x8a, 0x16, 0x8a, 0x11, 0xf4, 0xe4, 
+	0x4a, 0x11, 0x4a, 0x16, 0x4a, 0x17, 0xee, 0xf9, 
+	0x77, 0x11, 0x00, 0x7b, 0x76, 0x00, 0x00, 0x16, 
+	0x76, 0x01, 0x00, 0x17, 0x76, 0x02, 0x00, 0x1a, 
+	0x76, 0x03, 0x00, 0x1b, 0x76, 0x04, 0x00, 0x1c, 
+	0x76, 0x05, 0x00, 0x1d, 0x71, 0x81, 0x00, 0x17, 
+	0x71, 0xe7, 0x00, 0x06, 0x00, 0x11, 0x10, 0x81, 
+	0xf8, 0x44, 0x14, 0xdf, 0xf9, 0x80, 0x16, 0x53, 
+	0xf6, 0xb8, 0xfb, 0x80, 0x15, 0x85, 0xf0, 0x20, 
+	0xff, 0xff, 0xf6, 0xb8, 0xfb, 0x80, 0x16, 0x08, 
+	0xf0, 0x20, 0xff, 0xff, 0x77, 0x11, 0x00, 0x7b, 
+	0x71, 0x81, 0x00, 0x17, 0x76, 0xe7, 0x00, 0x06, 
+	0x00, 0x01, 0x48, 0x17, 0x77, 0x16, 0x00, 0x00, 
+	0x77, 0x10, 0x00, 0x04, 0x77, 0x15, 0x00, 0x03, 
+	0x77, 0x14, 0x00, 0x02, 0x77, 0x13, 0x00, 0x01, 
+	0xf0, 0x00, 0x00, 0x39, 0x76, 0xe7, 0x00, 0x08, 
+	0x00, 0x1f, 0x76, 0xe7, 0x00, 0x07, 0x00, 0x00, 
+	0x88, 0x0e, 0x77, 0x1a, 0x00, 0x05, 0x48, 0x17, 
+	0xf0, 0x00, 0x00, 0x09, 0x88, 0x12, 0x48, 0x18, 
+	0x88, 0x19, 0xe8, 0x00, 0xf0, 0x72, 0x15, 0x2c, 
+	0x73, 0x19, 0x00, 0x11, 0x76, 0x82, 0x00, 0x00, 
+	0x11, 0x91, 0x73, 0x11, 0x00, 0x19, 0x70, 0xe2, 
+	0x00, 0x03, 0x00, 0x16, 0x70, 0xe2, 0x00, 0x04, 
+	0x00, 0x13, 0x70, 0xe2, 0x00, 0x05, 0x00, 0x14, 
+	0x81, 0xe2, 0x00, 0x01, 0x70, 0xe2, 0x00, 0x06, 
+	0x00, 0x15, 0x70, 0xe2, 0x00, 0x07, 0x00, 0x10, 
+	0x80, 0xe2, 0x00, 0x02, 0x73, 0x0e, 0x00, 0x11, 
+	0xf1, 0x00, 0x00, 0x1e, 0x6d, 0xee, 0x00, 0x05, 
+	0x6d, 0xeb, 0x00, 0x05, 0x6d, 0xec, 0x00, 0x05, 
+	0x6d, 0xed, 0x00, 0x05, 0x6d, 0xe8, 0x00, 0x05, 
+	0xf0, 0x00, 0x00, 0x01, 0x81, 0x91, 0x6d, 0xea, 
+	0x00, 0x08, 0x73, 0x11, 0x00, 0x0e, 0xee, 0x07, 
+	0x76, 0xe7, 0x00, 0x41, 0x00, 0x24, 0x76, 0xe7, 
+	0x00, 0x46, 0x00, 0x25, 0x76, 0xe7, 0x00, 0x4b, 
+	0x00, 0x26, 0x76, 0xe7, 0x00, 0x50, 0x00, 0x27, 
+	0x8a, 0x17, 0x8a, 0x16, 0x8a, 0x11, 0xf4, 0xe4, 
+	0x4a, 0x11, 0x4a, 0x16, 0xee, 0xfe, 0x88, 0x11, 
+	0x56, 0x06, 0x4e, 0x00, 0xf9, 0x80, 0x16, 0xa2, 
+	0xf7, 0xb8, 0x10, 0xf8, 0x00, 0x11, 0xf0, 0x10, 
+	0xff, 0xff, 0xfa, 0x45, 0x15, 0x60, 0x77, 0x16, 
+	0xff, 0xff, 0x77, 0x12, 0x00, 0x7b, 0x49, 0x11, 
+	0x10, 0x82, 0xf6, 0x03, 0xf0, 0x00, 0x00, 0x09, 
+	0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x10, 0x81, 
+	0xf8, 0x44, 0x15, 0x71, 0xf2, 0x73, 0x15, 0x71, 
+	0xf4, 0x95, 0xe7, 0x16, 0x77, 0x11, 0x00, 0x7b, 
+	0x10, 0x81, 0xf0, 0x00, 0x00, 0x09, 0x88, 0x11, 
+	0xf4, 0x95, 0x77, 0x12, 0x00, 0x06, 0x10, 0x81, 
+	0xf8, 0x45, 0x15, 0x5c, 0x6e, 0xea, 0xff, 0xff, 
+	0x15, 0x69, 0x6d, 0xe9, 0x00, 0x08, 0x76, 0x86, 
+	0x00, 0x01, 0xe9, 0x01, 0x56, 0x00, 0xf1, 0x80, 
+	0x10, 0xf8, 0x00, 0x0b, 0xf8, 0x45, 0x15, 0x7e, 
+	0xfb, 0x80, 0x15, 0x85, 0xf4, 0x95, 0x48, 0x16, 
+	0xf9, 0x80, 0x16, 0x9a, 0xee, 0x02, 0x48, 0x16, 
+	0x8a, 0x16, 0x8a, 0x11, 0xf4, 0xe4, 0x4a, 0x11, 
+	0xee, 0xff, 0xfb, 0x80, 0x16, 0xa2, 0x88, 0x11, 
+	0xf4, 0x95, 0x77, 0x10, 0xff, 0xff, 0xf4, 0xa9, 
+	0xf8, 0x30, 0x15, 0xc4, 0x10, 0xe1, 0x00, 0x03, 
+	0x77, 0x12, 0x00, 0x55, 0x80, 0x82, 0x77, 0x12, 
+	0x00, 0x56, 0x76, 0x82, 0x00, 0x00, 0x77, 0x12, 
+	0x00, 0x56, 0x76, 0x82, 0x00, 0x00, 0x77, 0x12, 
+	0x00, 0x56, 0x76, 0x82, 0x00, 0x00, 0x77, 0x12, 
+	0x00, 0x56, 0x76, 0x82, 0x00, 0x00, 0x77, 0x12, 
+	0x00, 0x56, 0x76, 0x82, 0x00, 0x00, 0x10, 0xe1, 
+	0x00, 0x02, 0xf0, 0x00, 0x00, 0x08, 0x32, 0xf8, 
+	0x00, 0x08, 0x77, 0x12, 0x00, 0x54, 0xe8, 0x01, 
+	0xf4, 0x82, 0xf4, 0x93, 0x18, 0x82, 0x77, 0x12, 
+	0x00, 0x54, 0xf0, 0x40, 0x00, 0x00, 0x80, 0x82, 
+	0x10, 0xe1, 0x00, 0x01, 0xf9, 0x80, 0x16, 0x76, 
+	0x10, 0xe1, 0x00, 0x01, 0xf9, 0x80, 0x16, 0x66, 
+	0xf0, 0x73, 0x16, 0x03, 0x77, 0x11, 0x00, 0x7b, 
+	0x71, 0x81, 0x00, 0x11, 0x71, 0xe1, 0x00, 0x07, 
+	0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x10, 0xe1, 
+	0x00, 0x09, 0xf9, 0x80, 0x15, 0x85, 0x77, 0x11, 
+	0x00, 0x7b, 0x71, 0x81, 0x00, 0x11, 0x10, 0xe1, 
+	0x00, 0x09, 0xfb, 0x80, 0x15, 0x85, 0xf0, 0x00, 
+	0x00, 0x08, 0x77, 0x11, 0x00, 0x7b, 0x71, 0x81, 
+	0x00, 0x11, 0x10, 0xe1, 0x00, 0x09, 0xfb, 0x80, 
+	0x15, 0x85, 0xf0, 0x00, 0x00, 0x10, 0x77, 0x11, 
+	0x00, 0x7b, 0x71, 0x81, 0x00, 0x11, 0x10, 0xe1, 
+	0x00, 0x09, 0xfb, 0x80, 0x15, 0x85, 0xf0, 0x00, 
+	0x00, 0x18, 0x77, 0x11, 0x00, 0x7b, 0x71, 0x81, 
+	0x00, 0x11, 0x10, 0xe1, 0x00, 0x09, 0xfb, 0x80, 
+	0x15, 0x85, 0xf0, 0x00, 0x00, 0x20, 0x77, 0x11, 
+	0x00, 0x7b, 0x71, 0x81, 0x00, 0x11, 0x10, 0xe1, 
+	0x00, 0x09, 0xfb, 0x80, 0x15, 0x85, 0xf0, 0x00, 
+	0x00, 0x28, 0xf9, 0x80, 0x16, 0x9a, 0xee, 0x01, 
+	0x8a, 0x11, 0xf4, 0xe4, 0x4a, 0x11, 0xee, 0xff, 
+	0xfb, 0x80, 0x16, 0xa2, 0x88, 0x11, 0xf4, 0x95, 
+	0x77, 0x10, 0xff, 0xff, 0xf4, 0xa9, 0xf8, 0x30, 
+	0x16, 0x41, 0x77, 0x11, 0x00, 0x55, 0x76, 0x81, 
+	0x00, 0x1e, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81, 
+	0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81, 
+	0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81, 
+	0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81, 
+	0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81, 
+	0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81, 
+	0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81, 
+	0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81, 
+	0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81, 
+	0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0xf2, 0x73, 
+	0x16, 0x4e, 0x76, 0x81, 0x00, 0x00, 0x77, 0x11, 
+	0x00, 0x7b, 0x71, 0x81, 0x00, 0x11, 0x71, 0xe1, 
+	0x00, 0x07, 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 
+	0x10, 0xe1, 0x00, 0x39, 0xf9, 0x80, 0x16, 0x08, 
+	0xf9, 0x80, 0x16, 0x9a, 0xee, 0x01, 0x8a, 0x11, 
+	0xf4, 0xe4, 0x4a, 0x11, 0x77, 0x11, 0x00, 0x7b, 
+	0x10, 0x81, 0xf0, 0x00, 0x00, 0x04, 0x88, 0x11, 
+	0xf4, 0x95, 0xf4, 0x95, 0x10, 0x81, 0xfa, 0x44, 
+	0x16, 0x63, 0xf4, 0x95, 0xee, 0xff, 0x76, 0x81, 
+	0x00, 0x01, 0xee, 0x01, 0x8a, 0x11, 0xf4, 0xe4, 
+	0xf0, 0x10, 0x00, 0x10, 0x4a, 0x11, 0x32, 0xf8, 
+	0x00, 0x08, 0xee, 0xff, 0x77, 0x11, 0x00, 0x01, 
+	0xe8, 0x01, 0xee, 0x01, 0xf4, 0x82, 0x1a, 0x81, 
+	0x80, 0x81, 0x8a, 0x11, 0xf4, 0x95, 0xf4, 0xe4, 
+	0xf0, 0x10, 0x00, 0x10, 0x4a, 0x11, 0x32, 0xf8, 
+	0x00, 0x08, 0xee, 0xff, 0xe8, 0x01, 0x77, 0x11, 
+	0x00, 0x00, 0xf4, 0x82, 0xee, 0x01, 0xf4, 0x93, 
+	0x18, 0x81, 0x80, 0x81, 0x8a, 0x11, 0xf4, 0x95, 
+	0xf4, 0xe4, 0x4a, 0x11, 0xf0, 0x10, 0x00, 0x10, 
+	0x77, 0x11, 0x00, 0x00, 0x32, 0xf8, 0x00, 0x08, 
+	0xee, 0xff, 0x11, 0x81, 0xe8, 0x01, 0xee, 0x01, 
+	0x77, 0x11, 0x00, 0x00, 0xf4, 0x82, 0xf2, 0xa0, 
+	0x80, 0x81, 0x8a, 0x11, 0xf4, 0x95, 0xf4, 0xe4, 
+	0xf2, 0x73, 0x16, 0x9e, 0xf6, 0xbb, 0xf4, 0x95, 
+	0xf4, 0x95, 0xf4, 0x95, 0xf4, 0x95, 0xf4, 0xe4, 
+	0xf2, 0x73, 0x16, 0xa6, 0xf7, 0xbb, 0xf4, 0x95, 
+	0xf4, 0x95, 0xf4, 0x95, 0xf4, 0x95, 0xf4, 0xe4, 
+	0x4a, 0x11, 0x4a, 0x16, 0xf4, 0x95, 0x71, 0x04, 
+	0x00, 0x16, 0xfb, 0x80, 0x16, 0xa2, 0x88, 0x11, 
+	0xf4, 0x95, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 
+	0x76, 0x82, 0x00, 0x0e, 0x10, 0xe6, 0x00, 0x0e, 
+	0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x80, 0x82, 
+	0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 
+	0x00, 0x0d, 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 
+	0x10, 0xe6, 0x00, 0x0d, 0x80, 0x82, 0x71, 0xe1, 
+	0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x0c, 
+	0x10, 0xe6, 0x00, 0x0c, 0x71, 0xe1, 0x00, 0x06, 
+	0x00, 0x12, 0x80, 0x82, 0x71, 0xe1, 0x00, 0x05, 
+	0x00, 0x12, 0x76, 0x82, 0x00, 0x0b, 0x10, 0xe6, 
+	0x00, 0x0b, 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 
+	0x80, 0x82, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 
+	0x76, 0x82, 0x00, 0x0a, 0x71, 0xe1, 0x00, 0x06, 
+	0x00, 0x12, 0x10, 0xe6, 0x00, 0x0a, 0x80, 0x82, 
+	0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 
+	0x00, 0x09, 0x10, 0xe6, 0x00, 0x09, 0x71, 0xe1, 
+	0x00, 0x06, 0x00, 0x12, 0x80, 0x82, 0x71, 0xe1, 
+	0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x08, 
+	0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x10, 0xe6, 
+	0x00, 0x08, 0x80, 0x82, 0x71, 0xe1, 0x00, 0x05, 
+	0x00, 0x12, 0x76, 0x82, 0x00, 0x07, 0x10, 0xe6, 
+	0x00, 0x07, 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 
+	0x80, 0x82, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 
+	0x76, 0x82, 0x00, 0x06, 0x71, 0xe1, 0x00, 0x06, 
+	0x00, 0x12, 0x10, 0xe6, 0x00, 0x06, 0x80, 0x82, 
+	0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 
+	0x00, 0x05, 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 
+	0x10, 0xe6, 0x00, 0x05, 0x80, 0x82, 0x71, 0xe1, 
+	0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x04, 
+	0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x10, 0xe6, 
+	0x00, 0x04, 0x80, 0x82, 0x71, 0xe1, 0x00, 0x05, 
+	0x00, 0x12, 0x76, 0x82, 0x00, 0x03, 0x71, 0xe1, 
+	0x00, 0x06, 0x00, 0x12, 0x10, 0xe6, 0x00, 0x03, 
+	0x80, 0x82, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 
+	0x76, 0x82, 0x00, 0x02, 0x10, 0xe6, 0x00, 0x02, 
+	0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x80, 0x82, 
+	0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 
+	0x00, 0x01, 0x10, 0xe6, 0x00, 0x01, 0x71, 0xe1, 
+	0x00, 0x06, 0x00, 0x12, 0x80, 0x82, 0x71, 0xe1, 
+	0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 
+	0x71, 0xe1, 0x00, 0x06, 0x00, 0x13, 0xe7, 0x62, 
+	0xe5, 0x01, 0xf9, 0x80, 0x16, 0x9a, 0x8a, 0x16, 
+	0x8a, 0x11, 0xf4, 0xe4, 0x4a, 0x11, 0x88, 0x11, 
+	0xf4, 0x95, 0xf4, 0x95, 0x71, 0xe1, 0x00, 0x05, 
+	0x00, 0x12, 0xee, 0xff, 0x76, 0x82, 0x00, 0x00, 
+	0xee, 0x01, 0x71, 0xe1, 0x00, 0x06, 0x00, 0x11, 
+	0x69, 0x81, 0x00, 0x01, 0x8a, 0x11, 0xf4, 0x95, 
+	0xf4, 0xe4, 0x4a, 0x11, 0x88, 0x11, 0xf4, 0x95, 
+	0xf4, 0x95, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 
+	0xee, 0xff, 0x76, 0x82, 0x00, 0x01, 0xee, 0x01, 
+	0x71, 0xe1, 0x00, 0x06, 0x00, 0x11, 0x69, 0x81, 
+	0x00, 0x01, 0x8a, 0x11, 0xf4, 0x95, 0xf4, 0xe4, 
+	0x4a, 0x11, 0x77, 0x11, 0x00, 0x7b, 0x10, 0x81, 
+	0xf0, 0x00, 0x00, 0x94, 0x88, 0x11, 0xf4, 0x95, 
+	0xf4, 0x95, 0x10, 0x81, 0xfa, 0x44, 0x17, 0x9c, 
+	0xf4, 0x95, 0xee, 0xff, 0xf9, 0x80, 0x16, 0x53, 
+	0x77, 0x11, 0x00, 0x7b, 0x10, 0x81, 0xf0, 0x00, 
+	0x00, 0x94, 0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 
+	0x76, 0x81, 0x00, 0x01, 0xee, 0x01, 0x76, 0xe1, 
+	0x00, 0x01, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x02, 
+	0x00, 0x21, 0x76, 0xe1, 0x00, 0x03, 0x00, 0x20, 
+	0x76, 0xe1, 0x00, 0x04, 0x00, 0x23, 0x76, 0xe1, 
+	0x00, 0x05, 0x00, 0x22, 0x76, 0xe1, 0x00, 0x06, 
+	0x00, 0x38, 0x76, 0xe1, 0x00, 0x07, 0x00, 0x39, 
+	0x76, 0xe1, 0x00, 0x08, 0x00, 0x15, 0x76, 0xe1, 
+	0x00, 0x09, 0x00, 0x14, 0x76, 0xe1, 0x00, 0x0a, 
+	0x00, 0x00, 0x76, 0xe1, 0x00, 0x0b, 0x00, 0x41, 
+	0x76, 0xe1, 0x00, 0x0c, 0x00, 0x40, 0x76, 0xe1, 
+	0x00, 0x0d, 0x00, 0x43, 0x76, 0xe1, 0x00, 0x0e, 
+	0x00, 0x42, 0x76, 0xe1, 0x00, 0x0f, 0x00, 0x48, 
+	0x76, 0xe1, 0x00, 0x10, 0x00, 0x49, 0x76, 0xe1, 
+	0x00, 0x11, 0x00, 0x1b, 0x76, 0xe1, 0x00, 0x12, 
+	0x00, 0x1a, 0x8a, 0x11, 0xf4, 0x95, 0xf4, 0xe4, 
+	0x4a, 0x11, 0xee, 0xfd, 0x88, 0x11, 0x56, 0x06, 
+	0x4e, 0x00, 0xf9, 0x80, 0x16, 0xa2, 0x77, 0x12, 
+	0x00, 0x7b, 0x77, 0x0e, 0x00, 0x09, 0x10, 0x82, 
+	0x28, 0xf8, 0x00, 0x11, 0xf0, 0x00, 0x00, 0x95, 
+	0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x10, 0x81, 
+	0xf8, 0x45, 0x17, 0xf0, 0xf2, 0x73, 0x17, 0xfd, 
+	0x77, 0x11, 0xff, 0xff, 0x76, 0x81, 0x00, 0x01, 
+	0xe9, 0x01, 0x56, 0x00, 0xf1, 0x80, 0x10, 0xf8, 
+	0x00, 0x0b, 0xf8, 0x45, 0x17, 0xfd, 0xfb, 0x80, 
+	0x18, 0x10, 0xf4, 0x95, 0x48, 0x11, 0xf9, 0x80, 
+	0x16, 0x9a, 0xee, 0x03, 0x48, 0x11, 0x8a, 0x11, 
+	0xf4, 0x95, 0xf4, 0xe4, 0x4a, 0x11, 0x88, 0x11, 
+	0xf4, 0x95, 0xee, 0xff, 0x71, 0xe1, 0x00, 0x01, 
+	0x00, 0x11, 0xee, 0x01, 0x10, 0x81, 0x8a, 0x11, 
+	0xf4, 0x95, 0xf4, 0xe4, 0x4a, 0x11, 0xee, 0xff, 
+	0xfb, 0x80, 0x16, 0xa2, 0x88, 0x11, 0xf4, 0x95, 
+	0x77, 0x10, 0xff, 0xff, 0xf4, 0xa9, 0xf8, 0x30, 
+	0x18, 0xc3, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 
+	0x76, 0x82, 0x00, 0x00, 0x71, 0xe1, 0x00, 0x06, 
+	0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1, 
+	0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x01, 
+	0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82, 
+	0x00, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 
+	0x76, 0x82, 0x00, 0x02, 0x71, 0xe1, 0x00, 0x06, 
+	0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1, 
+	0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x03, 
+	0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82, 
+	0x00, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 
+	0x76, 0x82, 0x00, 0x04, 0x71, 0xe1, 0x00, 0x06, 
+	0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1, 
+	0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x05, 
+	0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82, 
+	0x00, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 
+	0x76, 0x82, 0x00, 0x06, 0x71, 0xe1, 0x00, 0x06, 
+	0x00, 0x12, 0x76, 0x82, 0x00, 0x01, 0x71, 0xe1, 
+	0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x07, 
+	0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82, 
+	0x20, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 
+	0x76, 0x82, 0x00, 0x08, 0x71, 0xe1, 0x00, 0x06, 
+	0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1, 
+	0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x09, 
+	0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82, 
+	0x00, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 
+	0x76, 0x82, 0x00, 0x0a, 0x71, 0xe1, 0x00, 0x06, 
+	0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1, 
+	0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x0b, 
+	0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82, 
+	0x00, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 
+	0x76, 0x82, 0x00, 0x0c, 0x71, 0xe1, 0x00, 0x06, 
+	0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1, 
+	0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x0d, 
+	0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82, 
+	0x00, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 
+	0x76, 0x82, 0x00, 0x0e, 0x71, 0xe1, 0x00, 0x06, 
+	0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x10, 0xe1, 
+	0x00, 0x07, 0xf9, 0x80, 0x16, 0x76, 0x10, 0xe1, 
+	0x00, 0x08, 0xf9, 0x80, 0x16, 0x76, 0x10, 0xe1, 
+	0x00, 0x07, 0xf9, 0x80, 0x16, 0x66, 0x10, 0xe1, 
+	0x00, 0x08, 0xf9, 0x80, 0x16, 0x66, 0xf0, 0x73, 
+	0x18, 0xd1, 0x77, 0x11, 0x00, 0x7b, 0x10, 0x81, 
+	0xfb, 0x80, 0x18, 0x10, 0xf0, 0x00, 0x00, 0x95, 
+	0x77, 0x11, 0x00, 0x7b, 0x10, 0x81, 0xfb, 0x80, 
+	0x18, 0x10, 0xf0, 0x00, 0x00, 0x9e, 0xf9, 0x80, 
+	0x16, 0x9a, 0xee, 0x01, 0x8a, 0x11, 0xf4, 0xe4, 
+	0x4a, 0x11, 0x88, 0x11, 0xee, 0xff, 0xf4, 0x95, 
+	0x10, 0x04, 0x71, 0xe1, 0x00, 0x03, 0x00, 0x11, 
+	0xee, 0x01, 0x80, 0x81, 0x8a, 0x11, 0xf4, 0x95, 
+	0xf4, 0xe4, 0x4a, 0x11, 0x4a, 0x16, 0xf4, 0x95, 
+	0x71, 0x04, 0x00, 0x16, 0xfb, 0x80, 0x16, 0xa2, 
+	0x88, 0x11, 0xf4, 0x95, 0x71, 0xe1, 0x00, 0x02, 
+	0x00, 0x12, 0x76, 0x82, 0x00, 0x10, 0x10, 0xe6, 
+	0x00, 0x01, 0x71, 0xe1, 0x00, 0x03, 0x00, 0x12, 
+	0x80, 0x82, 0x71, 0xe1, 0x00, 0x04, 0x00, 0x12, 
+	0x10, 0xe6, 0x00, 0x02, 0x80, 0x82, 0xe7, 0x62, 
+	0x71, 0xe1, 0x00, 0x02, 0x00, 0x13, 0xe5, 0x01, 
+	0xf9, 0x80, 0x16, 0x9a, 0x8a, 0x16, 0x8a, 0x11, 
+	0xf4, 0xe4, 0x4a, 0x11, 0x88, 0x11, 0xee, 0xff, 
+	0xee, 0x01, 0x10, 0xe1, 0x00, 0x01, 0x8a, 0x11, 
+	0xf4, 0x95, 0xf4, 0xe4, 0x4a, 0x11, 0x77, 0x11, 
+	0x00, 0x7b, 0x10, 0x81, 0xf0, 0x00, 0x00, 0xb3, 
+	0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x10, 0x81, 
+	0xfa, 0x44, 0x19, 0x2a, 0xf4, 0x95, 0xee, 0xff, 
+	0xf9, 0x80, 0x16, 0x53, 0x77, 0x11, 0x00, 0x7b, 
+	0x10, 0x81, 0xf0, 0x00, 0x00, 0xb3, 0x88, 0x11, 
+	0xf4, 0x95, 0xf4, 0x95, 0x76, 0x81, 0x00, 0x01, 
+	0xee, 0x01, 0x76, 0xe1, 0x00, 0x01, 0x00, 0x00, 
+	0x76, 0xe1, 0x00, 0x02, 0x00, 0x13, 0x76, 0xe1, 
+	0x00, 0x03, 0x00, 0x26, 0x76, 0xe1, 0x00, 0x04, 
+	0x00, 0x25, 0x76, 0xe1, 0x00, 0x05, 0x00, 0x24, 
+	0x76, 0xe1, 0x00, 0x06, 0x00, 0x00, 0x76, 0xe1, 
+	0x00, 0x07, 0x00, 0x17, 0x76, 0xe1, 0x00, 0x08, 
+	0x00, 0x32, 0x76, 0xe1, 0x00, 0x09, 0x00, 0x31, 
+	0x76, 0xe1, 0x00, 0x0a, 0x00, 0x30, 0x8a, 0x11, 
+	0xf4, 0x95, 0xf4, 0xe4, 0x4a, 0x11, 0x4a, 0x16, 
+	0x4a, 0x17, 0xee, 0xff, 0xf4, 0x95, 0x71, 0x06, 
+	0x00, 0x17, 0xfb, 0x80, 0x16, 0xa2, 0x88, 0x11, 
+	0xf4, 0x95, 0xf7, 0xb8, 0x10, 0xf8, 0x00, 0x11, 
+	0xf0, 0x10, 0xff, 0xff, 0xfa, 0x45, 0x19, 0x73, 
+	0x77, 0x16, 0xff, 0xff, 0x77, 0x12, 0x00, 0x7b, 
+	0x77, 0x0e, 0x00, 0x05, 0x10, 0x82, 0x28, 0xf8, 
+	0x00, 0x11, 0xf0, 0x00, 0x00, 0xb4, 0x88, 0x11, 
+	0xf4, 0x95, 0xf4, 0x95, 0x10, 0x81, 0xf8, 0x44, 
+	0x19, 0x84, 0xf2, 0x73, 0x19, 0x84, 0xf4, 0x95, 
+	0xe7, 0x16, 0x77, 0x11, 0x00, 0x7b, 0x10, 0x81, 
+	0xf0, 0x00, 0x00, 0xb4, 0x88, 0x11, 0xf4, 0x95, 
+	0x77, 0x12, 0x00, 0x02, 0x10, 0x81, 0xf8, 0x45, 
+	0x19, 0x6f, 0x6e, 0xea, 0xff, 0xff, 0x19, 0x7c, 
+	0x6d, 0xe9, 0x00, 0x05, 0x61, 0xf8, 0x00, 0x17, 
+	0x00, 0x01, 0xfa, 0x20, 0x19, 0x8f, 0x76, 0x86, 
+	0x00, 0x01, 0xfb, 0x80, 0x19, 0x97, 0xf4, 0x95, 
+	0x48, 0x16, 0xf9, 0x80, 0x16, 0x9a, 0xee, 0x01, 
+	0x8a, 0x17, 0x48, 0x16, 0x8a, 0x16, 0x8a, 0x11, 
+	0xf4, 0xe4, 0x4a, 0x11, 0xee, 0xff, 0xfb, 0x80, 
+	0x16, 0xa2, 0x88, 0x11, 0xf4, 0x95, 0x77, 0x10, 
+	0xff, 0xff, 0xf4, 0xa9, 0xf8, 0x30, 0x19, 0xcc, 
+	0x71, 0xe1, 0x00, 0x02, 0x00, 0x12, 0x69, 0x82, 
+	0x00, 0x10, 0x71, 0xe1, 0x00, 0x02, 0x00, 0x12, 
+	0x68, 0x82, 0xf7, 0xff, 0x71, 0xe1, 0x00, 0x02, 
+	0x00, 0x12, 0x68, 0x82, 0xfb, 0xff, 0x71, 0xe1, 
+	0x00, 0x02, 0x00, 0x12, 0x68, 0x82, 0xff, 0xf0, 
+	0x71, 0xe1, 0x00, 0x03, 0x00, 0x12, 0x76, 0x82, 
+	0xff, 0xff, 0x71, 0xe1, 0x00, 0x04, 0x00, 0x12, 
+	0x76, 0x82, 0xff, 0xff, 0x71, 0xe1, 0x00, 0x02, 
+	0x00, 0x12, 0x69, 0x82, 0x00, 0x20, 0x71, 0xe1, 
+	0x00, 0x02, 0x00, 0x11, 0xf2, 0x73, 0x19, 0xda, 
+	0x68, 0x81, 0xff, 0xef, 0x77, 0x11, 0x00, 0x7b, 
+	0x10, 0x81, 0xfb, 0x80, 0x19, 0x97, 0xf0, 0x00, 
+	0x00, 0xb4, 0x77, 0x11, 0x00, 0x7b, 0x10, 0x81, 
+	0xfb, 0x80, 0x19, 0x97, 0xf0, 0x00, 0x00, 0xb9, 
+	0xf9, 0x80, 0x16, 0x9a, 0xee, 0x01, 0x8a, 0x11, 
+	0xf4, 0xe4, 0x00, 0xa4, 0x00, 0x00, 0x19, 0xdf, 
+	0x00, 0x01, 0x2a, 0xe6, 0x00, 0x00, 0x00, 0x01, 
+	0x2a, 0xe7, 0x00, 0x00, 0x00, 0x03, 0x2a, 0x12, 
+	0x0c, 0x01, 0xc3, 0x4f, 0x00, 0x00, 0x00, 0x01, 
+	0x2a, 0x15, 0x00, 0x00, 0x00, 0x02, 0x2a, 0x16, 
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x2a, 0x5d, 
+	0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 
+	0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 
+	0x00, 0x74, 0x00, 0x20, 0x00, 0x54, 0x00, 0x65, 
+	0x00, 0x63, 0x00, 0x68, 0x00, 0x6e, 0x00, 0x6f, 
+	0x00, 0x54, 0x00, 0x72, 0x00, 0x65, 0x00, 0x6e, 
+	0x00, 0x64, 0x00, 0x20, 0x00, 0x41, 0x00, 0x47, 
+	0x00, 0x00, 0x00, 0x04, 0x2a, 0x76, 0x00, 0x30, 
+	0x00, 0x2e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0c, 
+	0x2a, 0x7a, 0x00, 0x46, 0x00, 0x65, 0x00, 0x62, 
+	0x00, 0x20, 0x00, 0x32, 0x00, 0x37, 0x00, 0x20, 
+	0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x31, 
+	0x00, 0x00, 0x00, 0x09, 0x2a, 0x86, 0x00, 0x31, 
+	0x00, 0x34, 0x00, 0x3a, 0x00, 0x33, 0x00, 0x35, 
+	0x00, 0x3a, 0x00, 0x33, 0x00, 0x33, 0x00, 0x00, 
+	0x00, 0x0f, 0x2a, 0x8f, 0x00, 0x00, 0x00, 0x00, 
+	0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+	0x00, 0x00, 0x00, 0x01, 0x2a, 0x9e, 0x00, 0x00, 
+	0x00, 0x01, 0x2a, 0x9f, 0x00, 0x00, 0x00, 0x01, 
+	0x2a, 0xa0, 0x00, 0x00, 0x00, 0x01, 0x2a, 0xa1, 
+	0x00, 0x00, 0x00, 0x01, 0x2a, 0xa2, 0x00, 0x00, 
+	0x00, 0x01, 0x29, 0x7e, 0x00, 0x00, 0x00, 0x02, 
+	0x29, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 
+	0x29, 0x82, 0xff, 0xff, 0x00, 0x01, 0x2a, 0xa7, 
+	0x00, 0x00, 0x00, 0x05, 0x2a, 0xa8, 0x71, 0x41, 
+	0x20, 0x00, 0x20, 0x00, 0x00, 0x23, 0x04, 0x00, 
+	0x00, 0x0a, 0x2a, 0xad, 0x00, 0x00, 0x00, 0x00, 
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+	0x00, 0x0f, 0x2a, 0xb7, 0x00, 0x00, 0x00, 0x00, 
+	0x00, 0x00, 0x00, 0x40, 0x00, 0xa0, 0x82, 0x40, 
+	0x00, 0x08, 0x30, 0x7f, 0x00, 0x80, 0x01, 0x80, 
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+	0x00, 0x00, 0x00, 0x01, 0x27, 0x6e, 0x00, 0x00, 
+	0x00, 0x01, 0x27, 0x6f, 0x00, 0x00, 0x00, 0x00, 
+	0x00, 0x09, 0x00, 0x00, 0x1a, 0x83, 0x04, 0xe8, 
+	0x04, 0xcf, 0x04, 0xc5, 0x04, 0xba, 0x04, 0xb0, 
+	0x04, 0xac, 0x04, 0x9c, 0x04, 0x8c, 0x04, 0x81, 
+	0x00, 0x78, 0x00, 0x00, 0x01, 0x00, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xaa, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x02, 0x23, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x05, 0xe5, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x02, 0xb5, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x0e, 0x33, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, 
+	0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0x00, 0x00, 
+};
+
diff -Nru a/drivers/media/dvb/ttusb-dec/Kconfig b/drivers/media/dvb/ttusb-dec/Kconfig
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/ttusb-dec/Kconfig	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,24 @@
+config DVB_TTUSB_DEC
+	tristate "Technotrend/Hauppauge USB DEC2000-T devices"
+	depends on DVB_CORE && USB
+	help
+	  Support for external USB adapters designed by Technotrend and
+	  produced by Hauppauge, shipped under the brand name 'DEC2000-T'.
+
+          Even if these devices have a MPEG decoder built in, they transmit
+	  only compressed MPEG data over the USB 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.
+
+config DVB_TTUSB_DEC_FIRMWARE_FILE
+	string "Full pathname of dec2000t.bin firmware file"
+	depends on DVB_TTUSB_DEC
+	default "/etc/dvb/dec2000t.bin"
+	help
+	  The DEC2000-T requires a firmware in order to boot into a mode in
+	  which it is a slave to the PC.  The firmware file can obtained as
+	  follows:
+	    wget http://hauppauge.lightpath.net/de/dec215a.exe
+	    unzip -j dec215a.exe Software/Oem/STB/App/Boot/STB_PC_T.bin
+	    mv STB_PC_T.bin /etc/dvb/dec2000t.bin
diff -Nru a/drivers/media/dvb/ttusb-dec/Makefile b/drivers/media/dvb/ttusb-dec/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/ttusb-dec/Makefile	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,11 @@
+
+obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o dec2000_frontend.o
+
+EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
+
+host-progs	:= fdump
+
+$(obj)/ttusb_dec.o: $(obj)/dsp_dec2000.h
+
+$(obj)/dsp_dec2000.h: $(patsubst "%", %, $(CONFIG_DVB_TTUSB_DEC_FIRMWARE_FILE)) $(obj)/fdump
+	$(obj)/fdump $< dsp_dec2000 > $@
diff -Nru a/drivers/media/dvb/ttusb-dec/dec2000_frontend.c b/drivers/media/dvb/ttusb-dec/dec2000_frontend.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/ttusb-dec/dec2000_frontend.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,180 @@
+/*
+ * TTUSB DEC-2000-t Frontend
+ *
+ * Copyright (C) 2003 Alex Woods <linux-dvb@giblets.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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/init.h>
+#include <linux/module.h>
+
+#include "dvb_frontend.h"
+#include "dvb_functions.h"
+
+static int debug = 0;
+
+#define dprintk	if (debug) printk
+
+static struct dvb_frontend_info dec2000_frontend_info = {
+	name:			"TechnoTrend/Hauppauge DEC-2000-t Frontend",
+	type:			FE_OFDM,
+	frequency_min:		51000000,
+	frequency_max:		858000000,
+	frequency_stepsize:	62500,
+	caps:	FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+		FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+		FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+		FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+		FE_CAN_HIERARCHY_AUTO,
+};
+
+static int dec2000_frontend_ioctl(struct dvb_frontend *fe, unsigned int cmd,
+				  void *arg)
+{
+	dprintk("%s\n", __FUNCTION__);
+
+	switch (cmd) {
+
+	case FE_GET_INFO:
+		dprintk("%s: FE_GET_INFO\n", __FUNCTION__);
+		memcpy(arg, &dec2000_frontend_info,
+		       sizeof (struct dvb_frontend_info));
+		break;
+
+	case FE_READ_STATUS: {
+			fe_status_t *status = (fe_status_t *)arg;
+			dprintk("%s: FE_READ_STATUS\n", __FUNCTION__);
+			*status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
+				  FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
+			break;
+		}
+
+	case FE_READ_BER: {
+			u32 *ber = (u32 *)arg;
+			dprintk("%s: FE_READ_BER\n", __FUNCTION__);
+			*ber = 0;
+			return -ENOSYS;
+			break;
+		}
+
+	case FE_READ_SIGNAL_STRENGTH: {
+			dprintk("%s: FE_READ_SIGNAL_STRENGTH\n", __FUNCTION__);
+			*(s32 *)arg = 0xFF;
+			return -ENOSYS;
+			break;
+		}
+
+	case FE_READ_SNR:
+		dprintk("%s: FE_READ_SNR\n", __FUNCTION__);
+		*(s32 *)arg = 0;
+		return -ENOSYS;
+		break;
+
+	case FE_READ_UNCORRECTED_BLOCKS:
+		dprintk("%s: FE_READ_UNCORRECTED_BLOCKS\n", __FUNCTION__);
+		*(u32 *)arg = 0;
+		return -ENOSYS;
+		break;
+
+	case FE_SET_FRONTEND:{
+			struct dvb_frontend_parameters *p =
+				(struct dvb_frontend_parameters *)arg;
+			u8 b[] = { 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+				   0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+				   0x00, 0xff, 0x00, 0x00, 0x00, 0xff };
+			u32 freq;
+			struct i2c_msg msg = { addr: 0x71, flags: 0, len:20 };
+
+			dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__);
+
+			dprintk("            frequency->%d\n", p->frequency);
+			dprintk("            symbol_rate->%d\n",
+				p->u.qam.symbol_rate);
+			dprintk("            inversion->%d\n", p->inversion);
+
+			freq = htonl(p->frequency / 1000);
+			memcpy(&b[4], &freq, sizeof (int));
+			msg.buf = b;
+			fe->i2c->xfer(fe->i2c, &msg, 1);
+
+			break;
+		}
+
+	case FE_GET_FRONTEND:
+		dprintk("%s: FE_GET_FRONTEND\n", __FUNCTION__);
+		break;
+
+	case FE_SLEEP:
+		dprintk("%s: FE_SLEEP\n", __FUNCTION__);
+		return -ENOSYS;
+		break;
+
+	case FE_INIT:
+		dprintk("%s: FE_INIT\n", __FUNCTION__);
+		break;
+
+	case FE_RESET:
+		dprintk("%s: FE_RESET\n", __FUNCTION__);
+		break;
+
+	default:
+		dprintk("%s: unknown IOCTL (0x%X)\n", __FUNCTION__, cmd);
+		return -EINVAL;
+
+	}
+
+	return 0;
+}
+
+static int dec2000_frontend_attach(struct dvb_i2c_bus *i2c)
+{
+	dprintk("%s\n", __FUNCTION__);
+
+	dvb_register_frontend(dec2000_frontend_ioctl, i2c, NULL,
+			      &dec2000_frontend_info);
+
+	return 0;
+}
+
+static void dec2000_frontend_detach(struct dvb_i2c_bus *i2c)
+{
+	dprintk("%s\n", __FUNCTION__);
+
+	dvb_unregister_frontend(dec2000_frontend_ioctl, i2c);
+}
+
+static int __init dec2000_frontend_init(void)
+{
+	return dvb_register_i2c_device(THIS_MODULE, dec2000_frontend_attach,
+				       dec2000_frontend_detach);
+}
+
+static void __exit dec2000_frontend_exit(void)
+{
+	dvb_unregister_i2c_device(dec2000_frontend_attach);
+}
+
+module_init(dec2000_frontend_init);
+module_exit(dec2000_frontend_exit);
+
+MODULE_DESCRIPTION("TechnoTrend/Hauppauge DEC-2000-t Frontend");
+MODULE_AUTHOR("Alex Woods <linux-dvb@giblets.org");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug level");
+
diff -Nru a/drivers/media/dvb/ttusb-dec/fdump.c b/drivers/media/dvb/ttusb-dec/fdump.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/ttusb-dec/fdump.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+
+int main (int argc, char **argv)
+{
+	unsigned char buf[8];
+	unsigned int i, count, bytes = 0;
+	int fd;
+
+	if (argc != 3) {
+		fprintf (stderr, "\n\tusage: %s <ucode.bin> <array_name>\n\n",
+			 argv[0]);
+		return -1;
+	}
+
+	fd = open (argv[1], O_RDONLY);
+
+	printf ("\n#include <asm/types.h>\n\nu8 %s [] __initdata = {",
+		argv[2]);
+
+	while ((count = read (fd, buf, 8)) > 0) {
+		printf ("\n\t");
+		for (i=0;i<count;i++, bytes++)
+			printf ("0x%02x, ", buf[i]);
+	}
+
+	printf ("\n};\n\n");
+	close (fd);
+
+	return 0;
+}
+
diff -Nru a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,991 @@
+/*
+ * TTUSB DEC Driver
+ *
+ * Copyright (C) 2003 Alex Woods <linux-dvb@giblets.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include "ttusb_dec.h"
+#include "dvb_frontend.h"
+
+static int debug = 0;
+
+#define dprintk	if (debug) printk
+
+static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
+				  int param_length, const u8 params[],
+				  int *result_length, u8 cmd_result[])
+{
+	int result, actual_len, i;
+	u8 b[COMMAND_PACKET_SIZE + 4];
+	u8 c[COMMAND_PACKET_SIZE + 4];
+
+	dprintk("%s\n", __FUNCTION__);
+
+	if ((result = down_interruptible(&dec->usb_sem))) {
+		printk("%s: Failed to down usb semaphore.\n", __FUNCTION__);
+		return result;
+	}
+
+	b[0] = 0xaa;
+	b[1] = ++dec->trans_count;
+	b[2] = command;
+	b[3] = param_length;
+
+	if (params)
+		memcpy(&b[4], params, param_length);
+
+	if (debug) {
+		printk("%s: command: ", __FUNCTION__);
+		for (i = 0; i < param_length + 4; i++)
+			printk("0x%02X ", b[i]);
+		printk("\n");
+	}
+
+	result = usb_bulk_msg(dec->udev, dec->command_pipe, b, sizeof(b),
+			      &actual_len, HZ);
+
+	if (result) {
+		printk("%s: command bulk message failed: error %d\n",
+		       __FUNCTION__, result);
+		up(&dec->usb_sem);
+		return result;
+	}
+
+	result = usb_bulk_msg(dec->udev, dec->result_pipe, c, sizeof(c),
+			      &actual_len, HZ);
+
+	if (result) {
+		printk("%s: result bulk message failed: error %d\n",
+		       __FUNCTION__, result);
+		up(&dec->usb_sem);
+		return result;
+	} else {
+		if (debug) {
+			printk("%s: result: ", __FUNCTION__);
+			for (i = 0; i < actual_len; i++)
+				printk("0x%02X ", c[i]);
+			printk("\n");
+		}
+
+		if (result_length)
+			*result_length = c[3];
+		if (cmd_result && c[3] > 0)
+			memcpy(cmd_result, &c[4], c[3]);
+
+		up(&dec->usb_sem);
+
+		return 0;
+	}
+}
+
+static int ttusb_dec_av_pes2ts_cb(void *priv, unsigned char *data)
+{
+	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)priv;
+
+	dvbdmxfeed->cb.ts(data, 188, 0, 0, &dvbdmxfeed->feed.ts, DMX_OK);
+
+	return 0;
+}
+
+static void ttusb_dec_set_pids(struct ttusb_dec *dec)
+{
+	u8 b[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+		   0xff, 0xff };
+
+	u16 pcr = htons(dec->pid[DMX_PES_PCR]);
+	u16 audio = htons(dec->pid[DMX_PES_AUDIO]);
+	u16 video = htons(dec->pid[DMX_PES_VIDEO]);
+
+	dprintk("%s\n", __FUNCTION__);
+
+	memcpy(&b[0], &pcr, 2);
+	memcpy(&b[2], &audio, 2);
+	memcpy(&b[4], &video, 2);
+
+	ttusb_dec_send_command(dec, 0x50, sizeof(b), b, NULL, NULL);
+
+	if (!down_interruptible(&dec->pes2ts_sem)) {
+		dvb_filter_pes2ts_init(&dec->a_pes2ts, dec->pid[DMX_PES_AUDIO],
+				       ttusb_dec_av_pes2ts_cb, dec->demux.feed);
+		dvb_filter_pes2ts_init(&dec->v_pes2ts, dec->pid[DMX_PES_VIDEO],
+				       ttusb_dec_av_pes2ts_cb, dec->demux.feed);
+
+		up(&dec->pes2ts_sem);
+	}
+}
+
+static int ttusb_dec_i2c_master_xfer(struct dvb_i2c_bus *i2c,
+				     const struct i2c_msg msgs[], int num)
+{
+	int result, i;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	for (i = 0; i < num; i++)
+		if ((result = ttusb_dec_send_command(i2c->data, msgs[i].addr,
+						     msgs[i].len, msgs[i].buf,
+						     NULL, NULL)))
+			return result;
+
+	return 0;
+}
+
+static void ttusb_dec_process_av_pes(struct ttusb_dec * dec, u8 * av_pes,
+				     int length)
+{
+	int i;
+	u16 csum = 0;
+	u8 c;
+
+	if (length < 16) {
+		printk("%s: packet too short.\n", __FUNCTION__);
+		return;
+	}
+
+	for (i = 0; i < length; i += 2) {
+		csum ^= le16_to_cpup((u16 *)(av_pes + i));
+		c = av_pes[i];
+		av_pes[i] = av_pes[i + 1];
+		av_pes[i + 1] = c;
+	}
+
+	if (csum) {
+		printk("%s: checksum failed.\n", __FUNCTION__);
+		return;
+	}
+
+	if (length > 8 + MAX_AV_PES_LENGTH + 4) {
+		printk("%s: packet too long.\n", __FUNCTION__);
+		return;
+	}
+
+	if (!(av_pes[0] == 'A' && av_pes[1] == 'V')) {
+		printk("%s: invalid AV_PES packet.\n", __FUNCTION__);
+		return;
+	}
+
+	switch (av_pes[2]) {
+
+	case 0x01: {		/* VideoStream */
+			int prebytes = av_pes[5] & 0x03;
+			int postbytes = (av_pes[5] & 0x0c) >> 2;
+			u16 v_pes_payload_length;
+
+			if (dec->v_pes_postbytes > 0 &&
+			    dec->v_pes_postbytes == prebytes) {
+				memcpy(&dec->v_pes[dec->v_pes_length],
+				       &av_pes[12], prebytes);
+
+				if (!down_interruptible(&dec->pes2ts_sem)) {
+					dvb_filter_pes2ts(&dec->v_pes2ts,
+							  dec->v_pes,
+							  dec->v_pes_length +
+							  prebytes);
+
+					up(&dec->pes2ts_sem);
+				}
+			}
+
+			if (av_pes[5] & 0x10) {
+				dec->v_pes[7] = 0x80;
+				dec->v_pes[8] = 0x05;
+
+				dec->v_pes[9] = 0x21 |
+						((av_pes[8] & 0xc0) >> 5);
+				dec->v_pes[10] = ((av_pes[8] & 0x3f) << 2) |
+						 ((av_pes[9] & 0xc0) >> 6);
+				dec->v_pes[11] = 0x01 |
+						 ((av_pes[9] & 0x3f) << 2) |
+						 ((av_pes[10] & 0x80) >> 6);
+				dec->v_pes[12] = ((av_pes[10] & 0x7f) << 1) |
+						 ((av_pes[11] & 0xc0) >> 7);
+				dec->v_pes[13] = 0x01 |
+						 ((av_pes[11] & 0x7f) << 1);
+
+				memcpy(&dec->v_pes[14], &av_pes[12 + prebytes],
+				       length - 16 - prebytes);
+				dec->v_pes_length = 14 + length - 16 - prebytes;
+			} else {
+				dec->v_pes[7] = 0x00;
+				dec->v_pes[8] = 0x00;
+
+				memcpy(&dec->v_pes[9], &av_pes[8], length - 12);
+				dec->v_pes_length = 9 + length - 12;
+			}
+
+			dec->v_pes_postbytes = postbytes;
+
+			if (dec->v_pes[9 + dec->v_pes[8]] == 0x00 &&
+			    dec->v_pes[10 + dec->v_pes[8]] == 0x00 &&
+			    dec->v_pes[11 + dec->v_pes[8]] == 0x01)
+				dec->v_pes[6] = 0x84;
+			else
+				dec->v_pes[6] = 0x80;
+
+			v_pes_payload_length = htons(dec->v_pes_length - 6 +
+						     postbytes);
+			memcpy(&dec->v_pes[4], &v_pes_payload_length, 2);
+
+			if (postbytes == 0) {
+				if (!down_interruptible(&dec->pes2ts_sem)) {
+					dvb_filter_pes2ts(&dec->v_pes2ts,
+							  dec->v_pes,
+							  dec->v_pes_length);
+
+					up(&dec->pes2ts_sem);
+				}
+			}
+
+			break;
+		}
+
+	case 0x02:		/* MainAudioStream */
+		dvb_filter_pes2ts(&dec->a_pes2ts, &av_pes[8], length - 12);
+		break;
+
+	default:
+		printk("%s: unknown AV_PES type: %02x.\n", __FUNCTION__,
+		       av_pes[2]);
+		break;
+
+	}
+}
+
+static void ttusb_dec_process_urb_frame(struct ttusb_dec * dec, u8 * b,
+					int length)
+{
+	while (length) {
+		switch (dec->av_pes_state) {
+
+		case 0:
+		case 1:
+		case 3:
+			if (*b++ == 0xaa) {
+				dec->av_pes_state++;
+				if (dec->av_pes_state == 4)
+					dec->av_pes_length = 0;
+			} else {
+				dec->av_pes_state = 0;
+			}
+
+			length--;
+			break;
+
+		case 2:
+			if (*b++ == 0x00) {
+				dec->av_pes_state++;
+			} else {
+				dec->av_pes_state = 0;
+			}
+
+			length--;
+			break;
+
+		case 4:
+			dec->av_pes[dec->av_pes_length++] = *b++;
+
+			if (dec->av_pes_length == 8) {
+				dec->av_pes_state++;
+				dec->av_pes_payload_length = le16_to_cpup(
+						(u16 *)(dec->av_pes + 6));
+			}
+
+			length--;
+			break;
+
+		case 5: {
+				int remainder = dec->av_pes_payload_length +
+						8 - dec->av_pes_length;
+
+				if (length >= remainder) {
+					memcpy(dec->av_pes + dec->av_pes_length,
+					       b, remainder);
+					dec->av_pes_length += remainder;
+					b += remainder;
+					length -= remainder;
+					dec->av_pes_state++;
+				} else {
+					memcpy(&dec->av_pes[dec->av_pes_length],
+					       b, length);
+					dec->av_pes_length += length;
+					length = 0;
+				}
+
+				break;
+			}
+
+		case 6:
+			dec->av_pes[dec->av_pes_length++] = *b++;
+
+			if (dec->av_pes_length ==
+			    8 + dec->av_pes_payload_length + 4) {
+				ttusb_dec_process_av_pes(dec, dec->av_pes,
+							 dec->av_pes_length);
+				dec->av_pes_state = 0;
+			}
+
+			length--;
+			break;
+
+		default:
+			printk("%s: illegal packet state encountered.\n",
+			       __FUNCTION__);
+			dec->av_pes_state = 0;
+
+		}
+
+	}
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+static void ttusb_dec_process_urb(struct urb *urb)
+#else
+static void ttusb_dec_process_urb(struct urb *urb, struct pt_regs *ptregs)
+#endif
+{
+	struct ttusb_dec *dec = urb->context;
+
+	if (!urb->status) {
+		int i;
+
+		for (i = 0; i < FRAMES_PER_ISO_BUF; i++) {
+			struct usb_iso_packet_descriptor *d;
+			u8 *b;
+			int length;
+
+			d = &urb->iso_frame_desc[i];
+			b = urb->transfer_buffer + d->offset;
+			length = d->actual_length;
+
+			ttusb_dec_process_urb_frame(dec, b, length);
+		}
+	} else {
+		 /* -ENOENT is expected when unlinking urbs */
+		if (urb->status != -ENOENT)
+			dprintk("%s: urb error: %d\n", __FUNCTION__,
+				urb->status);
+	}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	if (dec->iso_stream_count)
+		usb_submit_urb(urb, GFP_KERNEL);
+#endif
+}
+
+static void ttusb_dec_setup_urbs(struct ttusb_dec *dec)
+{
+	int i, j, buffer_offset = 0;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	for (i = 0; i < ISO_BUF_COUNT; i++) {
+		int frame_offset = 0;
+		struct urb *urb = dec->iso_urb[i];
+
+		urb->dev = dec->udev;
+		urb->context = dec;
+		urb->complete = ttusb_dec_process_urb;
+		urb->pipe = dec->stream_pipe;
+		urb->transfer_flags = URB_ISO_ASAP;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+		urb->interval = 1;
+#endif
+		urb->number_of_packets = FRAMES_PER_ISO_BUF;
+		urb->transfer_buffer_length = ISO_FRAME_SIZE *
+					      FRAMES_PER_ISO_BUF;
+		urb->transfer_buffer = dec->iso_buffer + buffer_offset;
+		buffer_offset += ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF;
+
+		for (j = 0; j < FRAMES_PER_ISO_BUF; j++) {
+			urb->iso_frame_desc[j].offset = frame_offset;
+			urb->iso_frame_desc[j].length = ISO_FRAME_SIZE;
+			frame_offset += ISO_FRAME_SIZE;
+		}
+	}
+}
+
+static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec)
+{
+	int i;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	if (down_interruptible(&dec->iso_sem))
+		return;
+
+	dec->iso_stream_count--;
+
+	if (!dec->iso_stream_count) {
+		u8 b0[] = { 0x00 };
+
+		for (i = 0; i < ISO_BUF_COUNT; i++)
+			usb_unlink_urb(dec->iso_urb[i]);
+
+		ttusb_dec_send_command(dec, 0x81, sizeof(b0), b0, NULL, NULL);
+	}
+
+	up(&dec->iso_sem);
+}
+
+/* Setting the interface of the DEC tends to take down the USB communications
+ * for a short period, so it's important not to call this function just before
+ * trying to talk to it.
+ */
+static void ttusb_dec_set_streaming_interface(struct ttusb_dec *dec)
+{
+	if (!dec->interface) {
+		usb_set_interface(dec->udev, 0, 8);
+		dec->interface = 8;
+	}
+}
+
+static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
+{
+	int i, result;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	if (down_interruptible(&dec->iso_sem))
+		return -EAGAIN;
+
+	if (!dec->iso_stream_count) {
+		u8 b0[] = { 0x05 };
+
+		ttusb_dec_send_command(dec, 0x80, sizeof(b0), b0, NULL, NULL);
+
+		ttusb_dec_setup_urbs(dec);
+
+		for (i = 0; i < ISO_BUF_COUNT; i++) {
+			if ((result = usb_submit_urb(dec->iso_urb[i]
+						    , GFP_KERNEL))) {
+				printk("%s: failed urb submission %d: "
+				       "error %d\n", __FUNCTION__, i, result);
+
+				while (i) {
+					usb_unlink_urb(dec->iso_urb[i - 1]);
+					i--;
+				}
+
+				up(&dec->iso_sem);
+				return result;
+			}
+		}
+
+		dec->av_pes_state = 0;
+		dec->v_pes_postbytes = 0;
+	}
+
+	dec->iso_stream_count++;
+
+	up(&dec->iso_sem);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	ttusb_dec_set_streaming_interface(dec);
+#endif
+
+	return 0;
+}
+
+static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	struct ttusb_dec *dec = dvbdmx->priv;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	if (!dvbdmx->dmx.frontend)
+		return -EINVAL;
+
+	dprintk("  pid: 0x%04X\n", dvbdmxfeed->pid);
+
+	switch (dvbdmxfeed->type) {
+
+	case DMX_TYPE_TS:
+		dprintk("  type: DMX_TYPE_TS\n");
+		break;
+
+	case DMX_TYPE_SEC:
+		dprintk("  type: DMX_TYPE_SEC\n");
+		break;
+
+	default:
+		dprintk("  type: unknown (%d)\n", dvbdmxfeed->type);
+		return -EINVAL;
+
+	}
+
+	dprintk("  ts_type:");
+
+	if (dvbdmxfeed->ts_type & TS_DECODER)
+		dprintk(" TS_DECODER");
+
+	if (dvbdmxfeed->ts_type & TS_PACKET)
+		dprintk(" TS_PACKET");
+
+	if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)
+		dprintk(" TS_PAYLOAD_ONLY");
+
+	dprintk("\n");
+
+	switch (dvbdmxfeed->pes_type) {
+
+	case DMX_TS_PES_VIDEO:
+		dprintk("  pes_type: DMX_TS_PES_VIDEO\n");
+		dec->pid[DMX_PES_PCR] = dvbdmxfeed->pid;
+		dec->pid[DMX_PES_VIDEO] = dvbdmxfeed->pid;
+		ttusb_dec_set_pids(dec);
+		break;
+
+	case DMX_TS_PES_AUDIO:
+		dprintk("  pes_type: DMX_TS_PES_AUDIO\n");
+		dec->pid[DMX_PES_AUDIO] = dvbdmxfeed->pid;
+		ttusb_dec_set_pids(dec);
+		break;
+
+	case DMX_TS_PES_TELETEXT:
+		dec->pid[DMX_PES_TELETEXT] = dvbdmxfeed->pid;
+		dprintk("  pes_type: DMX_TS_PES_TELETEXT\n");
+		break;
+
+	case DMX_TS_PES_PCR:
+		dprintk("  pes_type: DMX_TS_PES_PCR\n");
+		dec->pid[DMX_PES_PCR] = dvbdmxfeed->pid;
+		ttusb_dec_set_pids(dec);
+		break;
+
+	case DMX_TS_PES_OTHER:
+		dprintk("  pes_type: DMX_TS_PES_OTHER\n");
+		break;
+
+	default:
+		dprintk("  pes_type: unknown (%d)\n", dvbdmxfeed->pes_type);
+		return -EINVAL;
+
+	}
+
+	ttusb_dec_start_iso_xfer(dec);
+
+	return 0;
+}
+
+static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct ttusb_dec *dec = dvbdmxfeed->demux->priv;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	ttusb_dec_stop_iso_xfer(dec);
+
+	return 0;
+}
+
+static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec)
+{
+	int i;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	for (i = 0; i < ISO_BUF_COUNT; i++)
+		if (dec->iso_urb[i])
+			usb_free_urb(dec->iso_urb[i]);
+
+	pci_free_consistent(NULL,
+			    ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF *
+					      ISO_BUF_COUNT),
+			    dec->iso_buffer, dec->iso_dma_handle);
+}
+
+static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec)
+{
+	int i;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	dec->iso_buffer = pci_alloc_consistent(NULL,
+					       ISO_FRAME_SIZE *
+					       (FRAMES_PER_ISO_BUF *
+						ISO_BUF_COUNT),
+				 	       &dec->iso_dma_handle);
+
+	memset(dec->iso_buffer, 0,
+	       sizeof(ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT)));
+
+	for (i = 0; i < ISO_BUF_COUNT; i++) {
+		struct urb *urb;
+
+		if (!(urb = usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_KERNEL))) {
+			ttusb_dec_free_iso_urbs(dec);
+			return -ENOMEM;
+		}
+
+		dec->iso_urb[i] = urb;
+	}
+
+	ttusb_dec_setup_urbs(dec);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	for (i = 0; i < ISO_BUF_COUNT; i++) {
+		int next = (i + 1) % ISO_BUF_COUNT;
+		dec->iso_urb[i]->next = dec->iso_urb[next];
+	}
+#endif
+
+	return 0;
+}
+
+static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
+{
+	dprintk("%s\n", __FUNCTION__);
+
+	dec->v_pes[0] = 0x00;
+	dec->v_pes[1] = 0x00;
+	dec->v_pes[2] = 0x01;
+	dec->v_pes[3] = 0xe0;
+}
+
+static void ttusb_dec_init_usb(struct ttusb_dec *dec)
+{
+	dprintk("%s\n", __FUNCTION__);
+
+	sema_init(&dec->usb_sem, 1);
+	sema_init(&dec->iso_sem, 1);
+
+	dec->command_pipe = usb_sndbulkpipe(dec->udev, COMMAND_PIPE);
+	dec->result_pipe = usb_rcvbulkpipe(dec->udev, RESULT_PIPE);
+	dec->stream_pipe = usb_rcvisocpipe(dec->udev, STREAM_PIPE);
+
+	ttusb_dec_alloc_iso_urbs(dec);
+}
+
+#include "dsp_dec2000.h"
+
+static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
+{
+	int i, j, actual_len, result, size, trans_count;
+	u8 b0[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xc8, 0x61,
+		    0x00 };
+	u8 b1[] = { 0x61 };
+	u8 b[ARM_PACKET_SIZE];
+	u32 dsp_length = htonl(sizeof(dsp_dec2000));
+
+	dprintk("%s\n", __FUNCTION__);
+
+	memcpy(b0, &dsp_length, 4);
+
+	result = ttusb_dec_send_command(dec, 0x41, sizeof(b0), b0, NULL, NULL);
+
+	if (result)
+		return result;
+
+	trans_count = 0;
+	j = 0;
+
+	for (i = 0; i < sizeof(dsp_dec2000); i += COMMAND_PACKET_SIZE) {
+		size = sizeof(dsp_dec2000) - i;
+		if (size > COMMAND_PACKET_SIZE)
+			size = COMMAND_PACKET_SIZE;
+
+		b[j + 0] = 0xaa;
+		b[j + 1] = trans_count++;
+		b[j + 2] = 0xf0;
+		b[j + 3] = size;
+		memcpy(&b[j + 4], &dsp_dec2000[i], size);
+
+		j += COMMAND_PACKET_SIZE + 4;
+
+		if (j >= ARM_PACKET_SIZE) {
+			result = usb_bulk_msg(dec->udev, dec->command_pipe, b,
+					      ARM_PACKET_SIZE, &actual_len,
+					      HZ / 10);
+			j = 0;
+		} else if (size < COMMAND_PACKET_SIZE) {
+			result = usb_bulk_msg(dec->udev, dec->command_pipe, b,
+					      j - COMMAND_PACKET_SIZE + size,
+					      &actual_len, HZ / 10);
+		}
+	}
+
+	result = ttusb_dec_send_command(dec, 0x43, sizeof(b1), b1, NULL, NULL);
+
+	return result;
+}
+
+static void ttusb_dec_init_stb(struct ttusb_dec *dec)
+{
+	u8 c[COMMAND_PACKET_SIZE];
+	int c_length;
+	int result;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	result = ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c);
+
+	if (!result)
+		if (c_length != 0x0c || (c_length == 0x0c && c[9] != 0x63))
+			ttusb_dec_boot_dsp(dec);
+}
+
+static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
+{
+	int result;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	if ((result = dvb_register_adapter(&dec->adapter, "dec2000")) < 0) {
+		printk("%s: dvb_register_adapter failed: error %d\n",
+		       __FUNCTION__, result);
+
+		return result;
+	}
+
+	if (!(dec->i2c_bus = dvb_register_i2c_bus(ttusb_dec_i2c_master_xfer,
+						  dec, dec->adapter, 0))) {
+		printk("%s: dvb_register_i2c_bus failed\n", __FUNCTION__);
+
+		dvb_unregister_adapter(dec->adapter);
+
+		return -ENOMEM;
+	}
+
+	dec->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
+
+	dec->demux.priv = (void *)dec;
+	dec->demux.filternum = 31;
+	dec->demux.feednum = 31;
+	dec->demux.start_feed = ttusb_dec_start_feed;
+	dec->demux.stop_feed = ttusb_dec_stop_feed;
+	dec->demux.write_to_decoder = NULL;
+
+	if ((result = dvb_dmx_init(&dec->demux)) < 0) {
+		printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
+		       result);
+
+		dvb_unregister_i2c_bus(ttusb_dec_i2c_master_xfer, dec->adapter,
+				       0);
+		dvb_unregister_adapter(dec->adapter);
+
+		return result;
+	}
+
+	dec->dmxdev.filternum = 32;
+	dec->dmxdev.demux = &dec->demux.dmx;
+	dec->dmxdev.capabilities = 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_i2c_bus(ttusb_dec_i2c_master_xfer, dec->adapter,
+				       0);
+		dvb_unregister_adapter(dec->adapter);
+
+		return result;
+	}
+
+	dec->frontend.source = DMX_FRONTEND_0;
+
+	if ((result = dec->demux.dmx.add_frontend(&dec->demux.dmx,
+						  &dec->frontend)) < 0) {
+		printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
+		       result);
+
+		dvb_dmxdev_release(&dec->dmxdev);
+		dvb_dmx_release(&dec->demux);
+		dvb_unregister_i2c_bus(ttusb_dec_i2c_master_xfer, dec->adapter,
+				       0);
+		dvb_unregister_adapter(dec->adapter);
+
+		return result;
+	}
+
+	if ((result = dec->demux.dmx.connect_frontend(&dec->demux.dmx,
+						      &dec->frontend)) < 0) {
+		printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
+		       result);
+
+		dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
+		dvb_dmxdev_release(&dec->dmxdev);
+		dvb_dmx_release(&dec->demux);
+		dvb_unregister_i2c_bus(ttusb_dec_i2c_master_xfer, dec->adapter,
+				       0);
+		dvb_unregister_adapter(dec->adapter);
+
+		return result;
+	}
+
+	sema_init(&dec->pes2ts_sem, 1);
+
+	dvb_net_init(dec->adapter, &dec->dvb_net, &dec->demux.dmx);
+
+	return 0;
+}
+
+static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
+{
+	dprintk("%s\n", __FUNCTION__);
+
+	dvb_net_release(&dec->dvb_net);
+	dec->demux.dmx.close(&dec->demux.dmx);
+	dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
+	dvb_dmxdev_release(&dec->dmxdev);
+	dvb_dmx_release(&dec->demux);
+	dvb_unregister_i2c_bus(ttusb_dec_i2c_master_xfer, dec->adapter, 0);
+	dvb_unregister_adapter(dec->adapter);
+}
+
+static void ttusb_dec_exit_usb(struct ttusb_dec *dec)
+{
+	int i;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	dec->iso_stream_count = 0;
+
+	for (i = 0; i < ISO_BUF_COUNT; i++)
+		usb_unlink_urb(dec->iso_urb[i]);
+
+	ttusb_dec_free_iso_urbs(dec);
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+static void *ttusb_dec_probe(struct usb_device *udev, unsigned int ifnum,
+			     const struct usb_device_id *id)
+{
+	struct ttusb_dec *dec;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	if (ifnum != 0)
+		return NULL;
+
+	if (!(dec = kmalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) {
+		printk("%s: couldn't allocate memory.\n", __FUNCTION__);
+		return NULL;
+	}
+
+	memset(dec, 0, sizeof(struct ttusb_dec));
+
+	dec->udev = udev;
+
+	ttusb_dec_init_usb(dec);
+	ttusb_dec_init_stb(dec);
+	ttusb_dec_init_dvb(dec);
+	ttusb_dec_init_v_pes(dec);
+
+	return (void *)dec;
+}
+#else
+static int ttusb_dec_probe(struct usb_interface *intf,
+			   const struct usb_device_id *id)
+{
+	struct usb_device *udev;
+	struct ttusb_dec *dec;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	udev = interface_to_usbdev(intf);
+
+	if (!(dec = kmalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) {
+		printk("%s: couldn't allocate memory.\n", __FUNCTION__);
+		return -ENOMEM;
+	}
+
+	memset(dec, 0, sizeof(struct ttusb_dec));
+
+	dec->udev = udev;
+
+	ttusb_dec_init_usb(dec);
+	ttusb_dec_init_stb(dec);
+	ttusb_dec_init_dvb(dec);
+	ttusb_dec_init_v_pes(dec);
+
+	usb_set_intfdata(intf, (void *)dec);
+	ttusb_dec_set_streaming_interface(dec);
+
+	return 0;
+}
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+static void ttusb_dec_disconnect(struct usb_device *udev, void *data)
+{
+	struct ttusb_dec *dec = data;
+#else
+static void ttusb_dec_disconnect(struct usb_interface *intf)
+{
+	struct ttusb_dec *dec = usb_get_intfdata(intf);
+
+	usb_set_intfdata(intf, NULL);
+#endif
+
+	dprintk("%s\n", __FUNCTION__);
+
+	ttusb_dec_exit_usb(dec);
+	ttusb_dec_exit_dvb(dec);
+
+	kfree(dec);
+}
+
+static struct usb_device_id ttusb_dec_table[] = {
+	{USB_DEVICE(0x0b48, 0x1006)},	/* Unconfirmed */
+	{USB_DEVICE(0x0b48, 0x1007)},	/* Unconfirmed */
+	{USB_DEVICE(0x0b48, 0x1008)},	/* DEC 2000 t */
+	{}
+};
+
+static struct usb_driver ttusb_dec_driver = {
+      name:		DRIVER_NAME,
+      probe:		ttusb_dec_probe,
+      disconnect:	ttusb_dec_disconnect,
+      id_table:		ttusb_dec_table,
+};
+
+static int __init ttusb_dec_init(void)
+{
+	int result;
+
+	if ((result = usb_register(&ttusb_dec_driver)) < 0) {
+		printk("%s: initialisation failed: error %d.\n", __FUNCTION__,
+		       result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit ttusb_dec_exit(void)
+{
+	usb_deregister(&ttusb_dec_driver);
+}
+
+module_init(ttusb_dec_init);
+module_exit(ttusb_dec_exit);
+
+MODULE_AUTHOR("Alex Woods <linux-dvb@giblets.org>");
+MODULE_DESCRIPTION(DRIVER_NAME);
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(usb, ttusb_dec_table);
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug level");
diff -Nru a/drivers/media/dvb/ttusb-dec/ttusb_dec.h b/drivers/media/dvb/ttusb-dec/ttusb_dec.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,87 @@
+/*
+ * TTUSB DEC Driver
+ *
+ * Copyright (C) 2003 Alex Woods <linux-dvb@giblets.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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 _TTUSB_DEC_H
+#define _TTUSB_DEC_H
+
+#include "asm/semaphore.h"
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_filter.h"
+#include "dvb_i2c.h"
+#include "dvb_net.h"
+
+#define DRIVER_NAME		"TechnoTrend/Hauppauge DEC USB"
+
+#define COMMAND_PIPE		0x03
+#define RESULT_PIPE		0x84
+#define STREAM_PIPE		0x88
+
+#define COMMAND_PACKET_SIZE	0x3c
+#define ARM_PACKET_SIZE		0x1000
+
+#define ISO_BUF_COUNT		0x04
+#define FRAMES_PER_ISO_BUF	0x04
+#define ISO_FRAME_SIZE		0x0380
+
+#define	MAX_AV_PES_LENGTH	6144
+
+struct ttusb_dec {
+	/* DVB bits */
+	struct dvb_adapter	*adapter;
+	struct dmxdev		dmxdev;
+	struct dvb_demux	demux;
+	struct dmx_frontend	frontend;
+	struct dvb_i2c_bus	*i2c_bus;
+	struct dvb_net		dvb_net;
+
+	u16			pid[DMX_PES_OTHER];
+
+	/* USB bits */
+	struct usb_device	*udev;
+	u8			trans_count;
+	unsigned int		command_pipe;
+	unsigned int		result_pipe;
+	unsigned int		stream_pipe;
+	int			interface;
+	struct semaphore	usb_sem;
+
+	void			*iso_buffer;
+	dma_addr_t		iso_dma_handle;
+	struct urb		*iso_urb[ISO_BUF_COUNT];
+	int			iso_stream_count;
+	struct semaphore	iso_sem;
+
+	u8			av_pes[MAX_AV_PES_LENGTH + 4];
+	int			av_pes_state;
+	int			av_pes_length;
+	int			av_pes_payload_length;
+
+	struct dvb_filter_pes2ts	a_pes2ts;
+	struct dvb_filter_pes2ts	v_pes2ts;
+	struct semaphore		pes2ts_sem;
+
+	u8			v_pes[16 + MAX_AV_PES_LENGTH];
+	int			v_pes_length;
+	int			v_pes_postbytes;
+};
+
+#endif
diff -Nru a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
--- a/drivers/media/video/Kconfig	Sat Jul 19 12:54:29 2003
+++ b/drivers/media/video/Kconfig	Sat Jul 19 12:54:29 2003
@@ -257,5 +257,30 @@
 	  whenever you want). If you want to compile it as a module, say M
 	  here and read <file:Documentation/modules.txt>.
 
+config VIDEO_HEXIUM_ORION
+	tristate "Hexium HV-PCI6 and Orion frame grabber"
+	depends on VIDEO_DEV && PCI
+	---help---
+	  This is a video4linux driver for the Hexium HV-PCI6 and
+	  Orion frame grabber cards by Hexium.
+	  
+	  This driver is available as a module called hexium_orion
+	  ( = code which can be inserted in and removed from the
+	  running kernel whenever you want). If you want to compile
+	  it as a module, say M here and read <file:Documentation/modules.txt>.
+
+config VIDEO_HEXIUM_GEMINI
+	tristate "Hexium Gemini frame grabber"
+	depends on VIDEO_DEV && PCI
+	---help---
+	  This is a video4linux driver for the Hexium Gemini frame
+	  grabber card by Hexium. Please note that the Gemini Dual
+	  card is *not* fully supported.
+	  
+	  This driver is available as a module called hexium_gemini
+	  ( = code which can be inserted in and removed from the
+	  running kernel whenever you want). If you want to compile
+	  it as a module, say M here and read <file:Documentation/modules.txt>.
+
 endmenu
 
diff -Nru a/drivers/media/video/Makefile b/drivers/media/video/Makefile
--- a/drivers/media/video/Makefile	Sat Jul 19 12:54:24 2003
+++ b/drivers/media/video/Makefile	Sat Jul 19 12:54:24 2003
@@ -31,6 +31,8 @@
 obj-$(CONFIG_VIDEO_MEYE) += meye.o
 obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
 obj-$(CONFIG_VIDEO_MXB) += saa7111.o tuner.o tda9840.o tea6415c.o tea6420.o mxb.o
+obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
+obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
 obj-$(CONFIG_VIDEO_DPC) += saa7111.o dpc7146.o
 obj-$(CONFIG_TUNER_3036) += tuner-3036.o
 
diff -Nru a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c
--- a/drivers/media/video/dpc7146.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/media/video/dpc7146.c	Sat Jul 19 12:54:24 2003
@@ -173,6 +173,8 @@
 	return 0;
 }
 
+static struct saa7146_ext_vv vv_data;
+
 /* this function only gets called when the probing was successful */
 static int dpc_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
 {
@@ -183,7 +185,7 @@
 	/* checking for i2c-devices can be omitted here, because we
 	   already did this in "dpc_vl42_probe" */
 
-	saa7146_vv_init(dev);
+	saa7146_vv_init(dev,&vv_data);
 	if( 0 != saa7146_register_device(&dpc->video_dev, dev, "dpc", VFL_TYPE_GRABBER)) {
 		ERR(("cannot register capture v4l2 device. skipping.\n"));
 		return -1;
@@ -246,8 +248,9 @@
 }
 #endif
 
-static int dpc_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) 
+static int dpc_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) 
 {
+	struct saa7146_dev *dev = fh->dev;
 	struct dpc* dpc = (struct dpc*)dev->ext_priv;
 /*
 	struct saa7146_vv *vv = dev->vv_data; 
@@ -307,23 +310,32 @@
 }
 
 static struct saa7146_standard standard[] = {
-	{ "PAL-BG",	V4L2_STD_PAL_BG,	SAA7146_PAL_VALUES },
-	{ "PAL-I",	V4L2_STD_PAL_I,		SAA7146_PAL_VALUES },
-	{ "NTSC",	V4L2_STD_NTSC,		SAA7146_NTSC_VALUES },
-	{ "SECAM", 	V4L2_STD_SECAM,		SAA7146_SECAM_VALUES },
+	{
+		.name	= "PAL", 	.id	= V4L2_STD_PAL,
+		.v_offset	= 0x17,	.v_field 	= 288,	.v_calc		= 576,
+		.h_offset	= 0x14,	.h_pixels 	= 680,	.h_calc		= 680+1,
+		.v_max_out	= 576,	.h_max_out	= 768,
+	}, {
+		.name	= "NTSC", 	.id	= V4L2_STD_NTSC,
+		.v_offset	= 0x16,	.v_field 	= 240,	.v_calc		= 480,
+		.h_offset	= 0x06,	.h_pixels 	= 708,	.h_calc		= 708+1,
+		.v_max_out	= 480,	.h_max_out	= 640,
+	}, {
+		.name	= "SECAM", 	.id	= V4L2_STD_SECAM,
+		.v_offset	= 0x14,	.v_field 	= 288,	.v_calc		= 576,
+		.h_offset	= 0x14,	.h_pixels 	= 720,	.h_calc		= 720+1,
+		.v_max_out	= 576,	.h_max_out	= 768,
+	}
 };
 
-static
-struct saa7146_extension extension;
+static struct saa7146_extension extension;
 
-static
-struct saa7146_pci_extension_data dpc = {
+static struct saa7146_pci_extension_data dpc = {
         .ext_priv = "Multimedia eXtension Board",
         .ext = &extension,
 };
 
-static
-struct pci_device_id pci_tbl[] = {
+static struct pci_device_id pci_tbl[] = {
 	{
 		.vendor    = PCI_VENDOR_ID_PHILIPS,
 		.device	   = PCI_DEVICE_ID_PHILIPS_SAA7146,
@@ -337,8 +349,7 @@
 
 MODULE_DEVICE_TABLE(pci, pci_tbl);
 
-static
-struct saa7146_ext_vv vv_data = {
+static struct saa7146_ext_vv vv_data = {
 	.inputs		= DPC_INPUTS,
 	.capabilities	= V4L2_CAP_VBI_CAPTURE,
 	.stds		= &standard[0],
@@ -348,14 +359,12 @@
 	.ioctl		= dpc_ioctl,
 };
 
-static
-struct saa7146_extension extension = {
+static struct saa7146_extension extension = {
 	.name		= "dpc7146 demonstration board",
 	.flags		= SAA7146_USE_I2C_IRQ,
 	
 	.pci_tbl	= &pci_tbl[0],
 	.module		= THIS_MODULE,
-	.ext_vv_data	= &vv_data,
 
 	.probe		= dpc_probe,
 	.attach		= dpc_attach,
diff -Nru a/drivers/media/video/hexium.h b/drivers/media/video/hexium.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/video/hexium.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,51 @@
+#ifndef __HEXIUM__
+#define __HEXIUM__
+
+#define HEXIUM_HV_PCI6_ORION		1
+#define HEXIUM_ORION_1SVHS_3BNC		2
+#define HEXIUM_ORION_4BNC		3
+#define HEXIUM_GEMUINI			4
+#define HEXIUM_GEMUINI_DUAL		5
+
+static struct saa7146_standard hexium_standards[] = {
+	{
+		.name	= "PAL", 	.id	= V4L2_STD_PAL,
+		.v_offset	= 0x17,	.v_field 	= 288,	.v_calc		= 576,
+		.h_offset	= 0x14,	.h_pixels 	= 680,	.h_calc		= 680+1,
+		.v_max_out	= 576,	.h_max_out	= 768,
+	}, {
+		.name	= "NTSC", 	.id	= V4L2_STD_NTSC,
+		.v_offset	= 0x17,	.v_field 	= 240,	.v_calc		= 480,
+		.h_offset	= 0x06,	.h_pixels 	= 640,	.h_calc		= 641+1,
+		.v_max_out	= 480,	.h_max_out	= 640,
+	}, {
+		.name	= "SECAM", 	.id	= V4L2_STD_SECAM,
+		.v_offset	= 0x14,	.v_field 	= 288,	.v_calc		= 576,
+		.h_offset	= 0x14,	.h_pixels 	= 720,	.h_calc		= 720+1,
+		.v_max_out	= 576,	.h_max_out	= 768,
+	}
+};		
+
+
+#define HEXIUM_INPUTS	9
+static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = {
+	{ 0, "CVBS 1",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
+	{ 1, "CVBS 2",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
+	{ 2, "CVBS 3",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
+	{ 3, "CVBS 4",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
+	{ 4, "CVBS 5",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
+	{ 5, "CVBS 6",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
+	{ 6, "Y/C 1",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
+	{ 7, "Y/C 2",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
+	{ 8, "Y/C 3",	V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
+};
+
+#define HEXIUM_AUDIOS	0
+
+struct hexium_data
+{
+	s8 adr;
+	u8 byte;
+};
+
+#endif
diff -Nru a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/video/hexium_gemini.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,411 @@
+/*
+    hexium_gemini.c - v4l2 driver for Hexium Gemini frame grabber cards
+               
+    Visit http://www.mihu.de/linux/saa7146/ and follow the link
+    to "hexium" for further details about this card.
+    
+    Copyright (C) 2003 Michael Hunold <michael@mihu.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#define DEBUG_VARIABLE debug
+
+#include <media/saa7146_vv.h>
+
+static int debug = 255;
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "debug verbosity");
+
+/* global variables */
+int hexium_num = 0;
+
+#include "hexium_gemini.h"
+
+/* bring hardware to a sane state. this has to be done, just in case someone
+   wants to capture from this device before it has been properly initialized.
+   the capture engine would badly fail, because no valid signal arrives on the
+   saa7146, thus leading to timeouts and stuff. */
+static int hexium_init_done(struct saa7146_dev *dev)
+{
+	struct hexium *hexium = (struct hexium *) dev->ext_priv;
+	union i2c_smbus_data data;
+	int i = 0;
+
+	DEB_D(("hexium_init_done called.\n"));
+
+	/* initialize the helper ics to useful values */
+	for (i = 0; i < sizeof(hexium_ks0127b); i++) {
+		data.byte = hexium_ks0127b[i];
+		if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {
+			printk("failed for address 0x%02x\n", i);
+		}
+	}
+
+	return 0;
+}
+
+static int hexium_set_input(struct hexium *hexium, int input)
+{
+	union i2c_smbus_data data;
+
+	DEB_D((".\n"));
+
+	data.byte = hexium_input_select[input].byte;
+	if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, hexium_input_select[input].adr, I2C_SMBUS_BYTE_DATA, &data)) {
+		return -1;
+	}
+
+	return 0;
+}
+
+static int hexium_set_standard(struct hexium *hexium, struct hexium_data *vdec)
+{
+	union i2c_smbus_data data;
+	int i = 0;
+
+	DEB_D((".\n"));
+
+	while (vdec[i].adr != -1) {
+		data.byte = vdec[i].byte;
+		if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, vdec[i].adr, I2C_SMBUS_BYTE_DATA, &data)) {
+			printk("failed for address 0x%02x\n", i);
+			return -1;
+		}
+		i++;
+	}
+	return 0;
+}
+
+static struct saa7146_ext_vv vv_data;
+
+/* this function only gets called when the probing was successful */
+static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
+{
+	struct hexium *hexium = (struct hexium *) dev->ext_priv;
+
+	DEB_EE((".\n"));
+
+	hexium = (struct hexium *) kmalloc(sizeof(struct hexium), GFP_KERNEL);
+	if (NULL == hexium) {
+		printk("hexium_v4l2.o: hexium_probe: not enough kernel memory.\n");
+		return -ENOMEM;
+	}
+	memset(hexium, 0x0, sizeof(struct hexium));
+	(struct hexium *) dev->ext_priv = hexium;
+
+	/* FIXME: enable i2c-port pins, video-port-pins
+	   video port pins should be enabled here ?! */
+	saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
+
+	saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
+	if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
+		DEB_S(("cannot register i2c-device. skipping.\n"));
+		kfree(hexium);
+		return -EFAULT;
+	}
+
+	/*  set HWControl GPIO number 2 */
+	saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
+
+	saa7146_write(dev, DD1_INIT, 0x07000700);
+	saa7146_write(dev, DD1_STREAM_B, 0x00000000);
+	saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
+
+	/* the rest */
+	hexium->cur_input = 0;
+	hexium_init_done(dev);
+
+	hexium_set_standard(hexium, hexium_pal);
+	hexium->cur_std = V4L2_STD_PAL;
+
+	hexium_set_input(hexium, 0);
+	hexium->cur_input = 0;
+
+	saa7146_vv_init(dev, &vv_data);
+	if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium", VFL_TYPE_GRABBER)) {
+		ERR(("cannot register capture v4l2 device. skipping.\n"));
+		return -1;
+	}
+
+	printk("hexium: found 'hexium frame grabber'-%d.\n", hexium_num);
+	hexium_num++;
+
+	return 0;
+}
+
+static int hexium_detach(struct saa7146_dev *dev)
+{
+	struct hexium *hexium = (struct hexium *) dev->ext_priv;
+
+	DEB_EE(("dev:%p\n", dev));
+
+	saa7146_unregister_device(&hexium->video_dev, dev);
+	saa7146_vv_release(dev);
+
+	hexium_num--;
+
+	i2c_del_adapter(&hexium->i2c_adapter);
+	kfree(hexium);
+	return 0;
+}
+
+static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
+{
+	struct saa7146_dev *dev = fh->dev;
+	struct hexium *hexium = (struct hexium *) dev->ext_priv;
+/*
+	struct saa7146_vv *vv = dev->vv_data; 
+*/
+	switch (cmd) {
+	case VIDIOC_ENUMINPUT:
+		{
+			struct v4l2_input *i = arg;
+			DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
+
+			if (i->index < 0 || i->index >= HEXIUM_INPUTS) {
+				return -EINVAL;
+			}
+
+			memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
+
+			DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
+			return 0;
+		}
+	case VIDIOC_G_INPUT:
+		{
+			int *input = (int *) arg;
+			*input = hexium->cur_input;
+
+			DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
+			return 0;
+		}
+	case VIDIOC_S_INPUT:
+		{
+			int input = *(int *) arg;
+
+			DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
+
+			if (input < 0 || input >= HEXIUM_INPUTS) {
+				return -EINVAL;
+			}
+
+			hexium->cur_input = input;
+			hexium_set_input(hexium, input);
+
+			return 0;
+		}
+		/* the saa7146 provides some controls (brightness, contrast, saturation)
+		   which gets registered *after* this function. because of this we have
+		   to return with a value != 0 even if the function succeded.. */
+	case VIDIOC_QUERYCTRL:
+		{
+			struct v4l2_queryctrl *qc = arg;
+			int i;
+
+			for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
+				if (hexium_controls[i].id == qc->id) {
+					*qc = hexium_controls[i];
+					DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
+					return 0;
+				}
+			}
+			return -EAGAIN;
+		}
+	case VIDIOC_G_CTRL:
+		{
+			struct v4l2_control *vc = arg;
+			int i;
+
+			for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
+				if (hexium_controls[i].id == vc->id) {
+					break;
+				}
+			}
+
+			if (i < 0) {
+				return -EAGAIN;
+			}
+
+			switch (vc->id) {
+			case V4L2_CID_PRIVATE_BASE:{
+					vc->value = hexium->cur_bw;
+					DEB_D(("VIDIOC_G_CTRL BW:%d.\n", vc->value));
+					return 0;
+				}
+			}
+			return -EINVAL;
+		}
+
+	case VIDIOC_S_CTRL:
+		{
+			struct v4l2_control *vc = arg;
+			int i = 0;
+
+			for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) {
+				if (hexium_controls[i].id == vc->id) {
+					break;
+				}
+			}
+
+			if (i < 0) {
+				return -EAGAIN;
+			}
+
+			switch (vc->id) {
+			case V4L2_CID_PRIVATE_BASE:{
+					hexium->cur_bw = vc->value;
+					break;
+				}
+			}
+
+			DEB_D(("VIDIOC_S_CTRL BW:%d.\n", hexium->cur_bw));
+
+			if (0 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
+				hexium_set_standard(hexium, hexium_pal);
+				return 0;
+			}
+			if (0 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) {
+				hexium_set_standard(hexium, hexium_ntsc);
+				return 0;
+			}
+			if (0 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) {
+				hexium_set_standard(hexium, hexium_secam);
+				return 0;
+			}
+			if (1 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) {
+				hexium_set_standard(hexium, hexium_pal_bw);
+				return 0;
+			}
+			if (1 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) {
+				hexium_set_standard(hexium, hexium_ntsc_bw);
+				return 0;
+			}
+			if (1 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) {
+				/* fixme: is there no bw secam mode? */
+				return -EINVAL;
+			}
+
+			return -EINVAL;
+		}
+	default:
+/*
+		DEB_D(("v4l2_ioctl does not handle this ioctl.\n"));
+*/
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
+{
+	struct hexium *hexium = (struct hexium *) dev->ext_priv;
+
+	if (V4L2_STD_PAL == std->id) {
+		hexium_set_standard(hexium, hexium_pal);
+		hexium->cur_std = V4L2_STD_PAL;
+		return 0;
+	} else if (V4L2_STD_NTSC == std->id) {
+		hexium_set_standard(hexium, hexium_ntsc);
+		hexium->cur_std = V4L2_STD_NTSC;
+		return 0;
+	} else if (V4L2_STD_SECAM == std->id) {
+		hexium_set_standard(hexium, hexium_secam);
+		hexium->cur_std = V4L2_STD_SECAM;
+		return 0;
+	}
+
+	return -1;
+}
+
+static struct saa7146_extension hexium_extension;
+
+static struct saa7146_pci_extension_data hexium_gemini_4bnc = {
+	.ext_priv = "Hexium Gemini (4 BNC)",
+	.ext = &hexium_extension,
+};
+
+static struct saa7146_pci_extension_data hexium_gemini_dual_4bnc = {
+	.ext_priv = "Hexium Gemini Dual (4 BNC)",
+	.ext = &hexium_extension,
+};
+
+static struct pci_device_id pci_tbl[] = {
+	{
+	 .vendor = PCI_VENDOR_ID_PHILIPS,
+	 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
+	 .subvendor = 0x17c8,
+	 .subdevice = 0x2401,
+	 .driver_data = (unsigned long) &hexium_gemini_4bnc,
+	 },
+	{
+	 .vendor = PCI_VENDOR_ID_PHILIPS,
+	 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
+	 .subvendor = 0x17c8,
+	 .subdevice = 0x2402,
+	 .driver_data = (unsigned long) &hexium_gemini_dual_4bnc,
+	 },
+	{
+	 .vendor = 0,
+	 }
+};
+
+MODULE_DEVICE_TABLE(pci, pci_tbl);
+
+static struct saa7146_ext_vv vv_data = {
+	.inputs = HEXIUM_INPUTS,
+	.capabilities = 0,
+	.stds = &hexium_standards[0],
+	.num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard),
+	.std_callback = &std_callback,
+	.ioctls = &ioctls[0],
+	.ioctl = hexium_ioctl,
+};
+
+static struct saa7146_extension hexium_extension = {
+	.name = "hexium gemini",
+	.flags = SAA7146_USE_I2C_IRQ,
+
+	.pci_tbl = &pci_tbl[0],
+	.module = THIS_MODULE,
+
+	.attach = hexium_attach,
+	.detach = hexium_detach,
+
+	.irq_mask = 0,
+	.irq_func = NULL,
+};
+
+int __init hexium_init_module(void)
+{
+	if (0 != saa7146_register_extension(&hexium_extension)) {
+		DEB_S(("failed to register extension.\n"));
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+void __exit hexium_cleanup_module(void)
+{
+	saa7146_unregister_extension(&hexium_extension);
+}
+
+module_init(hexium_init_module);
+module_exit(hexium_cleanup_module);
+
+MODULE_DESCRIPTION("video4linux-2 driver for Hexium Gemini frame grabber cards");
+MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/media/video/hexium_gemini.h b/drivers/media/video/hexium_gemini.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/video/hexium_gemini.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,103 @@
+#ifndef __HEXIUM_GEMINI__
+#define __HEXIUM_GEMINI__
+
+#include "hexium.h"
+
+static struct saa7146_extension_ioctls ioctls[] = {
+	{ VIDIOC_G_INPUT,	SAA7146_EXCLUSIVE },
+	{ VIDIOC_S_INPUT,	SAA7146_EXCLUSIVE },
+	{ VIDIOC_QUERYCTRL, 	SAA7146_BEFORE },
+	{ VIDIOC_ENUMINPUT, 	SAA7146_EXCLUSIVE },
+	{ VIDIOC_S_STD,		SAA7146_AFTER },
+	{ VIDIOC_G_CTRL,	SAA7146_BEFORE },
+	{ VIDIOC_S_CTRL,	SAA7146_BEFORE },
+	{ 0,			0 }
+};
+
+#define HEXIUM_CONTROLS	1
+static struct v4l2_queryctrl hexium_controls[] = {
+	{ V4L2_CID_PRIVATE_BASE, V4L2_CTRL_TYPE_BOOLEAN, "B/W", 0, 1, 1, 0, 0 },
+};
+
+#define HEXIUM_GEMUINI_V_1_0		1
+#define HEXIUM_GEMUINI_DUAL_V_1_0	2
+
+struct hexium
+{
+	int type;
+	struct video_device	video_dev;
+	struct i2c_adapter	i2c_adapter;
+		
+	int 		cur_input;	/* current input */
+	v4l2_std_id 	cur_std;	/* current standard */
+	int		cur_bw;		/* current black/white status */
+};
+
+/* Samsung KS0127B decoder default registers */
+static u8 hexium_ks0127b[0x100]={
+/*00*/ 0x00,0x52,0x30,0x40,0x01,0x0C,0x2A,0x10,
+/*08*/ 0x00,0x00,0x00,0x60,0x00,0x00,0x0F,0x06,
+/*10*/ 0x00,0x00,0xE4,0xC0,0x00,0x00,0x00,0x00,
+/*18*/ 0x14,0x9B,0xFE,0xFF,0xFC,0xFF,0x03,0x22,
+/*20*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*28*/ 0x00,0x00,0x00,0x00,0x00,0x2C,0x9B,0x00,
+/*30*/ 0x00,0x00,0x10,0x80,0x80,0x10,0x80,0x80,
+/*38*/ 0x01,0x04,0x00,0x00,0x00,0x29,0xC0,0x00,
+/*40*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*48*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*50*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*58*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*60*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*68*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*70*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*78*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*80*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*88*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*90*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*98*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*A0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*A8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*B0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*B8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*C0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*C8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*D0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*D8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*E0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*E8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*F0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/*F8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
+
+static struct hexium_data hexium_pal[] = {
+	{ 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
+};
+
+static struct hexium_data hexium_pal_bw[] = {
+	{ 0x01, 0x52 },	{ 0x12, 0x64 },	{ 0x2D, 0x2C },	{ 0x2E, 0x9B },	{ -1 , 0xFF }
+};
+
+static struct hexium_data hexium_ntsc[] = {
+	{ 0x01, 0x53 }, { 0x12, 0x04 }, { 0x2D, 0x23 }, { 0x2E, 0x81 }, { -1 , 0xFF }
+};
+
+static struct hexium_data hexium_ntsc_bw[] = {
+	{ 0x01, 0x53 }, { 0x12, 0x04 }, { 0x2D, 0x23 }, { 0x2E, 0x81 }, { -1 , 0xFF }
+};
+
+static struct hexium_data hexium_secam[] = {
+	{ 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF }
+};
+
+static struct hexium_data hexium_input_select[] = {
+	{ 0x02, 0x60 },
+	{ 0x02, 0x64 },
+	{ 0x02, 0x61 },
+	{ 0x02, 0x65 },
+	{ 0x02, 0x62 },
+	{ 0x02, 0x66 },
+	{ 0x02, 0x68 },
+	{ 0x02, 0x69 },
+	{ 0x02, 0x6A },
+};
+#endif
diff -Nru a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/video/hexium_orion.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,328 @@
+/*
+    hexium_orion.c - v4l2 driver for the Hexium Orion frame grabber cards
+
+    Visit http://www.mihu.de/linux/saa7146/ and follow the link
+    to "hexium" for further details about this card.
+    
+    Copyright (C) 2003 Michael Hunold <michael@mihu.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#define DEBUG_VARIABLE debug
+
+#include <media/saa7146_vv.h>
+
+static int debug = 255;
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "debug verbosity");
+
+/* global variables */
+int hexium_num = 0;
+
+#include "hexium_orion.h"
+
+/* this is only called for old HV-PCI6/Orion cards
+   without eeprom */
+static int hexium_probe(struct saa7146_dev *dev)
+{
+	struct hexium *hexium = 0;
+	union i2c_smbus_data data;
+	int err = 0;
+
+	DEB_EE((".\n"));
+
+	/* there are no hexium orion cards with revision 0 saa7146s */
+	if (0 == dev->revision) {
+		return -EFAULT;
+	}
+
+	hexium = (struct hexium *) kmalloc(sizeof(struct hexium), GFP_KERNEL);
+	if (NULL == hexium) {
+		printk("hexium_orion.o: hexium_probe: not enough kernel memory.\n");
+		return -ENOMEM;
+	}
+	memset(hexium, 0x0, sizeof(struct hexium));
+
+	/* FIXME: enable i2c-port pins, video-port-pins
+	   video port pins should be enabled here ?! */
+	saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
+
+	saa7146_write(dev, DD1_INIT, 0x02000200);
+	saa7146_write(dev, DD1_STREAM_B, 0x00000000);
+	saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
+
+	saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
+	if (i2c_add_adapter(&hexium->i2c_adapter) < 0) {
+		DEB_S(("cannot register i2c-device. skipping.\n"));
+		kfree(hexium);
+		return -EFAULT;
+	}
+
+	/* set SAA7110 control GPIO 0 */
+	saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI);
+	/*  set HWControl GPIO number 2 */
+	saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
+
+	mdelay(10);
+
+	/* detect newer Hexium Orion cards by subsystem ids */
+	if (0x17c8 == dev->pci->subsystem_vendor && 0x0101 == dev->pci->subsystem_device) {
+		printk("hexium_orion.o: device is a Hexium Orion w/ 1 SVHS + 3 BNC inputs.\n");
+		/* we store the pointer in our private data field */
+		(struct hexium *) dev->ext_priv = hexium;
+		hexium->type = HEXIUM_ORION_1SVHS_3BNC;
+		return 0;
+	}
+
+	if (0x17c8 == dev->pci->subsystem_vendor && 0x2101 == dev->pci->subsystem_device) {
+		printk("hexium_orion.o: device is a Hexium Orion w/ 4 BNC inputs.\n");
+		/* we store the pointer in our private data field */
+		(struct hexium *) dev->ext_priv = hexium;
+		hexium->type = HEXIUM_ORION_4BNC;
+		return 0;
+	}
+
+	/* check if this is an old hexium Orion card by looking at 
+	   a saa7110 at address 0x4e */
+	if (0 == (err = i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, &data))) {
+		printk("hexium_orion.o: device is a Hexium HV-PCI6/Orion (old).\n");
+		/* we store the pointer in our private data field */
+		(struct hexium *) dev->ext_priv = hexium;
+		hexium->type = HEXIUM_HV_PCI6_ORION;
+		return 0;
+	}
+
+	i2c_del_adapter(&hexium->i2c_adapter);
+	kfree(hexium);
+	return -EFAULT;
+}
+
+/* bring hardware to a sane state. this has to be done, just in case someone
+   wants to capture from this device before it has been properly initialized.
+   the capture engine would badly fail, because no valid signal arrives on the
+   saa7146, thus leading to timeouts and stuff. */
+static int hexium_init_done(struct saa7146_dev *dev)
+{
+	struct hexium *hexium = (struct hexium *) dev->ext_priv;
+	union i2c_smbus_data data;
+	int i = 0;
+
+	DEB_D(("hexium_init_done called.\n"));
+
+	/* initialize the helper ics to useful values */
+	for (i = 0; i < sizeof(hexium_saa7110); i++) {
+		data.byte = hexium_saa7110[i];
+		if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) {
+			printk("hexium_orion: failed for address 0x%02x\n", i);
+		}
+	}
+
+	return 0;
+}
+
+static struct saa7146_ext_vv vv_data;
+
+/* this function only gets called when the probing was successful */
+static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
+{
+	struct hexium *hexium = (struct hexium *) dev->ext_priv;
+
+	DEB_EE((".\n"));
+
+	saa7146_vv_init(dev, &vv_data);
+	if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium", VFL_TYPE_GRABBER)) {
+		ERR(("cannot register capture v4l2 device. skipping.\n"));
+		return -1;
+	}
+
+	printk("hexium_orion.o: found 'hexium orion' frame grabber-%d.\n", hexium_num);
+	hexium_num++;
+
+	/* the rest */
+	hexium->cur_input = 0;
+	hexium_init_done(dev);
+
+	return 0;
+}
+
+static int hexium_detach(struct saa7146_dev *dev)
+{
+	struct hexium *hexium = (struct hexium *) dev->ext_priv;
+
+	DEB_EE(("dev:%p\n", dev));
+
+	saa7146_unregister_device(&hexium->video_dev, dev);
+	saa7146_vv_release(dev);
+
+	hexium_num--;
+
+	i2c_del_adapter(&hexium->i2c_adapter);
+	kfree(hexium);
+	return 0;
+}
+
+static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
+{
+	struct saa7146_dev *dev = fh->dev;
+	struct hexium *hexium = (struct hexium *) dev->ext_priv;
+/*
+	struct saa7146_vv *vv = dev->vv_data; 
+*/
+	switch (cmd) {
+	case VIDIOC_ENUMINPUT:
+		{
+			struct v4l2_input *i = arg;
+			DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
+
+			if (i->index < 0 || i->index >= HEXIUM_INPUTS) {
+				return -EINVAL;
+			}
+
+			memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input));
+
+			DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index));
+			return 0;
+		}
+	case VIDIOC_G_INPUT:
+		{
+			int *input = (int *) arg;
+			*input = hexium->cur_input;
+
+			DEB_D(("VIDIOC_G_INPUT: %d\n", *input));
+			return 0;
+		}
+	case VIDIOC_S_INPUT:
+		{
+			int input = *(int *) arg;
+
+			if (input < 0 || input >= HEXIUM_INPUTS) {
+				return -EINVAL;
+			}
+
+			hexium->cur_input = input;
+
+			/* fixme: switch input here, switch audio, too! */
+//              saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync);
+			printk("hexium_orion.o: VIDIOC_S_INPUT: fixme switch input.\n");
+
+			return 0;
+		}
+	default:
+/*
+		DEB_D(("v4l2_ioctl does not handle this ioctl.\n"));
+*/
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std)
+{
+	return 0;
+}
+
+static struct saa7146_extension extension;
+
+static struct saa7146_pci_extension_data hexium_hv_pci6 = {
+	.ext_priv = "Hexium HV-PCI6 / Orion",
+	.ext = &extension,
+};
+
+static struct saa7146_pci_extension_data hexium_orion_1svhs_3bnc = {
+	.ext_priv = "Hexium HV-PCI6 / Orion (1 SVHS/3 BNC)",
+	.ext = &extension,
+};
+
+static struct saa7146_pci_extension_data hexium_orion_4bnc = {
+	.ext_priv = "Hexium HV-PCI6 / Orion (4 BNC)",
+	.ext = &extension,
+};
+
+static struct pci_device_id pci_tbl[] = {
+	{
+	 .vendor = PCI_VENDOR_ID_PHILIPS,
+	 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
+	 .subvendor = 0x0000,
+	 .subdevice = 0x0000,
+	 .driver_data = (unsigned long) &hexium_hv_pci6,
+	 },
+	{
+	 .vendor = PCI_VENDOR_ID_PHILIPS,
+	 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
+	 .subvendor = 0x17c8,
+	 .subdevice = 0x0101,
+	 .driver_data = (unsigned long) &hexium_orion_1svhs_3bnc,
+	 },
+	{
+	 .vendor = PCI_VENDOR_ID_PHILIPS,
+	 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
+	 .subvendor = 0x17c8,
+	 .subdevice = 0x2101,
+	 .driver_data = (unsigned long) &hexium_orion_4bnc,
+	 },
+	{
+	 .vendor = 0,
+	 }
+};
+
+MODULE_DEVICE_TABLE(pci, pci_tbl);
+
+static struct saa7146_ext_vv vv_data = {
+	.inputs = HEXIUM_INPUTS,
+	.capabilities = 0,
+	.stds = &hexium_standards[0],
+	.num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard),
+	.std_callback = &std_callback,
+	.ioctls = &ioctls[0],
+	.ioctl = hexium_ioctl,
+};
+
+static struct saa7146_extension extension = {
+	.name = "hexium HV-PCI6/Orion",
+	.flags = 0,		// SAA7146_USE_I2C_IRQ,
+
+	.pci_tbl = &pci_tbl[0],
+	.module = THIS_MODULE,
+
+	.probe = hexium_probe,
+	.attach = hexium_attach,
+	.detach = hexium_detach,
+
+	.irq_mask = 0,
+	.irq_func = NULL,
+};
+
+int __init hexium_init_module(void)
+{
+	if (0 != saa7146_register_extension(&extension)) {
+		DEB_S(("failed to register extension.\n"));
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+void __exit hexium_cleanup_module(void)
+{
+	saa7146_unregister_extension(&extension);
+}
+
+module_init(hexium_init_module);
+module_exit(hexium_cleanup_module);
+
+MODULE_DESCRIPTION("video4linux-2 driver for Hexium Orion frame grabber cards");
+MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/media/video/hexium_orion.h b/drivers/media/video/hexium_orion.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/video/hexium_orion.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,138 @@
+#ifndef __HEXIUM_ORION__
+#define __HEXIUM_ORION__
+
+#include "hexium.h"
+
+static struct saa7146_extension_ioctls ioctls[] = {
+	{ VIDIOC_G_INPUT,	SAA7146_EXCLUSIVE },
+	{ VIDIOC_S_INPUT,	SAA7146_EXCLUSIVE },
+	{ VIDIOC_ENUMINPUT, 	SAA7146_EXCLUSIVE },
+	{ VIDIOC_S_STD,		SAA7146_AFTER },
+	{ 0,			0 }
+};
+
+struct hexium
+{
+	int type;
+	struct video_device	video_dev;
+	struct i2c_adapter	i2c_adapter;	
+	int cur_input;	/* current input */
+};
+
+/* Philips SAA7110 decoder default registers */
+static u8 hexium_saa7110[53]={
+/*00*/ 0x4C,0x3C,0x0D,0xEF,0xBD,0xF0,0x00,0x00,
+/*08*/ 0xF8,0xF8,0x60,0x60,0x40,0x86,0x18,0x90,
+/*10*/ 0x00,0x2C,0x40,0x46,0x42,0x1A,0xFF,0xDA,
+/*18*/ 0xF0,0x8B,0x00,0x00,0x00,0x00,0x00,0x00,
+/*20*/ 0xD9,0x17,0x40,0x41,0x80,0x41,0x80,0x4F,
+/*28*/ 0xFE,0x01,0x0F,0x0F,0x03,0x01,0x81,0x03,
+/*30*/ 0x44,0x75,0x01,0x8C,0x03
+};
+
+static struct {
+	struct hexium_data data[8];	
+} hexium_input_select[] = {
+{
+	{ /* input 0 */
+		{ 0x06, 0x00 },
+		{ 0x20, 0xD9 },
+		{ 0x21, 0x17 }, // 0x16,
+		{ 0x22, 0x40 },
+		{ 0x2C, 0x03 },
+		{ 0x30, 0x44 },
+		{ 0x31, 0x75 }, // ??
+		{ 0x21, 0x16 }, // 0x03,
+	}
+}, {
+	{ /* input 1 */
+		{ 0x06, 0x00 },
+		{ 0x20, 0xD8 },
+		{ 0x21, 0x17 }, // 0x16,
+		{ 0x22, 0x40 },
+		{ 0x2C, 0x03 },
+		{ 0x30, 0x44 },
+		{ 0x31, 0x75 }, // ??
+		{ 0x21, 0x16 }, // 0x03,
+	}
+}, {
+	{ /* input 2 */
+		{ 0x06, 0x00 },
+		{ 0x20, 0xBA },
+		{ 0x21, 0x07 }, // 0x05,
+		{ 0x22, 0x91 },
+		{ 0x2C, 0x03 },
+		{ 0x30, 0x60 },
+		{ 0x31, 0xB5 }, // ??
+		{ 0x21, 0x05 }, // 0x03,
+	}
+}, {
+	{ /* input 3 */
+		{ 0x06, 0x00 },
+		{ 0x20, 0xB8 },
+		{ 0x21, 0x07 }, // 0x05,
+		{ 0x22, 0x91 },
+		{ 0x2C, 0x03 },
+		{ 0x30, 0x60 },
+		{ 0x31, 0xB5 }, // ??
+		{ 0x21, 0x05 }, // 0x03,
+	}
+}, {
+	{ /* input 4 */
+		{ 0x06, 0x00 },
+		{ 0x20, 0x7C },
+		{ 0x21, 0x07 }, // 0x03
+		{ 0x22, 0xD2 },
+		{ 0x2C, 0x83 },
+		{ 0x30, 0x60 },
+		{ 0x31, 0xB5 }, // ??
+		{ 0x21, 0x03 },
+	} 
+}, {
+	{ /* input 5 */
+		{ 0x06, 0x00 },
+		{ 0x20, 0x78 },
+		{ 0x21, 0x07 }, // 0x03,
+		{ 0x22, 0xD2 },
+		{ 0x2C, 0x83 },
+		{ 0x30, 0x60 },
+		{ 0x31, 0xB5 }, // ?
+		{ 0x21, 0x03 },
+	}
+}, {
+	{ /* input 6 */
+		{ 0x06, 0x80 },
+		{ 0x20, 0x59 },
+		{ 0x21, 0x17 },
+		{ 0x22, 0x42 },
+		{ 0x2C, 0xA3 },
+		{ 0x30, 0x44 },
+		{ 0x31, 0x75 },
+		{ 0x21, 0x12 },
+	}
+}, {
+	{ /* input 7 */
+		{ 0x06, 0x80 },
+		{ 0x20, 0x9A },
+		{ 0x21, 0x17 },
+		{ 0x22, 0xB1 },
+		{ 0x2C, 0x13 },
+		{ 0x30, 0x60 },
+		{ 0x31, 0xB5 },
+		{ 0x21, 0x14 },
+	}
+}, {
+	{ /* input 8 */
+		{ 0x06, 0x80 },
+		{ 0x20, 0x3C },
+		{ 0x21, 0x27 },
+		{ 0x22, 0xC1 },
+		{ 0x2C, 0x23 },
+		{ 0x30, 0x44 },
+		{ 0x31, 0x75 },
+		{ 0x21, 0x21 },
+	}
+}	
+};
+
+#endif
diff -Nru a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
--- a/drivers/media/video/mxb.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/media/video/mxb.c	Sat Jul 19 12:54:22 2003
@@ -81,7 +81,7 @@
 enum { TUNER, AUX1, AUX3, AUX3_YC };
 
 static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
-	{ TUNER,	"Tuner",		V4L2_INPUT_TYPE_TUNER,	1, 1, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, 
+	{ TUNER,	"Tuner",		V4L2_INPUT_TYPE_TUNER,	1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, 
 	{ AUX1,		"AUX1",			V4L2_INPUT_TYPE_CAMERA,	2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
 	{ AUX3,		"AUX3 Composite",	V4L2_INPUT_TYPE_CAMERA,	4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
 	{ AUX3_YC,	"AUX3 S-Video",		V4L2_INPUT_TYPE_CAMERA,	4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
@@ -101,8 +101,8 @@
 
 /* this array holds the information of the audio source (mxb_audios),
    which has to be switched corresponding to the video source (mxb_channels) */
-static int video_audio_connect[MXB_AUDIOS] =
-	{ 0, 1, 2, 3, 3 };
+static int video_audio_connect[MXB_INPUTS] =
+	{ 0, 1, 3, 3 };
 
 /* these are the necessary input-output-pins for bringing one audio source
 (see above) to the CD-output */
@@ -173,8 +173,7 @@
 	int	cur_mute;	/* current mute status */
 };
 
-static
-struct saa7146_extension extension;
+static struct saa7146_extension extension;
 
 static int mxb_vbi_bypass(struct saa7146_dev* dev)
 {
@@ -431,10 +430,11 @@
 		   polling method ... */
 		extension.flags &= ~SAA7146_USE_I2C_IRQ;
 		for(i = 1;;i++) {
-			msg.len = mxb_saa7740_init[i].length;		
-			if (msg.len == -1U) {
+			if( -1 == mxb_saa7740_init[i].length ) {
 				break;
 			}
+
+			msg.len = mxb_saa7740_init[i].length;		
 			msg.buf = &mxb_saa7740_init[i].data[0];
 			if( 1 != (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) {
 				DEB_D(("failed to initialize 'sound arena module'.\n"));
@@ -472,6 +472,8 @@
 }
 */
 
+static struct saa7146_ext_vv vv_data;
+
 /* this function only gets called when the probing was successful */
 static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
 {
@@ -482,7 +484,7 @@
 	/* checking for i2c-devices can be omitted here, because we
 	   already did this in "mxb_vl42_probe" */
 
-	saa7146_vv_init(dev);
+	saa7146_vv_init(dev,&vv_data);
 	if( 0 != saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
 		ERR(("cannot register capture v4l2 device. skipping.\n"));
 		return -1;
@@ -566,8 +568,9 @@
 	return 0;
 }
 
-static int mxb_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) 
+static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) 
 {
+	struct saa7146_dev *dev = fh->dev;
 	struct mxb* mxb = (struct mxb*)dev->ext_priv;
 	struct saa7146_vv *vv = dev->vv_data; 
 	
@@ -1002,20 +1005,35 @@
 }
 
 static struct saa7146_standard standard[] = {
-	{ "PAL-BG",	V4L2_STD_PAL_BG,	SAA7146_PAL_VALUES },
-	{ "PAL-I",	V4L2_STD_PAL_I,		SAA7146_PAL_VALUES },
-	{ "NTSC",	V4L2_STD_NTSC,		SAA7146_NTSC_VALUES },
-	{ "SECAM", 	V4L2_STD_SECAM,		SAA7146_SECAM_VALUES },
+	{
+		.name	= "PAL-BG", 	.id	= V4L2_STD_PAL_BG,
+		.v_offset	= 0x17,	.v_field 	= 288,	.v_calc		= 576,
+		.h_offset	= 0x14,	.h_pixels 	= 680,	.h_calc		= 680+1,
+		.v_max_out	= 576,	.h_max_out	= 768,
+	}, {
+		.name	= "PAL-I", 	.id	= V4L2_STD_PAL_I,
+		.v_offset	= 0x17,	.v_field 	= 288,	.v_calc		= 576,
+		.h_offset	= 0x14,	.h_pixels 	= 680,	.h_calc		= 680+1,
+		.v_max_out	= 576,	.h_max_out	= 768,
+	}, {
+		.name	= "NTSC", 	.id	= V4L2_STD_NTSC,
+		.v_offset	= 0x16,	.v_field 	= 240,	.v_calc		= 480,
+		.h_offset	= 0x06,	.h_pixels 	= 708,	.h_calc		= 708+1,
+		.v_max_out	= 480,	.h_max_out	= 640,
+	}, {
+		.name	= "SECAM", 	.id	= V4L2_STD_SECAM,
+		.v_offset	= 0x14,	.v_field 	= 288,	.v_calc		= 576,
+		.h_offset	= 0x14,	.h_pixels 	= 720,	.h_calc		= 720+1,
+		.v_max_out	= 576,	.h_max_out	= 768,
+	}
 };
 
-static
-struct saa7146_pci_extension_data mxb = {
+static struct saa7146_pci_extension_data mxb = {
         .ext_priv = "Multimedia eXtension Board",
         .ext = &extension,
 };
 
-static
-struct pci_device_id pci_tbl[] = {
+static struct pci_device_id pci_tbl[] = {
 	{
 		.vendor    = PCI_VENDOR_ID_PHILIPS,
 		.device	   = PCI_DEVICE_ID_PHILIPS_SAA7146,
@@ -1029,8 +1047,7 @@
 
 MODULE_DEVICE_TABLE(pci, pci_tbl);
 
-static
-struct saa7146_ext_vv vv_data = {
+static struct saa7146_ext_vv vv_data = {
 	.inputs		= MXB_INPUTS,
 	.capabilities	= V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE,
 	.stds		= &standard[0],
@@ -1040,14 +1057,12 @@
 	.ioctl		= mxb_ioctl,
 };
 
-static
-struct saa7146_extension extension = {
+static struct saa7146_extension extension = {
 	.name		= MXB_IDENTIFIER,
 	.flags		= SAA7146_USE_I2C_IRQ,
 	
 	.pci_tbl	= &pci_tbl[0],
 	.module		= THIS_MODULE,
-	.ext_vv_data	= &vv_data,
 
 	.probe		= mxb_probe,
 	.attach		= mxb_attach,
diff -Nru a/drivers/media/video/pms.c b/drivers/media/video/pms.c
--- a/drivers/media/video/pms.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/media/video/pms.c	Sat Jul 19 12:54:27 2003
@@ -12,6 +12,10 @@
  *	Most of this code is directly derived from his userspace driver.
  *	His driver works so send any reports to alan@redhat.com unless the
  *	userspace driver also doesn't work for you...
+ *      
+ *      Changes:
+ *      08/07/2003        Daniele Bellucci <bellucda@tiscali.it>
+ *                        - pms_capture: report back -EFAULT 
  */
 
 #include <linux/module.h>
@@ -659,7 +663,8 @@
 			if(dt+len>count)
 				dt=count-len;
 			cnt += dev->height;
-			copy_to_user(buf, tmp+32, dt);
+			if (copy_to_user(buf, tmp+32, dt))
+				return -EFAULT;
 			buf += dt;    
 			len += dt;
 		}
diff -Nru a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
--- a/drivers/message/fusion/mptctl.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/message/fusion/mptctl.c	Sat Jul 19 12:54:21 2003
@@ -88,7 +88,6 @@
 
 #include <linux/kdev_t.h>	/* needed for access to Scsi_Host struct */
 #include <linux/blkdev.h>
-#include <linux/blk.h>          /* for io_request_lock (spinlock) decl */
 #include "../../scsi/scsi.h"
 #include "../../scsi/hosts.h"
 
diff -Nru a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
--- a/drivers/message/fusion/mptscsih.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/message/fusion/mptscsih.c	Sat Jul 19 12:54:24 2003
@@ -72,7 +72,6 @@
 #include <linux/errno.h>
 #include <linux/kdev_t.h>
 #include <linux/blkdev.h>
-#include <linux/blk.h>		/* for io_request_lock (spinlock) decl */
 #include <linux/delay.h>	/* for mdelay */
 #include <linux/interrupt.h>	/* needed for in_interrupt() proto */
 #include <linux/reboot.h>	/* notifier code */
diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
--- a/drivers/message/i2o/i2o_block.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/message/i2o/i2o_block.c	Sat Jul 19 12:54:26 2003
@@ -87,8 +87,6 @@
 
 #define MAJOR_NR I2O_MAJOR
 
-#include <linux/blk.h>
-
 #define MAX_I2OB	16
 
 #define MAX_I2OB_DEPTH	8
diff -Nru a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
--- a/drivers/message/i2o/i2o_scsi.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/message/i2o/i2o_scsi.c	Sat Jul 19 12:54:26 2003
@@ -54,7 +54,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/atomic.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/i2o.h>
 #include "../../scsi/scsi.h"
 #include "../../scsi/hosts.h"
diff -Nru a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
--- a/drivers/mtd/mtd_blkdevs.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/mtd/mtd_blkdevs.c	Sat Jul 19 12:54:21 2003
@@ -15,7 +15,6 @@
 #include <linux/mtd/blktrans.h>
 #include <linux/mtd/mtd.h>
 #include <linux/blkdev.h>
-#include <linux/blk.h>
 #include <linux/blkpg.h>
 #include <linux/spinlock.h>
 #include <linux/hdreg.h>
diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig
--- a/drivers/net/Kconfig	Sat Jul 19 12:54:27 2003
+++ b/drivers/net/Kconfig	Sat Jul 19 12:54:27 2003
@@ -1153,7 +1153,7 @@
 
 config SEEQ8005
 	tristate "SEEQ8005 support (EXPERIMENTAL)"
-	depends on NET_ISA && OBSOLETE && EXPERIMENTAL
+	depends on NET_ISA && EXPERIMENTAL
 	help
 	  This is a driver for the SEEQ 8005 network (Ethernet) card.  If this
 	  is for you, read the Ethernet-HOWTO, available from
diff -Nru a/drivers/net/eql.c b/drivers/net/eql.c
--- a/drivers/net/eql.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/net/eql.c	Sat Jul 19 12:54:27 2003
@@ -162,22 +162,12 @@
 static char version[] __initdata = 
 	"Equalizer2002: Simon Janes (simon@ncm.com) and David S. Miller (davem@redhat.com)\n";
 
-static int __init eql_init(struct net_device *dev)
+static void __init eql_setup(struct net_device *dev)
 {
-	static unsigned int version_printed;
-	equalizer_t *eql;
+	equalizer_t *eql = dev->priv;
 
 	SET_MODULE_OWNER(dev);
 
-	if (version_printed++ == 0)
-		printk(version);
-
-	dev->priv = kmalloc(sizeof (equalizer_t), GFP_KERNEL);
-	if (dev->priv == NULL)
-		return -ENOMEM;
-	memset(dev->priv, 0, sizeof (equalizer_t));
-	eql = dev->priv;
-
 	init_timer(&eql->timer);
 	eql->timer.data     	= (unsigned long) dev->priv;
 	eql->timer.expires  	= jiffies + EQL_DEFAULT_RESCHED_IVAL;
@@ -203,8 +193,6 @@
 
 	dev->type       	= ARPHRD_SLIP;
 	dev->tx_queue_len 	= 5;		/* Hands them off fast */
-
-	return 0;
 }
 
 static int eql_open(struct net_device *dev)
@@ -598,23 +586,28 @@
 	return -EINVAL;
 }
 
-static struct net_device dev_eql;
+static struct net_device *dev_eql;
 
 static int __init eql_init_module(void)
 {
-	strcpy(dev_eql.name, "eql");
-	dev_eql.init = eql_init;
-	if (register_netdev(&dev_eql) != 0) {
-		printk("eql: register_netdev() returned non-zero.\n");
-		return -EIO;
-	}
-	return 0;
+	int err;
+
+	printk(version);
+
+	dev_eql = alloc_netdev(sizeof(equalizer_t), "eql", eql_setup);
+	if (!dev_eql)
+		return -ENOMEM;
+
+	err = register_netdev(dev_eql);
+	if (err) 
+		kfree(dev_eql);
+	return err;
 }
 
 static void __exit eql_cleanup_module(void)
 {
-	kfree(dev_eql.priv);
-	unregister_netdev(&dev_eql);
+	unregister_netdev(dev_eql);
+	kfree(dev_eql);
 }
 
 module_init(eql_init_module);
diff -Nru a/drivers/net/fc/iph5526.c b/drivers/net/fc/iph5526.c
--- a/drivers/net/fc/iph5526.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/net/fc/iph5526.c	Sat Jul 19 12:54:23 2003
@@ -48,7 +48,6 @@
 #include <linux/timer.h>
 #include <linux/spinlock.h>
 #include <linux/netdevice.h>
-#include <linux/blk.h>
 #include <linux/fcdevice.h> /* had the declarations for init_fcdev among
 			       others + includes if_fcdevice.h */
 
diff -Nru a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
--- a/drivers/net/irda/vlsi_ir.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/net/irda/vlsi_ir.c	Sat Jul 19 12:54:21 2003
@@ -474,10 +474,8 @@
 	if (pos + nbytes > size)
 		nbytes = size - pos;
 
-	if (!access_ok(VERIFY_WRITE, buf, nbytes))
-		return -EINVAL;
-
-	copy_to_user(buf, procdata->data + pos, nbytes);
+	if (copy_to_user(buf, procdata->data + pos, nbytes))
+		return -EFAULT;
 
 	*ppos += nbytes;
 
diff -Nru a/drivers/net/ni65.c b/drivers/net/ni65.c
--- a/drivers/net/ni65.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/net/ni65.c	Sat Jul 19 12:54:24 2003
@@ -245,6 +245,7 @@
 	int cmdr_addr;
 	int cardno;
 	int features;
+	spinlock_t ring_lock;
 };
 
 static int  ni65_probe1(struct net_device *dev,int);
@@ -299,7 +300,7 @@
 	int irqval = request_irq(dev->irq, &ni65_interrupt,0,
                         cards[p->cardno].cardname,dev);
 	if (irqval) {
-		printk ("%s: unable to get IRQ %d (irqval=%d).\n",
+		printk(KERN_ERR "%s: unable to get IRQ %d (irqval=%d).\n",
 		          dev->name,dev->irq, irqval);
 		return -EAGAIN;
 	}
@@ -409,12 +410,14 @@
 	p = (struct priv *) dev->priv;
 	p->cmdr_addr = ioaddr + cards[i].cmd_offset;
 	p->cardno = i;
+	spin_lock_init(&p->ring_lock);
 
-	printk("%s: %s found at %#3x, ", dev->name, cards[p->cardno].cardname , ioaddr);
+	printk(KERN_INFO "%s: %s found at %#3x, ", dev->name, cards[p->cardno].cardname , ioaddr);
 
 	outw(inw(PORT+L_RESET),PORT+L_RESET); /* first: reset the card */
 	if( (j=readreg(CSR0)) != 0x4) {
-		 printk(KERN_ERR "can't RESET card: %04x\n",j);
+		 printk("failed.\n");
+		 printk(KERN_ERR "%s: Can't RESET card: %04x\n", dev->name, j);
 		 ni65_free_buffer(p);
 		 release_region(ioaddr, cards[p->cardno].total_size);
 		 return -EAGAIN;
@@ -467,7 +470,8 @@
 					break;
 			}
 			if(i == 5) {
-				printk("Can't detect DMA channel!\n");
+				printk("failed.\n");
+				printk(KERN_ERR "%s: Can't detect DMA channel!\n", dev->name);
 				ni65_free_buffer(p);
 				release_region(ioaddr, cards[p->cardno].total_size);
 				return -EAGAIN;
@@ -480,13 +484,13 @@
 
 		if(dev->irq < 2)
 		{
-			unsigned long irq_mask, delay;
+			unsigned long irq_mask;
 
 			ni65_init_lance(p,dev->dev_addr,0,0);
 			irq_mask = probe_irq_on();
 			writereg(CSR0_INIT|CSR0_INEA,CSR0); /* trigger interrupt */
-			delay = jiffies + HZ/50;
-			while (time_before(jiffies, delay)) ;
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(HZ/50);
 			dev->irq = probe_irq_off(irq_mask);
 			if(!dev->irq)
 			{
@@ -503,7 +507,7 @@
 
 	if(request_dma(dev->dma, cards[p->cardno].cardname ) != 0)
 	{
-		printk("%s: Can't request dma-channel %d\n",dev->name,(int) dev->dma);
+		printk(KERN_ERR "%s: Can't request dma-channel %d\n",dev->name,(int) dev->dma);
 		ni65_free_buffer(p);
 		release_region(ioaddr, cards[p->cardno].total_size);
 		return -EAGAIN;
@@ -570,7 +574,7 @@
 	if(type) {
 		ret = skb = alloc_skb(2+16+size,GFP_KERNEL|GFP_DMA);
 		if(!skb) {
-			printk("%s: unable to allocate %s memory.\n",dev->name,what);
+			printk(KERN_WARNING "%s: unable to allocate %s memory.\n",dev->name,what);
 			return NULL;
 		}
 		skb->dev = dev;
@@ -581,12 +585,12 @@
 	else {
 		ret = ptr = kmalloc(T_BUF_SIZE,GFP_KERNEL | GFP_DMA);
 		if(!ret) {
-			printk("%s: unable to allocate %s memory.\n",dev->name,what);
+			printk(KERN_WARNING "%s: unable to allocate %s memory.\n",dev->name,what);
 			return NULL;
 		}
 	}
 	if( (u32) virt_to_phys(ptr+size) > 0x1000000) {
-		printk("%s: unable to allocate %s memory in lower 16MB!\n",dev->name,what);
+		printk(KERN_WARNING "%s: unable to allocate %s memory in lower 16MB!\n",dev->name,what);
 		if(type)
 			kfree_skb(skb);
 		else
@@ -692,7 +696,7 @@
 	writedatareg(CSR0_STOP);
 
 	if(debuglevel > 1)
-		printk("ni65_stop_start\n");
+		printk(KERN_DEBUG "ni65_stop_start\n");
 
 	if(p->features & INIT_RING_BEFORE_START) {
 		int i;
@@ -846,6 +850,8 @@
 
 	p = (struct priv *) dev->priv;
 
+	spin_lock(&p->ring_lock);
+	
 	while(--bcnt) {
 		csr0 = inw(PORT+L_DATAREG);
 
@@ -867,7 +873,7 @@
 		{
 			struct priv *p = (struct priv *) dev->priv;
 			if(debuglevel > 1)
-				printk("%s: general error: %04x.\n",dev->name,csr0);
+				printk(KERN_ERR "%s: general error: %04x.\n",dev->name,csr0);
 			if(csr0 & CSR0_BABL)
 				p->stats.tx_errors++;
 			if(csr0 & CSR0_MISS) {
@@ -879,7 +885,7 @@
 			}
 			if(csr0 & CSR0_MERR) {
 				if(debuglevel > 1)
-					printk("%s: Ooops .. memory error: %04x.\n",dev->name,csr0);
+					printk(KERN_ERR "%s: Ooops .. memory error: %04x.\n",dev->name,csr0);
 				ni65_stop_start(dev,p);
 			}
 		}
@@ -932,12 +938,13 @@
 #endif
 
 	if( (csr0 & (CSR0_RXON | CSR0_TXON)) != (CSR0_RXON | CSR0_TXON) ) {
-		printk("%s: RX or TX was offline -> restart\n",dev->name);
+		printk(KERN_DEBUG "%s: RX or TX was offline -> restart\n",dev->name);
 		ni65_stop_start(dev,p);
 	}
 	else
 		writedatareg(CSR0_INEA);
 
+	spin_unlock(&p->ring_lock);
 	return IRQ_HANDLED;
 }
 
@@ -1147,9 +1154,7 @@
 				memset((char *)p->tmdbounce[p->tmdbouncenum]+skb->len, 0, len-skb->len);
 			dev_kfree_skb (skb);
 
-			save_flags(flags);
-			cli();
-
+			spin_lock_irqsave(&p->ring_lock, flags);
 			tmdp = p->tmdhead + p->tmdnum;
 			tmdp->u.buffer = (u32) isa_virt_to_bus(p->tmdbounce[p->tmdbouncenum]);
 			p->tmdbouncenum = (p->tmdbouncenum + 1) & (TMDNUM - 1);
@@ -1157,8 +1162,7 @@
 #ifdef XMT_VIA_SKB
 		}
 		else {
-			save_flags(flags);
-			cli();
+			spin_lock_irqsave(&p->ring_lock, flags);
 
 			tmdp = p->tmdhead + p->tmdnum;
 			tmdp->u.buffer = (u32) isa_virt_to_bus(skb->data);
@@ -1178,8 +1182,8 @@
 			
 		p->lock = 0;
 		dev->trans_start = jiffies;
-
-		restore_flags(flags);
+		
+		spin_unlock_irqrestore(&p->ring_lock, flags);
 	}
 
 	return 0;
@@ -1238,10 +1242,8 @@
 {
 	struct priv *p;
 	p = (struct priv *) dev_ni65.priv;
-	if(!p) {
-		printk("Ooops .. no private struct\n");
-		return;
-	}
+	if(!p)
+		BUG();
 	disable_dma(dev_ni65.dma);
 	free_dma(dev_ni65.dma);
 	unregister_netdev(&dev_ni65);
@@ -1250,6 +1252,7 @@
 	dev_ni65.priv = NULL;
 }
 #endif /* MODULE */
+
 MODULE_LICENSE("GPL");
 
 /*
diff -Nru a/drivers/net/ni65.h b/drivers/net/ni65.h
--- a/drivers/net/ni65.h	Sat Jul 19 12:54:30 2003
+++ b/drivers/net/ni65.h	Sat Jul 19 12:54:30 2003
@@ -20,32 +20,32 @@
 #define CSR0_BABL	0x4000	/* Babble transmitter timeout error (RC) */
 #define CSR0_CERR	0x2000	/* Collision Error (RC) */
 #define CSR0_MISS	0x1000	/* Missed packet (RC) */
-#define CSR0_MERR	0x0800	/* Memory Error (RC) */ 
+#define CSR0_MERR	0x0800	/* Memory Error (RC) */
 #define CSR0_RINT	0x0400	/* Receiver Interrupt (RC) */
-#define CSR0_TINT       0x0200	/* Transmit Interrupt (RC) */ 
+#define CSR0_TINT       0x0200	/* Transmit Interrupt (RC) */
 #define CSR0_IDON	0x0100	/* Initialization Done (RC) */
 #define CSR0_INTR	0x0080	/* Interrupt Flag (R) */
 #define CSR0_INEA	0x0040	/* Interrupt Enable (RW) */
 #define CSR0_RXON	0x0020	/* Receiver on (R) */
-#define CSR0_TXON	0x0010  /* Transmitter on (R) */
+#define CSR0_TXON	0x0010	/* Transmitter on (R) */
 #define CSR0_TDMD	0x0008	/* Transmit Demand (RS) */
-#define CSR0_STOP	0x0004 	/* Stop (RS) */
+#define CSR0_STOP	0x0004	/* Stop (RS) */
 #define CSR0_STRT	0x0002	/* Start (RS) */
 #define CSR0_INIT	0x0001	/* Initialize (RS) */
 
-#define CSR0_CLRALL    0x7f00  /* mask for all clearable bits */
+#define CSR0_CLRALL    0x7f00	/* mask for all clearable bits */
 /*
  *	Initialization Block  Mode operation Bit Definitions.
  */
 
 #define M_PROM		0x8000	/* Promiscuous Mode */
-#define M_INTL		0x0040  /* Internal Loopback */
-#define M_DRTY		0x0020  /* Disable Retry */ 
+#define M_INTL		0x0040	/* Internal Loopback */
+#define M_DRTY		0x0020	/* Disable Retry */
 #define M_COLL		0x0010	/* Force Collision */
 #define M_DTCR		0x0008	/* Disable Transmit CRC) */
 #define M_LOOP		0x0004	/* Loopback */
-#define M_DTX		0x0002	/* Disable the Transmitter */ 
-#define M_DRX		0x0001  /* Disable the Receiver */
+#define M_DTX		0x0002	/* Disable the Transmitter */
+#define M_DRX		0x0001	/* Disable the Receiver */
 
 
 /*
@@ -56,7 +56,7 @@
 #define RCV_ERR		0x40	/* Error Summary */
 #define RCV_FRAM	0x20	/* Framing Error */
 #define RCV_OFLO	0x10	/* Overflow Error */
-#define RCV_CRC		0x08	/* CRC Error */ 
+#define RCV_CRC		0x08	/* CRC Error */
 #define RCV_BUF_ERR	0x04	/* Buffer Error */
 #define RCV_START	0x02	/* Start of Packet */
 #define RCV_END		0x01	/* End of Packet */
@@ -67,7 +67,7 @@
  */
 
 #define XMIT_OWN	0x80	/* owner bit 0 = host, 1 = lance */
-#define XMIT_ERR	0x40    /* Error Summary */
+#define XMIT_ERR	0x40	/* Error Summary */
 #define XMIT_RETRY	0x10	/* more the 1 retry needed to Xmit */
 #define XMIT_1_RETRY	0x08	/* one retry needed to Xmit */
 #define XMIT_DEF	0x04	/* Deferred */
@@ -78,53 +78,44 @@
  * transmit status (2) (valid if XMIT_ERR == 1)
  */
 
-#define XMIT_TDRMASK    0x03ff  /* time-domain-reflectometer-value */
-#define XMIT_RTRY 	0x0400  /* Failed after 16 retransmissions  */
-#define XMIT_LCAR 	0x0800  /* Loss of Carrier */
-#define XMIT_LCOL 	0x1000  /* Late collision */
-#define XMIT_RESERV 	0x2000  /* Reserved */
-#define XMIT_UFLO 	0x4000  /* Underflow (late memory) */
-#define XMIT_BUFF 	0x8000  /* Buffering error (no ENP) */
-
-struct init_block 
-{
-  unsigned short mode;
-  unsigned char eaddr[6];
-  unsigned char filter[8];
-  /* bit 29-31: number of rmd's (power of 2) */
-  u32 rrp;   /* receive ring pointer (align 8) */
-  /* bit 29-31: number of tmd's (power of 2) */
-  u32 trp;   /* transmit ring pointer (align 8) */
+#define XMIT_TDRMASK    0x03ff	/* time-domain-reflectometer-value */
+#define XMIT_RTRY 	0x0400	/* Failed after 16 retransmissions  */
+#define XMIT_LCAR 	0x0800	/* Loss of Carrier */
+#define XMIT_LCOL 	0x1000	/* Late collision */
+#define XMIT_RESERV 	0x2000	/* Reserved */
+#define XMIT_UFLO 	0x4000	/* Underflow (late memory) */
+#define XMIT_BUFF 	0x8000	/* Buffering error (no ENP) */
+
+struct init_block {
+	unsigned short mode;
+	unsigned char eaddr[6];
+	unsigned char filter[8];
+	/* bit 29-31: number of rmd's (power of 2) */
+	u32 rrp;		/* receive ring pointer (align 8) */
+	/* bit 29-31: number of tmd's (power of 2) */
+	u32 trp;		/* transmit ring pointer (align 8) */
 };
 
-struct rmd /* Receive Message Descriptor */
-{ 
-  union
-  {
-    volatile u32 buffer;
-    struct 
-    {
-      volatile unsigned char dummy[3];
-      volatile unsigned char status; 
-    } s;
-  } u;
-  volatile short blen;
-  volatile unsigned short mlen;
+struct rmd {			/* Receive Message Descriptor */
+	union {
+		volatile u32 buffer;
+		struct {
+			volatile unsigned char dummy[3];
+			volatile unsigned char status;
+		} s;
+	} u;
+	volatile short blen;
+	volatile unsigned short mlen;
 };
 
-struct tmd
-{
-  union 
-  {
-    volatile u32 buffer;
-    struct 
-    {
-      volatile unsigned char dummy[3];
-      volatile unsigned char status;
-    } s;
-  } u;
-  volatile unsigned short blen;
-  volatile unsigned short status2;
+struct tmd {
+	union {
+		volatile u32 buffer;
+		struct {
+			volatile unsigned char dummy[3];
+			volatile unsigned char status;
+		} s;
+	} u;
+	volatile unsigned short blen;
+	volatile unsigned short status2;
 };
-
-
diff -Nru a/drivers/net/pcmcia/Kconfig b/drivers/net/pcmcia/Kconfig
--- a/drivers/net/pcmcia/Kconfig	Sat Jul 19 12:54:26 2003
+++ b/drivers/net/pcmcia/Kconfig	Sat Jul 19 12:54:26 2003
@@ -113,7 +113,7 @@
 	  If unsure, say N.
 
 config PCMCIA_AXNET
-	tristate "broken NS8390-cards support"
+	tristate "Asix AX88190 PCMCIA support"
 	depends on NET_PCMCIA && PCMCIA
 	---help---
 	  Say Y here if you intend to attach an Asix AX88190-based PCMCIA
diff -Nru a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c
--- a/drivers/net/seeq8005.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/net/seeq8005.c	Sat Jul 19 12:54:26 2003
@@ -700,7 +700,8 @@
  * wait_for_buffer
  *
  * This routine waits for the SEEQ chip to assert that the FIFO is ready
- * by checking for a window interrupt, and then clearing it
+ * by checking for a window interrupt, and then clearing it. This has to
+ * occur in the interrupt handler!
  */
 inline void wait_for_buffer(struct net_device * dev)
 {
@@ -710,7 +711,7 @@
 	
 	tmp = jiffies + HZ;
 	while ( ( ((status=inw(SEEQ_STATUS)) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && time_before(jiffies, tmp))
-		mb();
+		cpu_relax();
 		
 	if ( (status & SEEQSTAT_WINDOW_INT) == SEEQSTAT_WINDOW_INT)
 		outw( SEEQCMD_WINDOW_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
diff -Nru a/drivers/net/wan/comx-hw-comx.c b/drivers/net/wan/comx-hw-comx.c
--- a/drivers/net/wan/comx-hw-comx.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/net/wan/comx-hw-comx.c	Sat Jul 19 12:54:22 2003
@@ -11,6 +11,7 @@
  *
  * Contributors:
  * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 0.86
+ * Daniele Bellucci         <bellucda@tiscali.it>   - 0.87
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -42,9 +43,12 @@
  *		- printk cleanups
  * Version 0.86 (00/08/15):
  * 		- resource release on failure at COMX_init
+ *
+ * Version 0.87 (03/07/09)
+ *              - audit copy_from_user in comxhw_write_proc
  */
 
-#define VERSION "0.86"
+#define VERSION "0.87"
 
 #include <linux/module.h>
 #include <linux/version.h>
@@ -1084,7 +1088,8 @@
 		if (hw->firmware->data) {
 			kfree(hw->firmware->data);
 		}
-		copy_from_user(tmp + file->f_pos, buffer, count);
+		if (copy_from_user(tmp + file->f_pos, buffer, count))
+			return -EFAULT;
 		hw->firmware->len = entry->size = file->f_pos + count;
 		hw->firmware->data = tmp;
 		file->f_pos += count;
diff -Nru a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c
--- a/drivers/net/wan/sdladrv.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/net/wan/sdladrv.c	Sat Jul 19 12:54:23 2003
@@ -160,10 +160,6 @@
 
 /****** Function Prototypes *************************************************/
 
-/* Module entry points. These are called by the OS and must be public. */
-int init_module (void);
-void cleanup_module (void);
-
 /* Hardware-specific functions */
 static int sdla_detect	(sdlahw_t* hw);
 static int sdla_autodpm	(sdlahw_t* hw);
@@ -325,11 +321,7 @@
  * Context:	process
  */
 
-#ifdef MODULE
-int init_module (void)
-#else
 int sdladrv_init(void)
-#endif
 {
 	int i=0;
 
@@ -354,9 +346,12 @@
  * Module 'remove' entry point.
  * o release all remaining system resources
  */
-void cleanup_module (void)
+static void sdladrv_cleanup(void)
 {
 }
+
+module_init(sdladrv_init);
+module_cleanup(sdladrv_cleanup);
 #endif
 
 /******* Kernel APIs ********************************************************/
diff -Nru a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c
--- a/drivers/net/wan/sdlamain.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/net/wan/sdlamain.c	Sat Jul 19 12:54:26 2003
@@ -177,10 +177,6 @@
 extern void disable_irq(unsigned int);
 extern void enable_irq(unsigned int);
  
-/* Module entry points */
-int init_module (void);
-void cleanup_module (void);
-
 /* WAN link driver entry points */
 static int setup(struct wan_device* wandev, wandev_conf_t* conf);
 static int shutdown(struct wan_device* wandev);
@@ -246,11 +242,7 @@
  * Context:	process
  */
  
-#ifdef MODULE
-int init_module (void)
-#else
 int wanpipe_init(void)
-#endif
 {
 	int cnt, err = 0;
 
@@ -313,7 +305,7 @@
  * o unregister all adapters from the WAN router
  * o release all remaining system resources
  */
-void cleanup_module (void)
+static void wanpipe_cleanup(void)
 {
 	int i;
 
@@ -329,6 +321,8 @@
 	printk(KERN_INFO "\nwanpipe: WANPIPE Modules Unloaded.\n");
 }
 
+module_init(wanpipe_init);
+module_exit(wanpipe_cleanup);
 #endif
 
 /******* WAN Device Driver Entry Points *************************************/
diff -Nru a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c
--- a/drivers/net/wan/syncppp.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/net/wan/syncppp.c	Sat Jul 19 12:54:24 2003
@@ -161,7 +161,7 @@
  * then put the packet into tx_queue, and call sppp_flush_xmit()
  * after spinlock is released.
  */
-static void sppp_flush_xmit()
+static void sppp_flush_xmit(void)
 {
 	struct sk_buff *skb;
 	while ((skb = skb_dequeue(&tx_queue)) != NULL)
diff -Nru a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
--- a/drivers/net/wireless/ray_cs.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/net/wireless/ray_cs.c	Sat Jul 19 12:54:24 2003
@@ -25,6 +25,8 @@
  * - reorganize kmallocs in ray_attach, checking all for failure
  *   and releasing the previous allocations if one fails
  *
+ * Daniele Bellucci <bellucda@tiscali.it> - 07/10/2003
+ * - Audit copy_to_user in ioctl(SIOCGIWESSID)
  * 
 =============================================================================*/
 
@@ -1315,7 +1317,8 @@
 	  /* Push it out ! */
 	  wrq->u.data.length = strlen(essid) + 1;
 	  wrq->u.data.flags = 1; /* active */
-	  copy_to_user(wrq->u.data.pointer, essid, sizeof(essid));
+	  if (copy_to_user(wrq->u.data.pointer, essid, sizeof(essid)))
+		  err = -EFAULT;
 	}
       break;
 
diff -Nru a/drivers/parisc/led.c b/drivers/parisc/led.c
--- a/drivers/parisc/led.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/parisc/led.c	Sat Jul 19 12:54:24 2003
@@ -14,6 +14,10 @@
  * TODO:
  *	- speed-up calculations with inlined assembler
  *	- interface to write to second row of LCD from /proc (if technically possible)
+ *
+ * Changes:
+ *      - Audit copy_from_user in led_proc_write.
+ *                                Daniele Bellucci <bellucda@tiscali.it>
  */
 
 #include <linux/config.h>
@@ -160,7 +164,9 @@
 
 	memset(lbuf, 0, count);
 
-	copy_from_user(lbuf, buf, count);
+	if (copy_from_user(lbuf, buf, count))
+		return -EFAULT;
+
 	cur = lbuf;
 
 	/* skip initial spaces */
diff -Nru a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
--- a/drivers/parport/parport_pc.c	Sat Jul 19 12:54:29 2003
+++ b/drivers/parport/parport_pc.c	Sat Jul 19 12:54:29 2003
@@ -94,7 +94,8 @@
 } superios[NR_SUPERIOS] __devinitdata = { {0,},};
 
 static int user_specified __devinitdata = 0;
-#if defined(CONFIG_PARPORT_PC_FIFO) || defined(CONFIG_PARPORT_PC_SUPERIO)
+#if defined(CONFIG_PARPORT_PC_SUPERIO) || \
+       (defined(CONFIG_PARPORT_1284) && defined(CONFIG_PARPORT_PC_FIFO))
 static int verbose_probing;
 #endif
 static int registered_parport;
@@ -3116,7 +3117,8 @@
 MODULE_PARM(irq, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
 MODULE_PARM_DESC(dma, "DMA channel");
 MODULE_PARM(dma, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
-#if defined(CONFIG_PARPORT_PC_FIFO) || defined(CONFIG_PARPORT_PC_SUPERIO)
+#if defined(CONFIG_PARPORT_PC_SUPERIO) || \
+       (defined(CONFIG_PARPORT_1284) && defined(CONFIG_PARPORT_PC_FIFO))
 MODULE_PARM_DESC(verbose_probing, "Log chit-chat during initialisation");
 MODULE_PARM(verbose_probing, "i");
 #endif
diff -Nru a/drivers/pci/Makefile b/drivers/pci/Makefile
--- a/drivers/pci/Makefile	Sat Jul 19 12:54:28 2003
+++ b/drivers/pci/Makefile	Sat Jul 19 12:54:28 2003
@@ -2,7 +2,7 @@
 # Makefile for the PCI bus specific drivers.
 #
 
-obj-y		+= access.o bus.o probe.o pci.o pool.o quirks.o \
+obj-y		+= access.o bus.o probe.o remove.o pci.o pool.o quirks.o \
 			names.o pci-driver.o search.o pci-sysfs.o
 obj-$(CONFIG_PM)  += power.o
 obj-$(CONFIG_PROC_FS) += proc.o
diff -Nru a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
--- a/drivers/pci/hotplug/Kconfig	Sat Jul 19 12:54:24 2003
+++ b/drivers/pci/hotplug/Kconfig	Sat Jul 19 12:54:24 2003
@@ -99,22 +99,17 @@
 	  When in doubt, say N.
 
 config HOTPLUG_PCI_CPCI
-	tristate "CompactPCI Hotplug driver"
+	bool "CompactPCI Hotplug driver"
 	depends on HOTPLUG_PCI
 	help
 	  Say Y here if you have a CompactPCI system card with CompactPCI
 	  hotswap support per the PICMG 2.1 specification.
 
-	  This code is also available as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called cpci_hotplug. If you want to compile it
-	  as a module, say M here and read <file:Documentation/modules.txt>.
-
 	  When in doubt, say N.
 
 config HOTPLUG_PCI_CPCI_ZT5550
 	tristate "Ziatech ZT5550 CompactPCI Hotplug driver"
-	depends on HOTPLUG_PCI_CPCI && X86
+	depends on HOTPLUG_PCI && HOTPLUG_PCI_CPCI && X86
 	help
 	  Say Y here if you have an Performance Technologies (formerly Intel,
           formerly just Ziatech) Ziatech ZT5550 CompactPCI system card.
@@ -128,7 +123,7 @@
 
 config HOTPLUG_PCI_CPCI_GENERIC
 	tristate "Generic port I/O CompactPCI Hotplug driver"
-	depends on HOTPLUG_PCI_CPCI && X86
+	depends on HOTPLUG_PCI && HOTPLUG_PCI_CPCI && X86
 	help
 	  Say Y here if you have a CompactPCI system card that exposes the #ENUM
 	  hotswap signal as a bit in a system register that can be read through
diff -Nru a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
--- a/drivers/pci/hotplug/acpiphp_glue.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/pci/hotplug/acpiphp_glue.c	Sat Jul 19 12:54:24 2003
@@ -607,7 +607,7 @@
 
 	/* check if this bridge has ejectable slots */
 	if (detect_ejectable_slots(handle) > 0) {
-		dbg("found PCI-to-PCI bridge at PCI %s\n", dev->slot_name);
+		dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev));
 		add_p2p_bridge(handle, seg, bus, device, function);
 	}
 
@@ -693,7 +693,7 @@
 
 		if (func->flags & FUNC_HAS_PS0) {
 			dbg("%s: executing _PS0 on %s\n", __FUNCTION__,
-			    func->pci_dev->slot_name);
+			    pci_name(func->pci_dev));
 			status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL);
 			if (ACPI_FAILURE(status)) {
 				warn("%s: _PS0 failed\n", __FUNCTION__);
diff -Nru a/drivers/pci/hotplug/acpiphp_pci.c b/drivers/pci/hotplug/acpiphp_pci.c
--- a/drivers/pci/hotplug/acpiphp_pci.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/pci/hotplug/acpiphp_pci.c	Sat Jul 19 12:54:21 2003
@@ -212,7 +212,7 @@
 	int count;
 	struct pci_resource *res;
 
-	dbg("Device %s\n", dev->slot_name);
+	dbg("Device %s\n", pci_name(dev));
 
 	for (count = 0; address[count]; count++) {	/* for 6 BARs */
 		pci_read_config_dword(dev, address[count], &bar);
@@ -337,7 +337,7 @@
 	struct pci_dev *dev;
 
 	dev = func->pci_dev;
-	dbg("Hot-pluggable device %s\n", dev->slot_name);
+	dbg("Hot-pluggable device %s\n", pci_name(dev));
 
 	for (count = 0; address[count]; count++) {	/* for 6 BARs */
 		pci_read_config_dword(dev, address[count], &bar);
diff -Nru a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h
--- a/drivers/pci/hotplug/cpci_hotplug.h	Sat Jul 19 12:54:23 2003
+++ b/drivers/pci/hotplug/cpci_hotplug.h	Sat Jul 19 12:54:23 2003
@@ -75,7 +75,6 @@
 extern int cpci_hp_unregister_controller(struct cpci_hp_controller *controller);
 extern int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last);
 extern int cpci_hp_unregister_bus(struct pci_bus *bus);
-extern struct slot *cpci_find_slot(struct pci_bus *bus, unsigned int devfn);
 extern int cpci_hp_start(void);
 extern int cpci_hp_stop(void);
 
diff -Nru a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
--- a/drivers/pci/hotplug/cpci_hotplug_core.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/pci/hotplug/cpci_hotplug_core.c	Sat Jul 19 12:54:24 2003
@@ -427,34 +427,6 @@
 	return 0;
 }
 
-struct slot *
-cpci_find_slot(struct pci_bus *bus, unsigned int devfn)
-{
-	struct slot *slot;
-	struct slot *found;
-	struct list_head *tmp;
-
-	if(!bus) {
-		return NULL;
-	}
-
-	spin_lock(&list_lock);
-	if(!slots) {
-		spin_unlock(&list_lock);
-		return NULL;
-	}
-	found = NULL;
-	list_for_each(tmp, &slot_list) {
-		slot = list_entry(tmp, struct slot, slot_list);
-		if(slot->bus == bus && slot->devfn == devfn) {
-			found = slot;
-			break;
-		}
-	}
-	spin_unlock(&list_lock);
-	return found;
-}
-
 /* This is the interrupt mode interrupt handler */
 irqreturn_t
 cpci_hp_intr(int irq, void *data, struct pt_regs *regs)
@@ -924,6 +896,5 @@
 EXPORT_SYMBOL_GPL(cpci_hp_unregister_controller);
 EXPORT_SYMBOL_GPL(cpci_hp_register_bus);
 EXPORT_SYMBOL_GPL(cpci_hp_unregister_bus);
-EXPORT_SYMBOL_GPL(cpci_find_slot);
 EXPORT_SYMBOL_GPL(cpci_hp_start);
 EXPORT_SYMBOL_GPL(cpci_hp_stop);
diff -Nru a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
--- a/drivers/pci/hotplug/cpci_hotplug_pci.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/pci/hotplug/cpci_hotplug_pci.c	Sat Jul 19 12:54:25 2003
@@ -448,7 +448,7 @@
 }
 
 static int configure_visit_pci_dev(struct pci_dev_wrapped *wrapped_dev,
-			struct pci_bus_wrapped *wrapped_bus)
+				   struct pci_bus_wrapped *wrapped_bus)
 {
 	int rc;
 	struct pci_dev *dev = wrapped_dev->dev;
@@ -461,8 +461,8 @@
 	 * We need to fix up the hotplug representation with the Linux
 	 * representation.
 	 */
-	slot = cpci_find_slot(dev->bus, dev->devfn);
-	if(slot) {
+	if(wrapped_dev->data) {
+		slot = (struct slot*) wrapped_dev->data;
 		slot->dev = dev;
 	}
 
@@ -494,9 +494,7 @@
 		return -ENODEV;
 
 	/* Remove the Linux representation */
-	if(pci_remove_device_safe(dev) == 0) {
-		kfree(dev);
-	} else {
+	if(pci_remove_device_safe(dev)) {
 		err("Could not remove device\n");
 		return -1;
 	}
@@ -504,8 +502,8 @@
 	/*
 	 * Now remove the hotplug representation.
 	 */
-	slot = cpci_find_slot(dev->bus, dev->devfn);
-	if(slot) {
+	if(wrapped_dev->data) {
+		slot = (struct slot*) wrapped_dev->data;
 		slot->dev = NULL;
 	} else {
 		dbg("No hotplug representation for %02x:%02x.%x",
@@ -574,13 +572,18 @@
 
 	/* Still NULL? Well then scan for it! */
 	if(slot->dev == NULL) {
+		int n;
 		dbg("pci_dev still null");
 
 		/*
 		 * This will generate pci_dev structures for all functions, but
 		 * we will only call this case when lookup fails.
 		 */
-		slot->dev = pci_scan_slot(slot->bus, slot->devfn);
+		n = pci_scan_slot(slot->bus, slot->devfn);
+		dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n);
+		if(n > 0)
+			pci_bus_add_devices(slot->bus);
+		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;
@@ -603,6 +606,10 @@
 				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);
 		}
 	}
@@ -635,9 +642,14 @@
 		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);
+					   &wrapped_dev,
+					   &wrapped_bus);
 			if(rc)
 				break;
 		}
diff -Nru a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c
--- a/drivers/pci/hotplug.c	Sat Jul 19 12:54:28 2003
+++ b/drivers/pci/hotplug.c	Sat Jul 19 12:54:28 2003
@@ -10,8 +10,6 @@
 #define DBG(x...)
 #endif
 
-static void pci_free_resources(struct pci_dev *dev);
-
 int pci_hotplug (struct device *dev, char **envp, int num_envp,
 		 char *buffer, int buffer_size)
 {
@@ -57,7 +55,7 @@
 
 	envp[i++] = scratch;
 	length += snprintf (scratch, buffer_size - length, "PCI_SLOT_NAME=%s",
-			    pdev->slot_name);
+			    pci_name(pdev));
 	if ((buffer_size - length <= 0) || (i >= num_envp))
 		return -ENOMEM;
 
@@ -172,105 +170,3 @@
 }
 EXPORT_SYMBOL(pci_visit_dev);
 
-static void pci_destroy_dev(struct pci_dev *dev)
-{
-	pci_proc_detach_device(dev);
-	device_unregister(&dev->dev);
-
-	/* Remove the device from the device lists, and prevent any further
-	 * list accesses from this device */
-	spin_lock(&pci_bus_lock);
-	list_del(&dev->bus_list);
-	list_del(&dev->global_list);
-	dev->bus_list.next = dev->bus_list.prev = NULL;
-	dev->global_list.next = dev->global_list.prev = NULL;
-	spin_unlock(&pci_bus_lock);
-
-	pci_free_resources(dev);
-	pci_dev_put(dev);
-}
-
-/**
- * pci_remove_device_safe - remove an unused hotplug device
- * @dev: the device to remove
- *
- * Delete the device structure from the device lists and 
- * notify userspace (/sbin/hotplug), but only if the device
- * in question is not being used by a driver.
- * Returns 0 on success.
- */
-int pci_remove_device_safe(struct pci_dev *dev)
-{
-	if (pci_dev_driver(dev))
-		return -EBUSY;
-	pci_destroy_dev(dev);
-	return 0;
-}
-EXPORT_SYMBOL(pci_remove_device_safe);
-
-static void
-pci_free_resources(struct pci_dev *dev)
-{
-	int i;
-
-	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-		struct resource *res = dev->resource + i;
-		if (res->parent)
-			release_resource(res);
-	}
-}
-
-/**
- * pci_remove_bus_device - remove a PCI device and any children
- * @dev: the device to remove
- *
- * Remove a PCI device from the device lists, informing the drivers
- * that the device has been removed.  We also remove any subordinate
- * buses and children in a depth-first manner.
- *
- * For each device we remove, delete the device structure from the
- * device lists, remove the /proc entry, and notify userspace
- * (/sbin/hotplug).
- */
-void pci_remove_bus_device(struct pci_dev *dev)
-{
-	if (dev->subordinate) {
-		struct pci_bus *b = dev->subordinate;
-
-		pci_remove_behind_bridge(dev);
-		pci_proc_detach_bus(b);
-
-		spin_lock(&pci_bus_lock);
-		list_del(&b->node);
-		spin_unlock(&pci_bus_lock);
-
-		kfree(b);
-		dev->subordinate = NULL;
-	}
-
-	pci_destroy_dev(dev);
-}
-
-/**
- * pci_remove_behind_bridge - remove all devices behind a PCI bridge
- * @dev: PCI bridge device
- *
- * Remove all devices on the bus, except for the parent bridge.
- * This also removes any child buses, and any devices they may
- * contain in a depth-first manner.
- */
-void pci_remove_behind_bridge(struct pci_dev *dev)
-{
-	struct list_head *l, *n;
-
-	if (dev->subordinate) {
-		list_for_each_safe(l, n, &dev->subordinate->devices) {
-			struct pci_dev *dev = pci_dev_b(l);
-
-			pci_remove_bus_device(dev);
-		}
-	}
-}
-
-EXPORT_SYMBOL(pci_remove_bus_device);
-EXPORT_SYMBOL(pci_remove_behind_bridge);
diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c
--- a/drivers/pci/pci.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/pci/pci.c	Sat Jul 19 12:54:24 2003
@@ -506,7 +506,7 @@
 		pci_resource_flags(pdev, bar) & IORESOURCE_IO ? "I/O" : "mem",
 		bar + 1, /* PCI BAR # */
 		pci_resource_len(pdev, bar), pci_resource_start(pdev, bar),
-		pdev->slot_name);
+		pci_name(pdev));
 	return -EBUSY;
 }
 
@@ -555,7 +555,7 @@
 		pci_resource_flags(pdev, i) & IORESOURCE_IO ? "I/O" : "mem",
 		i + 1, /* PCI BAR # */
 		pci_resource_len(pdev, i), pci_resource_start(pdev, i),
-		pdev->slot_name);
+		pci_name(pdev));
 	while(--i >= 0)
 		pci_release_region(pdev, i);
 		
@@ -576,7 +576,7 @@
 
 	pci_read_config_word(dev, PCI_COMMAND, &cmd);
 	if (! (cmd & PCI_COMMAND_MASTER)) {
-		DBG("PCI: Enabling bus mastering for device %s\n", dev->slot_name);
+		DBG("PCI: Enabling bus mastering for device %s\n", pci_name(dev));
 		cmd |= PCI_COMMAND_MASTER;
 		pci_write_config_word(dev, PCI_COMMAND, cmd);
 	}
@@ -620,7 +620,7 @@
 		return 0;
 
 	printk(KERN_WARNING "PCI: cache line size of %d is not supported "
-	       "by device %s\n", pci_cache_line_size << 2, dev->slot_name);
+	       "by device %s\n", pci_cache_line_size << 2, pci_name(dev));
 
 	return -EINVAL;
 }
@@ -653,7 +653,7 @@
 
 	pci_read_config_word(dev, PCI_COMMAND, &cmd);
 	if (! (cmd & PCI_COMMAND_INVALIDATE)) {
-		DBG("PCI: Enabling Mem-Wr-Inval for device %s\n", dev->slot_name);
+		DBG("PCI: Enabling Mem-Wr-Inval for device %s\n", pci_name(dev));
 		cmd |= PCI_COMMAND_INVALIDATE;
 		pci_write_config_word(dev, PCI_COMMAND, cmd);
 	}
diff -Nru a/drivers/pci/pool.c b/drivers/pci/pool.c
--- a/drivers/pci/pool.c	Sat Jul 19 12:54:29 2003
+++ b/drivers/pci/pool.c	Sat Jul 19 12:54:29 2003
@@ -233,7 +233,7 @@
 				struct pci_page, page_list);
 		if (is_page_busy (pool->blocks_per_page, page->bitmap)) {
 			printk (KERN_ERR "pci_pool_destroy %s/%s, %p busy\n",
-				pool->dev ? pool->dev->slot_name : NULL,
+				pool->dev ? pci_name(pool->dev) : NULL,
 				pool->name, page->vaddr);
 			/* leak the still-in-use consistent memory */
 			list_del (&page->page_list);
@@ -359,7 +359,7 @@
 
 	if ((page = pool_find_page (pool, dma)) == 0) {
 		printk (KERN_ERR "pci_pool_free %s/%s, %p/%lx (bad dma)\n",
-			pool->dev ? pool->dev->slot_name : NULL,
+			pool->dev ? pci_name(pool->dev) : NULL,
 			pool->name, vaddr, (unsigned long) dma);
 		return;
 	}
@@ -372,13 +372,13 @@
 #ifdef	CONFIG_DEBUG_SLAB
 	if (((dma - page->dma) + (void *)page->vaddr) != vaddr) {
 		printk (KERN_ERR "pci_pool_free %s/%s, %p (bad vaddr)/%Lx\n",
-			pool->dev ? pool->dev->slot_name : NULL,
+			pool->dev ? pci_name(pool->dev) : NULL,
 			pool->name, vaddr, (unsigned long long) dma);
 		return;
 	}
 	if (page->bitmap [map] & (1UL << block)) {
 		printk (KERN_ERR "pci_pool_free %s/%s, dma %Lx already free\n",
-			pool->dev ? pool->dev->slot_name : NULL,
+			pool->dev ? pci_name(pool->dev) : NULL,
 			pool->name, (unsigned long long)dma);
 		return;
 	}
diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c
--- a/drivers/pci/quirks.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/pci/quirks.c	Sat Jul 19 12:54:21 2003
@@ -33,7 +33,7 @@
 	while ((d = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, d))) {
 		pci_read_config_byte(d, 0x82, &dlc);
 		if (!(dlc & 1<<1)) {
-			printk(KERN_ERR "PCI: PIIX3: Enabling Passive Release on %s\n", d->slot_name);
+			printk(KERN_ERR "PCI: PIIX3: Enabling Passive Release on %s\n", pci_name(d));
 			dlc |= 1<<1;
 			pci_write_config_byte(d, 0x82, dlc);
 		}
@@ -437,7 +437,7 @@
 
 	if (new_irq != irq) {
 		printk(KERN_INFO "PCI: Via IRQ fixup for %s, from %d to %d\n",
-		       dev->slot_name, irq, new_irq);
+		       pci_name(dev), irq, new_irq);
 
 		udelay(15);
 		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
@@ -598,7 +598,7 @@
                return;
 
        printk(KERN_INFO "PCI: Ignoring BAR%d-%d of IDE controller %s\n",
-              first_bar, last_bar, dev->slot_name);
+              first_bar, last_bar, pci_name(dev));
 }
 
 /*
@@ -856,7 +856,7 @@
  		    (f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
  		    (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
 #ifdef DEBUG
-			printk(KERN_INFO "PCI: Calling quirk %p for %s\n", f->hook, dev->slot_name);
+			printk(KERN_INFO "PCI: Calling quirk %p for %s\n", f->hook, pci_name(dev));
 #endif
 			f->hook(dev);
 		}
diff -Nru a/drivers/pci/remove.c b/drivers/pci/remove.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pci/remove.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,113 @@
+#include <linux/pci.h>
+#include <linux/module.h>
+#include "pci.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+static void pci_free_resources(struct pci_dev *dev)
+{
+	int i;
+
+	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+		struct resource *res = dev->resource + i;
+		if (res->parent)
+			release_resource(res);
+	}
+}
+
+static void pci_destroy_dev(struct pci_dev *dev)
+{
+	pci_proc_detach_device(dev);
+	device_unregister(&dev->dev);
+
+	/* Remove the device from the device lists, and prevent any further
+	 * list accesses from this device */
+	spin_lock(&pci_bus_lock);
+	list_del(&dev->bus_list);
+	list_del(&dev->global_list);
+	dev->bus_list.next = dev->bus_list.prev = NULL;
+	dev->global_list.next = dev->global_list.prev = NULL;
+	spin_unlock(&pci_bus_lock);
+
+	pci_free_resources(dev);
+	pci_dev_put(dev);
+}
+
+/**
+ * pci_remove_device_safe - remove an unused hotplug device
+ * @dev: the device to remove
+ *
+ * Delete the device structure from the device lists and 
+ * notify userspace (/sbin/hotplug), but only if the device
+ * in question is not being used by a driver.
+ * Returns 0 on success.
+ */
+int pci_remove_device_safe(struct pci_dev *dev)
+{
+	if (pci_dev_driver(dev))
+		return -EBUSY;
+	pci_destroy_dev(dev);
+	return 0;
+}
+EXPORT_SYMBOL(pci_remove_device_safe);
+
+/**
+ * pci_remove_bus_device - remove a PCI device and any children
+ * @dev: the device to remove
+ *
+ * Remove a PCI device from the device lists, informing the drivers
+ * that the device has been removed.  We also remove any subordinate
+ * buses and children in a depth-first manner.
+ *
+ * For each device we remove, delete the device structure from the
+ * device lists, remove the /proc entry, and notify userspace
+ * (/sbin/hotplug).
+ */
+void pci_remove_bus_device(struct pci_dev *dev)
+{
+	if (dev->subordinate) {
+		struct pci_bus *b = dev->subordinate;
+
+		pci_remove_behind_bridge(dev);
+		pci_proc_detach_bus(b);
+
+		spin_lock(&pci_bus_lock);
+		list_del(&b->node);
+		spin_unlock(&pci_bus_lock);
+
+		kfree(b);
+		dev->subordinate = NULL;
+	}
+
+	pci_destroy_dev(dev);
+}
+
+/**
+ * pci_remove_behind_bridge - remove all devices behind a PCI bridge
+ * @dev: PCI bridge device
+ *
+ * Remove all devices on the bus, except for the parent bridge.
+ * This also removes any child buses, and any devices they may
+ * contain in a depth-first manner.
+ */
+void pci_remove_behind_bridge(struct pci_dev *dev)
+{
+	struct list_head *l, *n;
+
+	if (dev->subordinate) {
+		list_for_each_safe(l, n, &dev->subordinate->devices) {
+			struct pci_dev *dev = pci_dev_b(l);
+
+			pci_remove_bus_device(dev);
+		}
+	}
+}
+
+EXPORT_SYMBOL(pci_remove_bus_device);
+EXPORT_SYMBOL(pci_remove_behind_bridge);
diff -Nru a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
--- a/drivers/pci/setup-bus.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/pci/setup-bus.c	Sat Jul 19 12:54:30 2003
@@ -81,7 +81,7 @@
 	struct pci_bus_region region;
 
 	printk("PCI: Bus %d, cardbus bridge: %s\n",
-		bus->number, bridge->slot_name);
+		bus->number, pci_name(bridge));
 
 	pcibios_resource_to_bus(bridge, &region, bus->resource[0]);
 	if (bus->resource[0]->flags & IORESOURCE_IO) {
@@ -344,7 +344,7 @@
 			if (order > 11) {
 				printk(KERN_WARNING "PCI: region %s/%d "
 				       "too large: %lx-%lx\n",
-				       dev->slot_name, i, r->start, r->end);
+				       pci_name(dev), i, r->start, r->end);
 				r->flags = 0;
 				continue;
 			}
@@ -513,7 +513,7 @@
 
 		default:
 			printk(KERN_INFO "PCI: not setting up bridge %s "
-			       "for bus %d\n", dev->slot_name, b->number);
+			       "for bus %d\n", pci_name(dev), b->number);
 			break;
 		}
 	}
diff -Nru a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
--- a/drivers/pci/setup-res.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/pci/setup-res.c	Sat Jul 19 12:54:27 2003
@@ -68,7 +68,7 @@
 
 	if ((new ^ check) & mask) {
 		printk(KERN_ERR "PCI: Error while updating region "
-		       "%s/%d (%08x != %08x)\n", dev->slot_name, resno,
+		       "%s/%d (%08x != %08x)\n", pci_name(dev), resno,
 		       new, check);
 	}
 
@@ -80,7 +80,7 @@
 		if (check != new) {
 			printk(KERN_ERR "PCI: Error updating region "
 			       "%s/%d (high %08x != %08x)\n",
-			       dev->slot_name, resno, new, check);
+			       pci_name(dev), resno, new, check);
 		}
 	}
 }
@@ -101,7 +101,7 @@
 		printk(KERN_ERR "PCI: %s region %d of %s %s [%lx:%lx]\n",
 		       root ? "Address space collision on" :
 			      "No parent found for",
-		       resource, dtype, dev->slot_name, res->start, res->end);
+		       resource, dtype, pci_name(dev), res->start, res->end);
 	}
 
 	return err;
@@ -139,7 +139,7 @@
 
 	if (ret) {
 		printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n",
-		       resno, res->start, res->end, dev->slot_name);
+		       resno, res->start, res->end, pci_name(dev));
 	} else if (resno < PCI_BRIDGE_RESOURCES) {
 		pci_update_resource(dev, res, resno);
 	}
diff -Nru a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
--- a/drivers/pcmcia/hd64465_ss.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/pcmcia/hd64465_ss.c	Sat Jul 19 12:54:25 2003
@@ -1,5 +1,5 @@
 /*
- * $Id$
+ * $Id: hd64465_ss.c,v 1.7 2003/07/06 14:42:50 lethal Exp $
  *
  * Device driver for the PCMCIA controller module of the
  * Hitachi HD64465 handheld companion chip.
@@ -24,7 +24,6 @@
  *
  * by Greg Banks <gbanks@pocketpenguins.com>
  * (c) 2000 PocketPenguins Inc
- *
  */
 
 #include <linux/types.h>
@@ -37,28 +36,26 @@
 #include <linux/vmalloc.h>
 #include <asm/errno.h>
 #include <linux/irq.h>
-#include <linux/workqueue.h>
+#include <linux/interrupt.h>
 #include <linux/device.h>
 
 #include <asm/io.h>
-#include <asm/hd64465.h>
+#include <asm/hd64465/hd64465.h>
+#include <asm/hd64465/io.h>
 
 #include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/bulkmem.h>
-#include <pcmcia/cistpl.h>
 #include "cs_internal.h"
 
 #define MODNAME "hd64465_ss"
 
 /* #define HD64465_DEBUG 1 */
 
-#ifndef HD64465_DEBUG
-#define HD64465_DEBUG 0
-#endif
-
 #if HD64465_DEBUG
 #define DPRINTK(args...)	printk(MODNAME ": " args)
 #else
@@ -66,7 +63,8 @@
 #endif
 
 extern int hd64465_io_debug;
-
+extern void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);
+extern void p3_iounmap(void *addr);
 
 /*============================================================*/
 
@@ -74,37 +72,22 @@
 
 typedef struct hs_socket_t
 {
+    unsigned int	number;
     u_int   	    	irq;
     u_long  	    	mem_base;
+    void		*io_base;
     u_long  	    	mem_length;
-    void	    	(*handler)(void *info, u_int events);
-    void    	    	*handler_info;
-    u_int   	    	pending_events;
     u_int   	    	ctrl_base;
     socket_state_t  	state;
     pccard_io_map     	io_maps[MAX_IO_WIN];
     pccard_mem_map  	mem_maps[MAX_WIN];
-    struct vm_struct	*io_vma;    /* allocated kernel vm for mapping IO space */
+    struct pcmcia_socket	socket;
 } hs_socket_t;
 
-#define HS_MAX_SOCKETS 2
-static hs_socket_t hs_sockets[HS_MAX_SOCKETS];
-static spinlock_t hs_pending_event_lock = SPIN_LOCK_UNLOCKED;
 
-/* Calculate socket number from ptr into hs_sockets[] */
-#define hs_sockno(sp) 	(sp - hs_sockets)
 
-static socket_cap_t hs_socket_cap =
-{
-    SS_CAP_PCCARD   	    /* support 16 bit cards */
-    |SS_CAP_STATIC_MAP      /* mappings are fixed in host memory */
-    ,
-    0xffde/*0xffff*/, 	    /* IRQs mapped in s/w so can do any, really */
-    HD64465_PCC_WINDOW,     /* 16MB fixed window size */
-    0,	    	    	    /* no PCI support */
-    0,	    	    	    /* no CardBus support */
-    0	    	    	    /* no bus operations needed */
-};
+#define HS_MAX_SOCKETS 2
+static hs_socket_t hs_sockets[HS_MAX_SOCKETS];
 
 #define hs_in(sp, r)	    inb((sp)->ctrl_base + (r))
 #define hs_out(sp, v, r)    outb(v, (sp)->ctrl_base + (r))
@@ -179,7 +162,7 @@
 {
     	unsigned short cscier;
 	
-    	DPRINTK("hs_socket_enable_ireq(sock=%d)\n", hs_sockno(sp));
+    	DPRINTK("hs_socket_enable_ireq(sock=%d)\n", sp->number);
 
     	cscier = hs_in(sp, CSCIER);
 	cscier &= ~HD64465_PCCCSCIER_PIREQE_MASK;
@@ -191,7 +174,7 @@
 {
     	unsigned short cscier;
 	
-    	DPRINTK("hs_socket_disable_ireq(sock=%d)\n", hs_sockno(sp));
+    	DPRINTK("hs_socket_disable_ireq(sock=%d)\n", sp->number);
 	
     	cscier = hs_in(sp, CSCIER);
 	cscier &= ~HD64465_PCCCSCIER_PIREQE_MASK;
@@ -255,7 +238,7 @@
  */
 static void hs_map_irq(hs_socket_t *sp, unsigned int irq)
 {
-    	DPRINTK("hs_map_irq(sock=%d irq=%d)\n", hs_sockno(sp), irq);
+    	DPRINTK("hs_map_irq(sock=%d irq=%d)\n", sp->number, irq);
 	
 	if (irq >= HS_NUM_MAPPED_IRQS)
 	    return;
@@ -272,7 +255,7 @@
  */
 static void hs_unmap_irq(hs_socket_t *sp, unsigned int irq)
 {
-    	DPRINTK("hs_unmap_irq(sock=%d irq=%d)\n", hs_sockno(sp), irq);
+    	DPRINTK("hs_unmap_irq(sock=%d irq=%d)\n", sp->number, irq);
 	
 	if (irq >= HS_NUM_MAPPED_IRQS)
 	    return;
@@ -301,7 +284,7 @@
 {
     	u_int psr;
 	u_int vcci = 0;
-	u_int sock = hs_sockno(sp);
+	u_int sock = sp->number;
 	
     	DPRINTK("hs_set_voltage(%d, %d, %d)\n", sock, Vcc, Vpp);
 
@@ -359,13 +342,12 @@
 
 /*============================================================*/
 
-static int hs_init(unsigned int sock)
+static int hs_init(struct pcmcia_socket *s)
 {
-    	hs_socket_t *sp = &hs_sockets[sock];
+    	hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
 	
-    	DPRINTK("hs_init(%d)\n", sock);
+    	DPRINTK("hs_init(%d)\n", sp->number);
 	
-	sp->pending_events = 0;
 	sp->state.Vcc = 0;
 	sp->state.Vpp = 0;
 	hs_set_voltages(sp, 0, 0);
@@ -375,9 +357,12 @@
 
 /*============================================================*/
 
-static int hs_suspend(unsigned int sock)
+static int hs_suspend(struct pcmcia_socket *s)
 {
-    	DPRINTK("hs_suspend(%d)\n", sock);
+#ifdef HD64465_DEBUG
+    	hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
+    	DPRINTK("hs_suspend(%d)\n", sp->number);
+#endif
 
     	/* TODO */
 	
@@ -386,32 +371,10 @@
 
 /*============================================================*/
 
-static int hs_register_callback(unsigned int sock,
-    	    void (*handler)(void *, unsigned int), void * info)
-{
-    	hs_socket_t *sp = &hs_sockets[sock];
-	
-    	DPRINTK("hs_register_callback(%d)\n", sock);
-	sp->handler = handler;
-	sp->handler_info = info;
-	return 0;
-}
-
-/*============================================================*/
 
-static int hs_inquire_socket(unsigned int sock, socket_cap_t *cap)
+static int hs_get_status(struct pcmcia_socket *s, u_int *value)
 {
-    	DPRINTK("hs_inquire_socket(%d)\n", sock);
-
-	*cap = hs_socket_cap;
-	return 0;
-}
-
-/*============================================================*/
-
-static int hs_get_status(unsigned int sock, u_int *value)
-{
-    	hs_socket_t *sp = &hs_sockets[sock];
+    	hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
     	unsigned int isr;
 	u_int status = 0;
 	
@@ -473,9 +436,9 @@
 
 /*============================================================*/
 
-static int hs_get_socket(unsigned int sock, socket_state_t *state)
+static int hs_get_socket(struct pcmcia_socket *s, socket_state_t *state)
 {
-    	hs_socket_t *sp = &hs_sockets[sock];
+    	hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
 
     	DPRINTK("hs_get_socket(%d)\n", sock);
 	
@@ -485,9 +448,9 @@
 
 /*============================================================*/
 
-static int hs_set_socket(unsigned int sock, socket_state_t *state)
+static int hs_set_socket(struct pcmcia_socket *s, socket_state_t *state)
 {
-    	hs_socket_t *sp = &hs_sockets[sock];
+    	hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
     	u_long flags;
 	u_int changed;
 	unsigned short cscier;
@@ -495,12 +458,12 @@
     	DPRINTK("hs_set_socket(sock=%d, flags=%x, csc_mask=%x, Vcc=%d, Vpp=%d, io_irq=%d)\n",
 	    sock, state->flags, state->csc_mask, state->Vcc, state->Vpp, state->io_irq);
 	
-	save_and_cli(flags);	/* Don't want interrupts happening here */
+	local_irq_save(flags);	/* Don't want interrupts happening here */
 
 	if (state->Vpp != sp->state.Vpp ||
 	    state->Vcc != sp->state.Vcc) {
 	    if (!hs_set_voltages(sp, state->Vcc, state->Vpp)) {
-	    	restore_flags(flags);
+	    	local_irq_restore(flags);
 	    	return -EINVAL;
 	    }
 	}
@@ -588,7 +551,7 @@
 /*    	hd64465_io_debug = 0; */
 	sp->state = *state;
 	    
-	restore_flags(flags);
+	local_irq_restore(flags);
 
 #if HD64465_DEBUG > 10
 	if (state->flags & SS_OUTPUT_ENA)   
@@ -599,10 +562,11 @@
 
 /*============================================================*/
 
-static int hs_set_io_map(unsigned int sock, struct pccard_io_map *io)
+static int hs_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
 {
-    	hs_socket_t *sp = &hs_sockets[sock];
+    	hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
 	int map = io->map;
+	int sock = sp->number;
 	struct pccard_io_map *sio;
 	pgprot_t prot;
 
@@ -639,10 +603,9 @@
 	    printk(KERN_INFO MODNAME ": MAP_0WS unimplemented\n");
 
 	if (io->flags & MAP_ACTIVE) {
-	    unsigned long pstart, psize, paddrbase, vaddrbase;
+	    unsigned long pstart, psize, paddrbase;
 	    
 	    paddrbase = virt_to_phys((void*)(sp->mem_base + 2 * HD64465_PCC_WINDOW));
-	    vaddrbase = (unsigned long)sp->io_vma->addr;
 	    pstart = io->start & PAGE_MASK;
 	    psize = ((io->stop + PAGE_SIZE) & PAGE_MASK) - pstart;
 
@@ -653,26 +616,17 @@
 	     * page will be mapped.  But the code allows for weird cards
 	     * that might want IO ports > 4K.
 	     */
-	    DPRINTK("remap_page_range(vaddr=0x%08lx, paddr=0x%08lx, size=0x%08lxx)\n",
-	    	vaddrbase + pstart, paddrbase + pstart, psize);
-#error This does not work.  Firstly remap_page_range() uses current->mm for
-#error the address space, which is wrong for kernel mappings.  remap_page_range
-#error also does flush_{cache,tlb}_range() which ONLY works for user mappings.
-#error Next, remap_page_range() now wants to take a vm_area_struct arg.
-	    remap_page_range(vaddrbase + pstart, paddrbase + pstart, psize, prot);
+	    sp->io_base = p3_ioremap(paddrbase + pstart, psize, pgprot_val(prot));
 	    
 	    /*
 	     * Change the mapping used by inb() outb() etc
 	     */
-	    hd64465_port_map(
-	    	io->start,
+	    hd64465_port_map(io->start,
 		io->stop - io->start + 1,
-	    	vaddrbase + io->start,0);
+	    	(unsigned long)sp->io_base + io->start, 0);
 	} else {
-	    hd64465_port_unmap(
-	    	sio->start,
-		sio->stop - sio->start + 1);
-	    /* TODO: remap_page_range() to mark pages not present ? */
+	    hd64465_port_unmap(sio->start, sio->stop - sio->start + 1);
+	    p3_iounmap(sp->io_base);
 	}
 	
 	*sio = *io;
@@ -681,9 +635,9 @@
 
 /*============================================================*/
 
-static int hs_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+static int hs_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
 {
-    	hs_socket_t *sp = &hs_sockets[sock];
+    	hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
 	struct pccard_mem_map *smem;
 	int map = mem->map;
 	unsigned long paddr, size;
@@ -722,13 +676,6 @@
 
 /*============================================================*/
 
-static void hs_proc_setup(unsigned int sock, struct proc_dir_entry *base)
-{
-    	DPRINTK("hs_proc_setup(%d)\n", sock);
-}
-
-/*============================================================*/
-
 /*
  * This function is registered with the HD64465 glue code to do a
  * secondary demux step on the PCMCIA interrupts.  It handles 
@@ -756,35 +703,9 @@
 
 /*
  * Interrupt handling routine.
- *
- * This uses the schedule_work() technique to cause reportable events
- * such as card insertion and removal to be handled in keventd's
- * process context.
  */
  
-
-static void hs_events_bh(void *dummy)
-{
-	hs_socket_t *sp;
-	u_int events;
-	int i;
-
-	for (i=0; i<HS_MAX_SOCKETS; i++) {
-	    sp = &hs_sockets[i];
-
-	    spin_lock_irq(&hs_pending_event_lock);
-	    events = sp->pending_events;
-	    sp->pending_events = 0;
-	    spin_unlock_irq(&hs_pending_event_lock);
-	    
-	    if (sp->handler)
-		sp->handler(sp->handler_info, events);
-	}
-}
-
-static DECLARE_WORK(hs_events_task, hs_events_bh, NULL);
-
-static void hs_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t hs_interrupt(int irq, void *dev, struct pt_regs *regs)
 {
     	hs_socket_t *sp = (hs_socket_t *)dev;
 	u_int events = 0;
@@ -801,7 +722,7 @@
 	    if ((hs_in(sp, ISR) & HD64465_PCCISR_PCD_MASK) != 0) {
 	    	printk(KERN_NOTICE MODNAME
 		    ": socket %d, card not a supported card type or not inserted correctly\n",
-		    hs_sockno(sp));
+		    sp->number);
 		/* Don't do the rest unless a card is present */
 		cscr &= ~(HD64465_PCCCSCR_PCDC|
 		    	  HD64465_PCCCSCR_PRC|
@@ -839,34 +760,22 @@
 
 	hs_out(sp, cscr, CSCR);
 
-	if (events) {
-	    /*
-    	     * Arrange for events to be reported to the registered
-	     * event handler function (from CardServices) in a process
-	     * context (keventd) "soon".
-	     */
-	    spin_lock(&hs_pending_event_lock);
-	    sp->pending_events |= events;
-	    spin_unlock(&hs_pending_event_lock);
-	    
-	    schedule_work(&hs_events_task);
-	}
+	if (events)
+		pcmcia_parse_events(&sp->socket, events);
+
+	return IRQ_HANDLED;
 }
 
 /*============================================================*/
 
 static struct pccard_operations hs_operations = {
-	.owner			= THIS_MODULE,
 	.init			= hs_init,
 	.suspend		= hs_suspend,
-	.register_callback	= hs_register_callback,
-	.inquire_socket		= hs_inquire_socket,
 	.get_status		= hs_get_status,
 	.get_socket		= hs_get_socket,
 	.set_socket		= hs_set_socket,
 	.set_io_map		= hs_set_io_map,
 	.set_mem_map		= hs_set_mem_map,
-	.proc_setup		= hs_proc_setup,
 };
 
 static int hs_init_socket(hs_socket_t *sp, int irq, unsigned long mem_base,
@@ -886,9 +795,6 @@
 	for (i=0 ; i<MAX_WIN ; i++)
 	    sp->mem_maps[i].map = i;
 	
-	if ((sp->io_vma = get_vm_area(HS_IO_MAP_SIZE, VM_IOREMAP)) == 0)
-	    return -ENOMEM;
-
 	hd64465_register_irq_demux(sp->irq, hs_irq_demux, sp);
 	
     	if ((err = request_irq(sp->irq, hs_interrupt, SA_INTERRUPT, MODNAME, sp)) < 0)
@@ -925,9 +831,8 @@
 	
 	hs_reset_socket(sp, 1);
 
-	printk(KERN_INFO "HD64465 PCMCIA bridge socket %d at 0x%08lx irq %d io window %ldK@0x%08lx\n",
-	    	i, sp->mem_base, sp->irq,
-		sp->io_vma->size>>10, (unsigned long)sp->io_vma->addr);
+	printk(KERN_INFO "HD64465 PCMCIA bridge socket %d at 0x%08lx irq %d\n",
+	    	i, sp->mem_base, sp->irq);
 
     	return 0;
 }
@@ -935,7 +840,10 @@
 static void hs_exit_socket(hs_socket_t *sp)
 {
     	unsigned short cscier, gcr;
+	unsigned long flags;
 	
+	local_irq_save(flags);
+
 	/* turn off interrupts in hardware */
     	cscier = hs_in(sp, CSCIER);
 	cscier = (cscier & IER_MASK) | IER_OFF;
@@ -955,19 +863,13 @@
 	    free_irq(sp->irq, hs_interrupt);
     	    hd64465_unregister_irq_demux(sp->irq);
 	}
-	if (sp->io_vma != 0)
-	    vfree(sp->io_vma->addr);
-}
 
-static struct pcmcia_socket_class_data hd64465_data = {
-	.nsock = HS_MAX_SOCKETS,
-	.ops = &hs_operations,
-};
+	local_irq_restore(flags);
+}
 
 static struct device_driver hd64465_driver = {
 	.name = "hd64465-pcmcia",
 	.bus = &platform_bus_type,
-	.devclass = &pcmcia_socket_class,
 	.suspend = pcmcia_socket_dev_suspend,
 	.resume = pcmcia_socket_dev_resume,
 };
@@ -996,7 +898,8 @@
 	}
 
 /*	hd64465_io_debug = 1; */
-	register_driver(&hd64465_driver);
+	if (driver_register(&hd64465_driver))
+		return -EINVAL;
 	
 	/* Wake both sockets out of STANDBY mode */
 	/* TODO: wait 15ms */
@@ -1014,14 +917,22 @@
 	v |= HD64465_PCCCSCR_PSWSEL;
 	outb(v, HD64465_REG_PCC0CSCR);
 
-    	hs_set_voltages(&hs_sockets[0], 0, 0);
-    	hs_set_voltages(&hs_sockets[1], 0, 0);
-	
 	/*
 	 * Setup hs_sockets[] structures and request system resources.
 	 * TODO: on memory allocation failure, power down the socket
 	 *       before quitting.
 	 */
+	for (i=0; i<HS_MAX_SOCKETS; i++) {
+		hs_set_voltages(&hs_sockets[i], 0, 0);
+
+		hs_sockets[i].socket.features |=  SS_CAP_PCCARD | SS_CAP_STATIC_MAP;      /* mappings are fixed in host memory */
+		hs_sockets[i].socket.irq_mask =  0xffde;/*0xffff*/	    /* IRQs mapped in s/w so can do any, really */
+		hs_sockets[i].socket.map_size = HD64465_PCC_WINDOW;     /* 16MB fixed window size */
+
+		hs_sockets[i].socket.owner = THIS_MODULE;
+		hs_sockets[i].socket.ss_entry = &hs_operations;
+	}
+
 	i = hs_init_socket(&hs_sockets[0],
 	    HD64465_IRQ_PCMCIA0,
 	    HD64465_PCC0_BASE,
@@ -1040,27 +951,31 @@
 	}
 
 /*	hd64465_io_debug = 0; */
-	hd64465_device.dev.class_data = &hd64465_data;
+
 	platform_device_register(&hd64465_device);
 
-	return 0;
+	for (i=0; i<HS_MAX_SOCKETS; i++) {
+		unsigned int ret;
+		hs_sockets[i].socket.dev.dev = &hd64465_device.dev;		
+		hs_sockets[i].number = i;
+		ret = pcmcia_register_socket(&hs_sockets[i].socket);
+		if (ret && i)
+			pcmcia_unregister_socket(&hs_sockets[0].socket);
+	}
+
+    	return 0;
 }
 
 static void __exit exit_hs(void)
 {
-    	u_long flags;
 	int i;
-	
-	save_and_cli(flags);
 
-    	/*
-	 * Release kernel resources
-	 */
-	for (i=0 ; i<HS_MAX_SOCKETS ; i++)
-	    hs_exit_socket(&hs_sockets[i]);
+	for (i=0 ; i<HS_MAX_SOCKETS ; i++) {
+		pcmcia_unregister_socket(&hs_sockets[i].socket);
+		hs_exit_socket(&hs_sockets[i]);
+	}
+
 	platform_device_unregister(&hd64465_device);
-	
-	restore_flags(flags);
 	unregister_driver(&hd64465_driver);
 }
 
diff -Nru a/drivers/pcmcia/ricoh.h b/drivers/pcmcia/ricoh.h
--- a/drivers/pcmcia/ricoh.h	Sat Jul 19 12:54:25 2003
+++ b/drivers/pcmcia/ricoh.h	Sat Jul 19 12:54:25 2003
@@ -116,6 +116,8 @@
 #define  RL5C4XX_CMD_SHIFT		4
 #define  RL5C4XX_HOLD_MASK		0x1c00
 #define  RL5C4XX_HOLD_SHIFT		10
+#define  RL5C4XX_MISC_CONTROL           0x2F /* 8 bit */
+#define  RL5C4XX_ZV_ENABLE              0x08
 
 #ifdef __YENTA_H
 
@@ -125,10 +127,41 @@
 #define rl_mem(socket)		((socket)->private[3])
 #define rl_config(socket)	((socket)->private[4])
 
+static void ricoh_zoom_video(struct pcmcia_socket *sock, int onoff)
+{
+        u8 reg;
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+
+        reg = config_readb(socket, RL5C4XX_MISC_CONTROL);
+        if (onoff)
+                /* Zoom zoom, we will all go together, zoom zoom, zoom zoom */
+                reg |=  RL5C4XX_ZV_ENABLE;
+        else
+                reg &= ~RL5C4XX_ZV_ENABLE;
+	
+        config_writeb(socket, RL5C4XX_MISC_CONTROL, reg);
+}
+
+static void ricoh_set_zv(struct pcmcia_socket *sock)
+{
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+        if(socket->dev->vendor == PCI_VENDOR_ID_RICOH)
+        {
+                switch(socket->dev->device)
+                {
+                        /* There may be more .. */
+		case  PCI_DEVICE_ID_RICOH_RL5C478:
+			sock->zoom_video = ricoh_zoom_video;
+			break;  
+                }
+        }
+}
+
 static int ricoh_init(struct pcmcia_socket *sock)
 {
 	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
 	yenta_init(sock);
+	ricoh_set_zv(sock);
 
 	config_writew(socket, RL5C4XX_MISC, rl_misc(socket));
 	config_writew(socket, RL5C4XX_16BIT_CTL, rl_ctl(socket));
diff -Nru a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
--- a/drivers/pcmcia/ti113x.h	Sat Jul 19 12:54:24 2003
+++ b/drivers/pcmcia/ti113x.h	Sat Jul 19 12:54:24 2003
@@ -148,14 +148,96 @@
 	return 0;
 }
 
+/*
+ *	Zoom video control for TI122x/113x chips
+ */
+
+static void ti_zoom_video(struct pcmcia_socket *sock, int onoff)
+{
+	u8 reg;
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+
+	/* If we don't have a Zoom Video switch this is harmless,
+	   we just tristate the unused (ZV) lines */
+	reg = config_readb(socket, TI113X_CARD_CONTROL);
+	if (onoff)
+		/* Zoom zoom, we will all go together, zoom zoom, zoom zoom */
+		reg |= TI113X_CCR_ZVENABLE;
+	else
+		reg &= ~TI113X_CCR_ZVENABLE;
+	config_writeb(socket, TI113X_CARD_CONTROL, reg);
+}
+
+/*
+ *	The 145x series can also use this. They have an additional
+ *	ZV autodetect mode we don't use but don't actually need.
+ *	FIXME: manual says its in func0 and func1 but disagrees with
+ *	itself about this - do we need to force func0, if so we need
+ *	to know a lot more about socket pairings in pcmcia_socket than
+ *	we do now.. uggh.
+ */
+ 
+static void ti1250_zoom_video(struct pcmcia_socket *sock, int onoff)
+{	
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+	int shift = 0;
+	u8 reg;
+
+	ti_zoom_video(sock, onoff);
+
+	reg = config_readb(socket, 0x84);
+	reg |= (1<<7);	/* ZV bus enable */
+
+	if(PCI_FUNC(socket->dev->devfn)==1)
+		shift = 1;
+	
+	if(onoff)
+	{
+		reg &= ~(1<<6); 	/* Clear select bit */
+		reg |= shift<<6;	/* Favour our socket */
+		reg |= 1<<shift;	/* Socket zoom video on */
+	}
+	else
+	{
+		reg &= ~(1<<6); 	/* Clear select bit */
+		reg |= (1^shift)<<6;	/* Favour other socket */
+		reg &= ~(1<<shift);	/* Socket zoon video off */
+	}
+
+	config_writeb(socket, 0x84, reg);
+}
+
+static void ti_set_zv(struct pcmcia_socket *sock)
+{
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+	if(socket->dev->vendor == PCI_VENDOR_ID_TI)
+	{
+		switch(socket->dev->device)
+		{
+			/* There may be more .. */
+			case PCI_DEVICE_ID_TI_1220:
+			case PCI_DEVICE_ID_TI_1221:
+			case PCI_DEVICE_ID_TI_1225:
+				sock->zoom_video = ti_zoom_video;
+				break;	
+			case PCI_DEVICE_ID_TI_1250:
+			case PCI_DEVICE_ID_TI_1251A:
+			case PCI_DEVICE_ID_TI_1251B:
+			case PCI_DEVICE_ID_TI_1450:
+				sock->zoom_video = ti1250_zoom_video;
+		}
+	}
+}
 static int ti_init(struct pcmcia_socket *sock)
 {
 	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
 	yenta_init(sock);
+	ti_set_zv(sock);
 	ti_intctl(socket);
 	return 0;
 }
 
+
 /*
  * Generic TI init - TI has an extension for the
  * INTCTL register that sets the PCI CSC interrupt.
@@ -176,9 +258,6 @@
 	if (new != reg)
 		exca_writeb(socket, I365_INTCTL, new);
 
-#if 0
-	/* THIS CAUSES HANGS! Disabled for now, do not know why */
-
 	/*
 	 * If ISA interrupts don't work, then fall back to routing card
 	 * interrupts to the PCI interrupt of the socket.
@@ -190,7 +269,7 @@
 		u8 irqmux, devctl;
 
 		devctl = config_readb(socket, TI113X_DEVICE_CONTROL);
-		if (devctl & TI113X_DCR_IMODE_MASK != TI12XX_DCR_IMODE_ALL_SERIAL) {
+		if ((devctl & TI113X_DCR_IMODE_MASK) != TI12XX_DCR_IMODE_ALL_SERIAL) {
 			printk (KERN_INFO "ti113x: Routing card interrupts to PCI\n");
 
 			devctl &= ~TI113X_DCR_IMODE_MASK;
@@ -203,7 +282,6 @@
 			config_writeb(socket, TI113X_DEVICE_CONTROL, devctl);
 		}
 	}
-#endif
 
 	socket->socket.ops->init = ti_init;
 	return 0;
@@ -220,6 +298,7 @@
 {
 	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
 	yenta_init(sock);
+	ti_set_zv(sock);
 
 	config_writel(socket, TI113X_SYSTEM_CONTROL, ti_sysctl(socket));
 	config_writeb(socket, TI113X_CARD_CONTROL, ti_cardctl(socket));
@@ -248,6 +327,7 @@
 	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
 	yenta_init(sock);
 	ti113x_init(sock);
+	ti_set_zv(sock);
 	ti_irqmux(socket) = config_readl(socket, TI122X_IRQMUX);
 	ti_irqmux(socket) = (ti_irqmux(socket) & ~0x0f) | 0x02; /* route INTA */
 	if (!(ti_sysctl(socket) & TI122X_SCR_INTRTIE))
diff -Nru a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
--- a/drivers/pcmcia/yenta_socket.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/pcmcia/yenta_socket.c	Sat Jul 19 12:54:25 2003
@@ -297,6 +297,8 @@
 		}
 		exca_writeb(socket, I365_CSCINT, reg);
 		exca_readb(socket, I365_CSC);
+		if(sock->zoom_video)
+			sock->zoom_video(sock, state->flags & SS_ZVCARD);
 	}
 	config_writew(socket, CB_BRIDGE_CONTROL, bridge);
 	/* Socket event mask: get card insert/remove events.. */
diff -Nru a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
--- a/drivers/pnp/isapnp/core.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/pnp/isapnp/core.c	Sat Jul 19 12:54:25 2003
@@ -255,14 +255,22 @@
 static int isapnp_next_rdp(void)
 {
 	int rdp = isapnp_rdp;
+	static int old_rdp = 0;
+	
+	if(old_rdp)
+	{
+		release_region(old_rdp, 1);
+		old_rdp = 0;
+	}
 	while (rdp <= 0x3ff) {
 		/*
 		 *	We cannot use NE2000 probe spaces for ISAPnP or we
 		 *	will lock up machines.
 		 */
-		if ((rdp < 0x280 || rdp >  0x380) && !check_region(rdp, 1))
+		if ((rdp < 0x280 || rdp >  0x380) && request_region(rdp, 1, "ISAPnP"))
 		{
 			isapnp_rdp = rdp;
+			old_rdp = rdp;
 			return 0;
 		}
 		rdp += RDP_STEP;
diff -Nru a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
--- a/drivers/s390/block/dasd.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/s390/block/dasd.c	Sat Jul 19 12:54:25 2003
@@ -16,7 +16,6 @@
 #include <linux/interrupt.h>
 #include <linux/ctype.h>
 #include <linux/major.h>
-#include <linux/blk.h>
 #include <linux/slab.h>
 #include <linux/buffer_head.h>
 
diff -Nru a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
--- a/drivers/s390/block/dasd_genhd.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/s390/block/dasd_genhd.c	Sat Jul 19 12:54:26 2003
@@ -9,7 +9,7 @@
  *
  * Dealing with devices registered to multiple major numbers.
  *
- * $Revision: 1.29 $
+ * $Revision: 1.31 $
  */
 
 #include <linux/config.h>
@@ -17,7 +17,6 @@
 #include <linux/interrupt.h>
 #include <linux/fs.h>
 #include <linux/blkpg.h>
-#include <linux/blk.h>
 
 #include <asm/uaccess.h>
 
@@ -200,7 +199,6 @@
 dasd_destroy_partitions(struct dasd_device * device)
 {
 	del_gendisk(device->gdp);
-	put_disk(device->gdp);
 }
 
 int
diff -Nru a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
--- a/drivers/s390/block/dasd_ioctl.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/s390/block/dasd_ioctl.c	Sat Jul 19 12:54:25 2003
@@ -14,7 +14,6 @@
 #include <linux/major.h>
 #include <linux/fs.h>
 #include <linux/blkpg.h>
-#include <linux/blk.h>
 
 #include <asm/ccwdev.h>
 #include <asm/uaccess.h>
diff -Nru a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
--- a/drivers/s390/block/xpram.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/s390/block/xpram.c	Sat Jul 19 12:54:26 2003
@@ -31,7 +31,6 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
 #include <linux/blkpg.h>
 #include <linux/hdreg.h>  /* HDIO_GETGEO */
 #include <linux/sysdev.h>
diff -Nru a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
--- a/drivers/s390/char/tape_block.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/s390/char/tape_block.c	Sat Jul 19 12:54:26 2003
@@ -13,7 +13,6 @@
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/blkdev.h>
-#include <linux/blk.h>
 #include <linux/interrupt.h>
 #include <linux/buffer_head.h>
 
diff -Nru a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
--- a/drivers/s390/cio/chsc.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/s390/cio/chsc.c	Sat Jul 19 12:54:25 2003
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/chsc.c
  *   S/390 common I/O routines -- channel subsystem call
- *   $Revision: 1.73 $
+ *   $Revision: 1.74 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -206,6 +206,7 @@
 	if (!page)
 		return -ENOMEM;
 
+	err = 0;
 	for (irq = 0; irq <= highest_subchannel; irq++) {
 		/*
 		 * retrieve information for each sch
@@ -222,13 +223,14 @@
 				       "not work\n", err);
 				cio_chsc_err_msg = 1;
 			}
-			return err;
+			goto out;
 		}
 		clear_page(page);
 	}
 	cio_chsc_desc_avail = 1;
+out:
 	free_page((unsigned long)page);
-	return 0;
+	return err;
 }
 
 __initcall(chsc_get_sch_descriptions);
@@ -428,7 +430,7 @@
 			ret = css_probe_device(irq);
 			if (ret == -ENXIO)
 				/* We're through */
-				return;
+				break;
 			continue;
 		}
 	
diff -Nru a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
--- a/drivers/s390/cio/cio.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/s390/cio/cio.c	Sat Jul 19 12:54:30 2003
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/cio.c
  *   S/390 common I/O routines -- low level i/o calls
- *   $Revision: 1.98 $
+ *   $Revision: 1.100 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -16,10 +16,12 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/device.h>
+#include <linux/kernel_stat.h>
 
 #include <asm/hardirq.h>
 #include <asm/cio.h>
 #include <asm/delay.h>
+#include <asm/irq.h>
 
 #include "airq.h"
 #include "cio.h"
@@ -442,6 +444,11 @@
 			if (sch->schib.pmcw.ena)
 				break;
 		}
+		if (ret == -EBUSY) {
+			struct irb irb;
+			if (tsch(sch->irq, &irb) != 0)
+				break;
+		}
 	}
 	sprintf (dbf_txt, "ret:%d", ret);
 	CIO_TRACE_EVENT (2, dbf_txt);
@@ -608,6 +615,7 @@
 	tpi_info = (struct tpi_info *) __LC_SUBCHANNEL_ID;
 	irb = (struct irb *) __LC_IRB;
 	do {
+		kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++;
 		/*
 		 * Non I/O-subchannel thin interrupts are processed differently
 		 */
diff -Nru a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
--- a/drivers/s390/cio/device.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/s390/cio/device.c	Sat Jul 19 12:54:26 2003
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/device.c
  *  bus driver for ccw devices
- *   $Revision: 1.58 $
+ *   $Revision: 1.60 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
@@ -434,6 +434,13 @@
 	return ret;
 }
 
+void
+ccw_device_unregister(void *data)
+{
+	device_unregister((struct device *)data);
+}
+	
+
 static void
 ccw_device_release(struct device *dev)
 {
@@ -513,17 +520,11 @@
 		wake_up(&ccw_device_init_wq);
 }
 
-static void
+static int
 io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
 {
 	int rc;
 
-	if (!get_device(&sch->dev)) {
-		if (cdev->dev.release)
-			cdev->dev.release(&cdev->dev);
-		return;
-	}
-
 	sch->dev.driver_data = cdev;
 	sch->driver = &io_subchannel_driver;
 	cdev->ccwlock = &sch->lock;
@@ -540,9 +541,6 @@
 	snprintf (cdev->dev.bus_id, DEVICE_ID_SIZE, "0:%04x",
 		  sch->schib.pmcw.dev);
 
-	/* Do first half of device_register. */
-	device_initialize(&cdev->dev);
-
 	/* Increase counter of devices currently in recognition. */
 	atomic_inc(&ccw_device_init_count);
 
@@ -551,13 +549,10 @@
 	rc = ccw_device_recognition(cdev);
 	spin_unlock_irq(cdev->ccwlock);
 	if (rc) {
-		sch->dev.driver_data = 0;
-		put_device(&sch->dev);
-		if (cdev->dev.release)
-			cdev->dev.release(&cdev->dev);
 		if (atomic_dec_and_test(&ccw_device_init_count))
 			wake_up(&ccw_device_init_wq);
 	}
+	return rc;
 }
 
 static int
@@ -565,6 +560,7 @@
 {
 	struct subchannel *sch;
 	struct ccw_device *cdev;
+	int rc;
 
 	sch = to_subchannel(pdev);
 	if (sch->dev.driver_data) {
@@ -573,8 +569,20 @@
 		 * Register it and exit. This happens for all early
 		 * device, e.g. the console.
 		 */
-		ccw_device_register(sch->dev.driver_data);
+		cdev = sch->dev.driver_data;
+		device_initialize(&cdev->dev);
+		ccw_device_register(cdev);
 		subchannel_add_files(&sch->dev);
+		/*
+		 * Check if the device is already online. If it is
+		 * the reference count needs to be corrected
+		 * (see ccw_device_online and css_init_done for the
+		 * ugly details).
+		 */
+		if (cdev->private->state != DEV_STATE_NOT_OPER &&
+		    cdev->private->state != DEV_STATE_OFFLINE &&
+		    cdev->private->state != DEV_STATE_BOXED)
+			get_device(&cdev->dev);
 		return 0;
 	}
 	cdev  = kmalloc (sizeof(*cdev), GFP_KERNEL);
@@ -592,7 +600,23 @@
 		.parent = pdev,
 		.release = ccw_device_release,
 	};
-	io_subchannel_recog(cdev, to_subchannel(pdev));
+	/* Do first half of device_register. */
+	device_initialize(&cdev->dev);
+
+	if (!get_device(&sch->dev)) {
+		if (cdev->dev.release)
+			cdev->dev.release(&cdev->dev);
+		return 0;
+	}
+
+	rc = io_subchannel_recog(cdev, to_subchannel(pdev));
+	if (rc) {
+		sch->dev.driver_data = 0;
+		put_device(&sch->dev);
+		if (cdev->dev.release)
+			cdev->dev.release(&cdev->dev);
+	}
+
 	return 0;
 }
 
@@ -604,6 +628,8 @@
 static int
 ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch)
 {
+	int rc;
+
 	/* Initialize the ccw_device structure. */
 	cdev->dev = (struct device) {
 		.parent = &sch->dev,
@@ -613,7 +639,11 @@
 		.parent = &css_bus_device,
 		.bus	= &css_bus_type,
 	};
-	io_subchannel_recog(cdev, sch);
+
+	rc = io_subchannel_recog(cdev, sch);
+	if (rc)
+		return rc;
+
 	/* Now wait for the async. recognition to come to an end. */
 	while (!dev_fsm_final_state(cdev))
 		wait_cons_dev();
diff -Nru a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
--- a/drivers/s390/cio/device.h	Sat Jul 19 12:54:27 2003
+++ b/drivers/s390/cio/device.h	Sat Jul 19 12:54:27 2003
@@ -65,6 +65,8 @@
 
 void io_subchannel_recog_done(struct ccw_device *cdev);
 
+void ccw_device_unregister(void *);
+
 int ccw_device_recognition(struct ccw_device *);
 int ccw_device_online(struct ccw_device *);
 int ccw_device_offline(struct ccw_device *);
diff -Nru a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
--- a/drivers/s390/cio/device_fsm.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/s390/cio/device_fsm.c	Sat Jul 19 12:54:25 2003
@@ -188,7 +188,7 @@
 
 	wake_up(&cdev->private->wait_q);
 
-	if (state != DEV_STATE_ONLINE)
+	if (css_init_done && state != DEV_STATE_ONLINE)
 		put_device (&cdev->dev);
 }
 
@@ -293,7 +293,7 @@
 	if (cdev->private->state != DEV_STATE_OFFLINE)
 		return -EINVAL;
 	sch = to_subchannel(cdev->dev.parent);
-	if (!get_device(&cdev->dev))
+	if (css_init_done && !get_device(&cdev->dev))
 		return -ENODEV;
 	if (cio_enable_subchannel(sch, sch->schib.pmcw.isc) != 0) {
 		/* Couldn't enable the subchannel for i/o. Sick device. */
@@ -384,7 +384,9 @@
 ccw_device_offline_notoper(struct ccw_device *cdev, enum dev_event dev_event)
 {
 	cdev->private->state = DEV_STATE_NOT_OPER;
-	device_unregister(&cdev->dev);
+	INIT_WORK(&cdev->private->kick_work,
+		  ccw_device_unregister, (void *) &cdev->dev);
+	queue_work(ccw_device_work, &cdev->private->kick_work);
 	wake_up(&cdev->private->wait_q);
 }
 
@@ -403,8 +405,10 @@
 		// FIXME: not-oper indication to device driver ?
 		ccw_device_call_handler(cdev);
 	}
+	INIT_WORK(&cdev->private->kick_work,
+		  ccw_device_unregister, (void *) &cdev->dev);
+	queue_work(ccw_device_work, &cdev->private->kick_work);
 	wake_up(&cdev->private->wait_q);
-	device_unregister(&cdev->dev);
 }
 
 /*
diff -Nru a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
--- a/drivers/s390/cio/qdio.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/s390/cio/qdio.c	Sat Jul 19 12:54:25 2003
@@ -55,7 +55,7 @@
 #include "ioasm.h"
 #include "chsc.h"
 
-#define VERSION_QDIO_C "$Revision: 1.51 $"
+#define VERSION_QDIO_C "$Revision: 1.55 $"
 
 /****************** MODULE PARAMETER VARIABLES ********************/
 MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
@@ -1643,6 +1643,7 @@
 	default:
 		BUG();
 	}
+	ccw_device_set_timeout(cdev, 0);
 	wake_up(&cdev->private->wait_q);
 
 }
@@ -1891,26 +1892,25 @@
 		result=-EIO;
 		goto exit;
 	}
-	/* 4: request block
-	 * 2: general char
-	 * 512: chsc char */
-	if ((scsc_area->general_char[1] & 0x00800000) != 0x00800000) {
+	/* Check for bit 41. */
+	if ((scsc_area->general_char[1] & 0x00400000) != 0x00400000) {
 		QDIO_PRINT_WARN("Adapter interruption facility not " \
 				"installed.\n");
 		result=-ENOENT;
 		goto exit;
 	}
-	if ((scsc_area->chsc_char[2] & 0x00180000) != 0x00180000) {
+	/* Check for bits 107 and 108. */
+	if ((scsc_area->chsc_char[3] & 0x00180000) != 0x00180000) {
 		QDIO_PRINT_WARN("Set Chan Subsys. Char. & Fast-CHSCs " \
 				"not available.\n");
 		result=-ENOENT;
 		goto exit;
 	}
 
-	/* Check for hydra thin interrupts. */
+	/* Check for hydra thin interrupts (bit 67). */
 	hydra_thinints = ((scsc_area->general_char[2] & 0x10000000)
 		== 0x10000000);
-	sprintf(dbf_text,"hydra_ti%1x", hydra_thinints);
+	sprintf(dbf_text,"hydrati%1x", hydra_thinints);
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
 exit:
 	free_page ((unsigned long) scsc_area);
@@ -2413,8 +2413,10 @@
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
 	QDIO_DBF_TEXT0(0,trace,dbf_text);
 
-	if (qdio_establish_irq_check_for_errors(cdev, cstat, dstat))
+	if (qdio_establish_irq_check_for_errors(cdev, cstat, dstat)) {
+		ccw_device_set_timeout(cdev, 0);
 		return;
+	}
 
 	irq_ptr = cdev->private->qdio_data;
 
@@ -2439,7 +2441,7 @@
 	qdio_initialize_set_siga_flags_output(irq_ptr);
 
 	qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ESTABLISHED);
-
+	ccw_device_set_timeout(cdev, 0);
 }
 
 int
@@ -2698,6 +2700,8 @@
                            "returned %i, next try returned %i\n",
                            irq_ptr->irq,result,result2);
 		result=result2;
+		if (result)
+			ccw_device_set_timeout(cdev, 0);
 	}
 
 	spin_unlock_irqrestore(get_ccwdev_lock(cdev),saveflags);
@@ -3000,7 +3004,6 @@
 			int buffer_length, int *eof, void *data)
 {
         int c=0;
-	int irq;
 
         /* we are always called with buffer_length=4k, so we all
            deliver on the first read */
@@ -3020,7 +3023,7 @@
 		 perf_stats.siga_ins);
 	_OUTP_IT("Number of SIGA out's issued                     : %u\n",
 		 perf_stats.siga_outs);
-	_OUTP_IT("Number of PCIs caught                          : %u\n",
+	_OUTP_IT("Number of PCIs caught                           : %u\n",
 		 perf_stats.pcis);
 	_OUTP_IT("Number of adapter interrupts caught             : %u\n",
 		 perf_stats.thinints);
@@ -3037,27 +3040,6 @@
 		 perf_stats.outbound_cnt);
 	_OUTP_IT("\n");
 
-	/* 
-	 * FIXME: Rather use driver_for_each_dev, if we had it. 
-	 * I know this loop destroys our layering, but at least gets the 
-	 * performance stats out...
-	 */
-	for (irq=0;irq <= highest_subchannel; irq++) {
-		struct qdio_irq *irq_ptr;
-		struct ccw_device *cdev;
-
-		if (!ioinfo[irq])
-			continue;
-		cdev = ioinfo[irq]->dev.driver_data;
-		if (!cdev)
-			continue;
-		irq_ptr = cdev->private->qdio_data;
-		if (!irq_ptr)
-			continue;
-		_OUTP_IT("Polling time on irq %4x                        " \
-			 ": %u\n",
-			 irq_ptr->irq,irq_ptr->input_qs[0]->timing.threshold);
-	}
         return c;
 }
 
diff -Nru a/drivers/s390/net/qeth.c b/drivers/s390/net/qeth.c
--- a/drivers/s390/net/qeth.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/s390/net/qeth.c	Sat Jul 19 12:54:30 2003
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth.c ($Revision: 1.118 $)
+ * linux/drivers/s390/net/qeth.c ($Revision: 1.126 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  *
@@ -165,7 +165,7 @@
 		 "reserved for low memory situations");
 
 /****************** MODULE STUFF **********************************/
-#define VERSION_QETH_C "$Revision: 1.118 $"
+#define VERSION_QETH_C "$Revision: 1.126 $"
 static const char *version = "qeth S/390 OSA-Express driver ("
     VERSION_QETH_C "/" VERSION_QETH_H "/" VERSION_QETH_MPC_H
     QETH_VERSION_IPV6 QETH_VERSION_VLAN ")";
@@ -1156,7 +1156,7 @@
 	return skb;
 }
 
-static struct sk_buff *
+static inline struct sk_buff *
 qeth_get_next_skb(struct qeth_card *card,
 		  int *element_ptr, int *pos_in_el_ptr,
 		  void **hdr_ptr, struct qdio_buffer *buffer)
@@ -1464,8 +1464,21 @@
 	skb->ip_summed = card->options.checksum_type;
 	if (card->options.checksum_type == HW_CHECKSUMMING) {
 		/* do we have a checksummed packet? */
-		if (*(__u8 *) (hdr_ptr + 11) & QETH_EXT_HEADER_CSUM_TRANSP_REQ) {
-			/* skb->ip_summed is set already */
+
+		/* 
+		 * we only check for TCP/UDP checksums when the pseudo
+		 * header was also checked successfully -- for the
+		 * rest of the packets, it's not clear, whether the
+		 * upper layer csum is alright. And they shouldn't
+		 * occur too often anyway in real life 
+		 */
+
+		if ((*(__u8*)(hdr_ptr+11) & (QETH_EXT_HEADER_CSUM_HDR_REQ |
+					     QETH_EXT_HEADER_CSUM_TRANSP_REQ)) ==
+		    (QETH_EXT_HEADER_CSUM_HDR_REQ |
+		     QETH_EXT_HEADER_CSUM_TRANSP_REQ)) {
+#if 0
+			/* csum does not need to be set inbound anyway */
 			
 			/* 
 			 * vlan is not an issue here, it's still in
@@ -1485,11 +1498,15 @@
 					(&skb->data[ip_len +
 						    QETH_TCP_CSUM_OFFSET]);
 			}
+#endif /* 0 */
+			skb->ip_summed=CHECKSUM_UNNECESSARY;
 		} else {
 			/* make the stack check it */
 			skb->ip_summed = SW_CHECKSUMMING;
 		}
-	}
+	} else
+		skb->ip_summed=card->options.checksum_type;
+
 	__qeth_rebuild_skb_vlan(card, skb, hdr_ptr);
 }
 
@@ -1596,7 +1613,7 @@
 #endif
 }
 
-static __u8
+static inline __u8
 __qeth_get_flags_v4(int multicast)
 {
 	if (multicast == RTN_MULTICAST)
@@ -1606,7 +1623,7 @@
 	return QETH_CAST_UNICAST;
 }
 
-static __u8
+static inline __u8
 __qeth_get_flags_v6(int multicast)
 {
 	if (multicast == RTN_MULTICAST)
@@ -1625,7 +1642,7 @@
 		QETH_HEADER_IPV6;
 }
 
-static void
+static inline void
 qeth_fill_header(struct qeth_hdr *hdr, struct sk_buff *skb,
 		 int version, int multicast)
 {
@@ -1681,7 +1698,7 @@
 		      __max(QETH_DBF_DATA_LEN, QETH_DBF_DATA_LEN));
 }
 
-static int inline
+static inline int
 qeth_fill_buffer(struct qdio_buffer *buffer, char *dataptr,
 		 int length, int element)
 {
@@ -1735,7 +1752,7 @@
 	return element;
 }
 
-static void
+static inline void
 qeth_flush_packed_packets(struct qeth_card *card, int queue, int under_int)
 {
 	struct qdio_buffer *buffer;
@@ -1900,7 +1917,7 @@
 	return ERROR_LINK_FAILURE;	/* should never happen */
 }
 
-static void
+static inline void
 qeth_free_buffer(struct qeth_card *card, int queue, int bufno,
 		 int qdio_error, int siga_error)
 {
@@ -2013,7 +2030,7 @@
 	card->send_retries[queue][bufno] = 0;
 }
 
-static void
+static inline void
 qeth_free_all_skbs(struct qeth_card *card)
 {
 	int q, b;
@@ -2049,7 +2066,7 @@
 }
 
 #ifdef QETH_VLAN
-void
+static inline void
 qeth_insert_ipv6_vlan_tag(struct sk_buff *__skb)
 {
 
@@ -2088,7 +2105,7 @@
 #endif
 }
 
-static void
+static inline void
 qeth_send_packet_fast(struct qeth_card *card, struct sk_buff *skb,
 		      struct net_device *dev,
 		      int queue, int version, int multicast)
@@ -2183,7 +2200,7 @@
 
 /* no checks, if all elements are used, as then we would not be here (at most
    127 buffers are enqueued) */
-static void
+static inline void
 qeth_send_packet_packed(struct qeth_card *card, struct sk_buff *skb,
 			struct net_device *dev,
 			int queue, int version, int multicast)
@@ -2391,7 +2408,7 @@
 	}
 }
 
-static int
+static inline int
 qeth_do_send_packet(struct qeth_card *card, struct sk_buff *skb,
 		    struct net_device *dev)
 {
@@ -2829,23 +2846,27 @@
 
 	if (!buffer) {
 		if (atomic_read(&card->escape_softsetup))
-			result = 0;
+			return 0;
 		else
-			result = -1;
-	} else {
-		reply = (struct ipa_cmd *) PDU_ENCAPSULATION(buffer);
-		if ((update_cmd) && (reply))
-			memcpy(cmd, reply, sizeof (struct ipa_cmd));
-		result = reply->return_code;
-
-		/* some special sausages: */
-		if ((ipa_cmd == IPA_CMD_SETASSPARMS) && (result == 0)) {
-			result = reply->data.setassparms.return_code;
-		}
-		if ((ipa_cmd == IPA_CMD_SETADAPTERPARMS) && (result == 0)) {
-			result = reply->data.setadapterparms.return_code;
-		}
+			return -1;
+	}
+	reply = (struct ipa_cmd *) PDU_ENCAPSULATION(buffer);
+	if ((update_cmd) && (reply))
+		memcpy(cmd, reply, sizeof (struct ipa_cmd));
+	result = reply->return_code;
+
+	/* some special sausages: */
+	if ((ipa_cmd == IPA_CMD_SETASSPARMS) && (result == 0)) {
+		result = reply->data.setassparms.return_code;
+		if ((reply->data.setassparms.assist_no==IPA_INBOUND_CHECKSUM) &&
+		    (reply->data.setassparms.command_code == IPA_CMD_ASS_START))
+			card->csum_enable_mask =
+				reply->data.setassparms.data.flags_32bit;
+	}
+	if ((ipa_cmd == IPA_CMD_SETADAPTERPARMS) && (result == 0)) {
+		result = reply->data.setadapterparms.return_code;
 	}
+
 	return result;
 }
 
@@ -5599,7 +5620,7 @@
 			}
 			result=qeth_send_setassparms_simple_with_data
 				(card,IPA_INBOUND_CHECKSUM,
-				 IPA_CMD_ASS_ENABLE, IPA_CHECKSUM_ENABLE_MASK);
+				 IPA_CMD_ASS_ENABLE, card->csum_enable_mask);
 			if (result) {
 				PRINT_WARN("Could not enable inbound " \
 					   "checksumming on %s: 0x%x, " \
@@ -6881,6 +6902,14 @@
 	return level;		/* hmmm... don't know what to do with that level. */
 }
 
+/* returns last four digits of bus_id */
+static inline __u16
+__raw_devno_from_bus_id(char *id)
+{
+	id += (strlen(id) - 4); 
+	return (__u16) simple_strtoul(id, &id, 16);
+}
+
 static int
 qeth_idx_activate_read(struct qeth_card *card)
 {
@@ -6905,7 +6934,7 @@
 	memcpy(QETH_IDX_ACT_FUNC_LEVEL(card->dma_stuff->sendbuf),
 	       &card->func_level, 2);
 
-	temp = _ccw_device_get_device_number(card->ddev);
+	temp = __raw_devno_from_bus_id(card->ddev->dev.bus_id);
 	memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(card->dma_stuff->sendbuf), &temp, 2);
 	temp = (card->cula << 8) + card->unit_addr2;
 	memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(card->dma_stuff->sendbuf),
@@ -7501,10 +7530,8 @@
 	for (; tmp && (!result); tmp = tmp->next) {
 		if (atomic_read(&tmp->shutdown_phase))
 			continue;
-		if (dev == tmp->dev) {
-			result = QETH_VERIFY_IS_REAL_DEV;
-		}
-		result = __qeth_verify_dev_vlan(dev, tmp);
+		result = (dev == tmp->dev)?
+			QETH_VERIFY_IS_REAL_DEV:__qeth_verify_dev_vlan(dev, tmp);
 	}
 	read_unlock(&list_lock);
 	return result;
@@ -8547,6 +8574,8 @@
 	card->ip_mc_new_state.ipm6_ifa = NULL;
 #endif /* QETH_IPV6 */
 
+	card->csum_enable_mask = IPA_CHECKSUM_DEFAULT_ENABLE_MASK;
+
 	/* setup net_device stuff */
 	card->dev->priv = card;
 
@@ -9087,21 +9116,19 @@
 		/* FIXME: this is really a mess... */
 
 #ifdef QETH_IPV6
-		if (atomic_read(&card->rt4fld) && atomic_read(&card->rt6fld))
-			strcpy(router_str, "no");
-		else if (atomic_read(&card->rt4fld)
-			 || atomic_read(&card->rt6fld))
-			strcpy(router_str, "mix");
+		if (atomic_read(&card->rt4fld) || atomic_read(&card->rt6fld))
+			strcpy(router_str, "FLD");
 #else/* QETH_IPV6 */
 		if (atomic_read(&card->rt4fld))
-			strcpy(router_str, "no");
+			strcpy(router_str, "FLD");
 #endif /* QETH_IPV6 */
 		else if (((card->options.routing_type4 & ROUTER_MASK) ==
 			  PRIMARY_ROUTER)
 #ifdef QETH_IPV6
 			 &&
-			 ((card->options.routing_type6 & ROUTER_MASK) ==
-			  PRIMARY_ROUTER)
+			 (((card->options.routing_type6 & ROUTER_MASK) ==
+			  PRIMARY_ROUTER) ||
+			  (!qeth_is_supported(IPA_IPv6)))
 #endif /* QETH_IPV6 */
 		    ) {
 			strcpy(router_str, "pri");
@@ -9110,8 +9137,9 @@
 			 SECONDARY_ROUTER)
 #ifdef QETH_IPV6
 			&&
-			((card->options.routing_type6 & ROUTER_MASK) ==
-			 SECONDARY_ROUTER)
+			(((card->options.routing_type6 & ROUTER_MASK) ==
+			 SECONDARY_ROUTER) ||
+			 (!qeth_is_supported(IPA_IPv6)))
 #endif /* QETH_IPV6 */
 		    ) {
 			strcpy(router_str, "sec");
@@ -9120,8 +9148,9 @@
 			 MULTICAST_ROUTER)
 #ifdef QETH_IPV6
 			&&
-			((card->options.routing_type6 & ROUTER_MASK) ==
-			 MULTICAST_ROUTER)
+			(((card->options.routing_type6 & ROUTER_MASK) ==
+			 MULTICAST_ROUTER) ||
+			 (!qeth_is_supported(IPA_IPv6)))
 #endif /* QETH_IPV6 */
 		    ) {
 			strcpy(router_str, "mc");
@@ -9130,8 +9159,9 @@
 			 PRIMARY_CONNECTOR)
 #ifdef QETH_IPV6
 			&&
-			((card->options.routing_type6 & ROUTER_MASK) ==
-			 PRIMARY_CONNECTOR)
+			(((card->options.routing_type6 & ROUTER_MASK) ==
+			 PRIMARY_CONNECTOR) ||
+			 (!qeth_is_supported(IPA_IPv6)))
 #endif /* QETH_IPV6 */
 		    ) {
 			strcpy(router_str, "p.c");
@@ -9140,8 +9170,9 @@
 			 SECONDARY_CONNECTOR)
 #ifdef QETH_IPV6
 			&&
-			((card->options.routing_type6 & ROUTER_MASK) ==
-			 SECONDARY_CONNECTOR)
+			(((card->options.routing_type6 & ROUTER_MASK) ==
+			 SECONDARY_CONNECTOR) ||
+			 (!qeth_is_supported(IPA_IPv6)))
 #endif /* QETH_IPV6 */
 		    ) {
 			strcpy(router_str, "s.c");
@@ -9150,8 +9181,9 @@
 			 NO_ROUTER)
 #ifdef QETH_IPV6
 			&&
-			((card->options.routing_type6 & ROUTER_MASK) ==
-			 NO_ROUTER)
+			(((card->options.routing_type6 & ROUTER_MASK) ==
+			 NO_ROUTER) ||
+			 (!qeth_is_supported(IPA_IPv6)))
 #endif /* QETH_IPV6 */
 		    ) {
 			strcpy(router_str, "no");
@@ -10115,7 +10147,7 @@
 		return -EINVAL;
 
 	if (atomic_read(&card->rt4fld))
-		return sprintf(buf, "%s\n", "no");
+		return sprintf(buf, "%s\n", "FLD");
 
 	switch (card->options.routing_type4 & ROUTER_MASK) {
 	case PRIMARY_ROUTER:
@@ -10202,7 +10234,10 @@
 		return -EINVAL;
 
 	if (atomic_read(&card->rt6fld))
-		return sprintf(buf, "%s\n", "no");
+		return sprintf(buf, "%s\n", "FLD");
+
+	if (!qeth_is_supported(IPA_IPv6))
+		return sprintf(buf, "%s\n", "n/a");
 
 	switch (card->options.routing_type6 & ROUTER_MASK) {
 	case PRIMARY_ROUTER:
@@ -11060,6 +11095,10 @@
 	qeth_remove_card_from_list(card);
 
 	QETH_DBF_TEXT4(0, trace, "freecard");
+
+	memset(card->dev, 0, sizeof (struct net_device));
+	card->dev->priv = card;
+	strncpy(card->dev->name, card->dev_name, IFNAMSIZ);
 
 	ccw_device_set_offline(card->ddev);
 	ccw_device_set_offline(card->wdev);
diff -Nru a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
--- a/drivers/s390/net/qeth.h	Sat Jul 19 12:54:21 2003
+++ b/drivers/s390/net/qeth.h	Sat Jul 19 12:54:21 2003
@@ -14,7 +14,7 @@
 
 #define QETH_NAME " qeth"
 
-#define VERSION_QETH_H "$Revision: 1.47 $"
+#define VERSION_QETH_H "$Revision: 1.49 $"
 
 /******************** CONFIG STUFF ***********************/
 //#define QETH_DBF_LIKE_HELL
@@ -938,6 +938,8 @@
 	__u32 ipa6_enabled;
 	__u32 adp_supported;
 
+	__u32 csum_enable_mask;
+
 	atomic_t startlan_attempts;
 	atomic_t enable_routing_attempts4;
 	atomic_t rt4fld;
@@ -1021,7 +1023,7 @@
 		case QETH_MPC_LINK_TYPE_LANE_TR:
 			/* fallthrough */
 		case QETH_MPC_LINK_TYPE_HSTR:
-			return ARPHRD_IEEE802;
+			return ARPHRD_IEEE802_TR;
 		default:
 			return ARPHRD_ETHER;
 		}
diff -Nru a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h
--- a/drivers/s390/net/qeth_mpc.h	Sat Jul 19 12:54:25 2003
+++ b/drivers/s390/net/qeth_mpc.h	Sat Jul 19 12:54:25 2003
@@ -10,7 +10,7 @@
 #ifndef __QETH_MPC_H__
 #define __QETH_MPC_H__
 
-#define VERSION_QETH_MPC_H "$Revision: 1.15 $"
+#define VERSION_QETH_MPC_H "$Revision: 1.16 $"
 
 #define QETH_IPA_TIMEOUT (card->ipa_timeout)
 #define QETH_MPC_TIMEOUT 2000
@@ -188,7 +188,7 @@
 #define IPA_CMD_ASS_ARP_QUERY_INFO 0x0104
 #define IPA_CMD_ASS_ARP_QUERY_STATS 0x0204
 
-#define IPA_CHECKSUM_ENABLE_MASK 0x001a
+#define IPA_CHECKSUM_DEFAULT_ENABLE_MASK 0x001a
 
 #define IPA_CMD_ASS_FILTER_SET_TYPES 0x0003
 
diff -Nru a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
--- a/drivers/sbus/char/envctrl.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/sbus/char/envctrl.c	Sat Jul 19 12:54:23 2003
@@ -14,6 +14,9 @@
  *
  * EB - Added support for CP1500 Global Address and PS/Voltage monitoring.
  * 		Eric Brower <ebrower@usa.net>
+ *
+ * DB - Audit every copy_to_user in envctrl_read.
+ *              Daniele Bellucci <bellucda@tiscali.it>
  */
 
 #include <linux/config.h>
@@ -571,7 +574,8 @@
 
 		data[0] = (unsigned char)(warning_temperature);
 		ret = 1;
-		copy_to_user((unsigned char *)buf, data, ret);
+		if (copy_to_user((unsigned char *)buf, data, ret))
+			ret = -EFAULT;
 		break;
 
 	case ENVCTRL_RD_SHUTDOWN_TEMPERATURE:
@@ -580,14 +584,16 @@
 
 		data[0] = (unsigned char)(shutdown_temperature);
 		ret = 1;
-		copy_to_user((unsigned char *)buf, data, ret);
+		if (copy_to_user((unsigned char *)buf, data, ret))
+			ret = -EFAULT;
 		break;
 
 	case ENVCTRL_RD_MTHRBD_TEMPERATURE:
 		if (!(pchild = envctrl_get_i2c_child(ENVCTRL_MTHRBDTEMP_MON)))
 			return 0;
 		ret = envctrl_read_noncpu_info(pchild, ENVCTRL_MTHRBDTEMP_MON, data);
-		copy_to_user((unsigned char *)buf, data, ret);
+		if (copy_to_user((unsigned char *)buf, data, ret))
+			ret = -EFAULT;
 		break;
 
 	case ENVCTRL_RD_CPU_TEMPERATURE:
@@ -596,7 +602,8 @@
 		ret = envctrl_read_cpu_info(read_cpu, pchild, ENVCTRL_CPUTEMP_MON, data);
 
 		/* Reset cpu to the default cpu0. */
-		copy_to_user((unsigned char *)buf, data, ret);
+		if (copy_to_user((unsigned char *)buf, data, ret))
+			ret = -EFAULT;
 		break;
 
 	case ENVCTRL_RD_CPU_VOLTAGE:
@@ -605,21 +612,24 @@
 		ret = envctrl_read_cpu_info(read_cpu, pchild, ENVCTRL_CPUVOLTAGE_MON, data);
 
 		/* Reset cpu to the default cpu0. */
-		copy_to_user((unsigned char *)buf, data, ret);
+		if (copy_to_user((unsigned char *)buf, data, ret))
+			ret = -EFAULT;
 		break;
 
 	case ENVCTRL_RD_SCSI_TEMPERATURE:
 		if (!(pchild = envctrl_get_i2c_child(ENVCTRL_SCSITEMP_MON)))
 			return 0;
 		ret = envctrl_read_noncpu_info(pchild, ENVCTRL_SCSITEMP_MON, data);
-		copy_to_user((unsigned char *)buf, data, ret);
+		if (copy_to_user((unsigned char *)buf, data, ret))
+			ret = -EFAULT;
 		break;
 
 	case ENVCTRL_RD_ETHERNET_TEMPERATURE:
 		if (!(pchild = envctrl_get_i2c_child(ENVCTRL_ETHERTEMP_MON)))
 			return 0;
 		ret = envctrl_read_noncpu_info(pchild, ENVCTRL_ETHERTEMP_MON, data);
-		copy_to_user((unsigned char *)buf, data, ret);
+		if (copy_to_user((unsigned char *)buf, data, ret))
+			ret = -EFAULT;
 		break;
 
 	case ENVCTRL_RD_FAN_STATUS:
@@ -627,7 +637,8 @@
 			return 0;
 		data[0] = envctrl_i2c_read_8574(pchild->addr);
 		ret = envctrl_i2c_fan_status(pchild,data[0], data);
-		copy_to_user((unsigned char *)buf, data, ret);
+		if (copy_to_user((unsigned char *)buf, data, ret))
+			ret = -EFAULT;
 		break;
 	
 	case ENVCTRL_RD_GLOBALADDRESS:
@@ -635,7 +646,8 @@
 			return 0;
 		data[0] = envctrl_i2c_read_8574(pchild->addr);
 		ret = envctrl_i2c_globaladdr(pchild, data[0], data);
-		copy_to_user((unsigned char *)buf, data, ret);
+		if (copy_to_user((unsigned char *)buf, data, ret))
+			ret = -EFAULT;
 		break;
 
 	case ENVCTRL_RD_VOLTAGE_STATUS:
@@ -645,7 +657,8 @@
 				return 0;
 		data[0] = envctrl_i2c_read_8574(pchild->addr);
 		ret = envctrl_i2c_voltage_status(pchild, data[0], data);
-		copy_to_user((unsigned char *)buf, data, ret);
+		if (copy_to_user((unsigned char *)buf, data, ret))
+			ret = -EFAULT;
 		break;
 
 	default:
diff -Nru a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
--- a/drivers/sbus/char/jsflash.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/sbus/char/jsflash.c	Sat Jul 19 12:54:25 2003
@@ -38,12 +38,8 @@
 #include <linux/smp_lock.h>
 #include <linux/genhd.h>
 
-/*
- * <linux/blk.h> is controlled from the outside with these definitions.
- */
 #define MAJOR_NR	JSFD_MAJOR
 
-#include <linux/blk.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
diff -Nru a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
--- a/drivers/scsi/3w-xxxx.c	Sat Jul 19 12:54:29 2003
+++ b/drivers/scsi/3w-xxxx.c	Sat Jul 19 12:54:29 2003
@@ -187,7 +187,7 @@
 #include <linux/proc_fs.h>
 #include <linux/sched.h>
 #include <linux/ioport.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <linux/string.h>
 #include <linux/delay.h>
diff -Nru a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
--- a/drivers/scsi/53c700.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/scsi/53c700.c	Sat Jul 19 12:54:23 2003
@@ -131,7 +131,7 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/byteorder.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 
@@ -172,7 +172,7 @@
 STATIC int NCR_700_slave_configure(Scsi_Device *SDpnt);
 STATIC void NCR_700_slave_destroy(Scsi_Device *SDpnt);
 
-static struct device_attribute **NCR_700_dev_attrs = NULL;
+STATIC struct device_attribute *NCR_700_dev_attrs[];
 
 static char *NCR_700_phase[] = {
 	"",
@@ -2027,25 +2027,12 @@
 	.show = NCR_700_show_active_tags,
 };
 
-STATIC int __init
-NCR_700_init(void)
-{
-	scsi_sysfs_modify_sdev_attribute(&NCR_700_dev_attrs,
-					 &NCR_700_queue_depth_attr);
-	scsi_sysfs_modify_sdev_attribute(&NCR_700_dev_attrs,
-					 &NCR_700_active_tags_attr);
-	return 0;
-}
-
-/* NULL exit routine to keep modutils happy */
-STATIC void __exit
-NCR_700_exit(void)
-{
-}
+STATIC struct device_attribute *NCR_700_dev_attrs[] = {
+	&NCR_700_queue_depth_attr,
+	&NCR_700_active_tags_attr,
+	NULL,
+};
 
 EXPORT_SYMBOL(NCR_700_detect);
 EXPORT_SYMBOL(NCR_700_release);
 EXPORT_SYMBOL(NCR_700_intr);
-
-module_init(NCR_700_init);
-module_exit(NCR_700_exit);
diff -Nru a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c
--- a/drivers/scsi/53c7xx.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/scsi/53c7xx.c	Sat Jul 19 12:54:30 2003
@@ -249,7 +249,7 @@
 #include <linux/mm.h>
 #include <linux/ioport.h>
 #include <linux/time.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <asm/pgtable.h>
diff -Nru a/drivers/scsi/AM53C974.c b/drivers/scsi/AM53C974.c
--- a/drivers/scsi/AM53C974.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/AM53C974.c	Sat Jul 19 12:54:25 2003
@@ -7,7 +7,7 @@
 #include <linux/errno.h>
 #include <linux/pci.h>
 #include <linux/string.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 
diff -Nru a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
--- a/drivers/scsi/BusLogic.c	Sat Jul 19 12:54:29 2003
+++ b/drivers/scsi/BusLogic.c	Sat Jul 19 12:54:29 2003
@@ -36,7 +36,6 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/types.h>
-#include <linux/blk.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
diff -Nru a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
--- a/drivers/scsi/NCR53C9x.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/scsi/NCR53C9x.c	Sat Jul 19 12:54:23 2003
@@ -29,7 +29,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/interrupt.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -Nru a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
--- a/drivers/scsi/NCR53c406a.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/NCR53c406a.c	Sat Jul 19 12:54:25 2003
@@ -51,7 +51,7 @@
 #include <asm/bitops.h>
 #include <asm/irq.h>
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/spinlock.h>
 #include "scsi.h"
 #include "hosts.h"
diff -Nru a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c
--- a/drivers/scsi/NCR_D700.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/scsi/NCR_D700.c	Sat Jul 19 12:54:23 2003
@@ -218,7 +218,8 @@
 		goto irq_failed;
 	}
 
-	scsi_add_host(host, p->dev);
+	scsi_add_host(host, p->dev); /* XXX handle failure */
+	scsi_scan_host(host);
 
 	p->hosts[siop] = host;
 	hostdata->dev = p->dev;
@@ -387,7 +388,6 @@
 static void __exit NCR_D700_exit(void)
 {
 	mca_unregister_driver(&NCR_D700_driver);
-	scsi_sysfs_release_attributes(&NCR_D700_driver_template);
 }
 
 module_init(NCR_D700_init);
diff -Nru a/drivers/scsi/NCR_Q720.c b/drivers/scsi/NCR_Q720.c
--- a/drivers/scsi/NCR_Q720.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/scsi/NCR_Q720.c	Sat Jul 19 12:54:23 2003
@@ -85,6 +85,7 @@
 	__u8 scsr1 = readb(vaddr + NCR_Q720_SCSR_OFFSET + 1);
 	__u8 differential = readb(vaddr + NCR_Q720_SCSR_OFFSET) & 0x20;
 	__u8 version;
+	int error;
 
 	scsi_id = scsr1 >> 4;
 	/* enable burst length 16 (FIXME: should allow this) */
@@ -120,9 +121,12 @@
 	scsr1 &= ~0x01;
 	writeb(scsr1, vaddr + NCR_Q720_SCSR_OFFSET + 1);
 
-	scsi_add_host(p->hosts[siop], p->dev);
-
-	return 0;
+	error = scsi_add_host(p->hosts[siop], p->dev);
+	if (error)
+		ncr53c8xx_release(p->hosts[siop]);
+	else
+		scsi_scan_host(p->hosts[siop]);
+	return error;
 
  fail:
 	return -ENODEV;
@@ -347,7 +351,6 @@
 NCR_Q720_exit(void)
 {
 	mca_unregister_driver(&NCR_Q720_driver);
-	//scsi_sysfs_release_attributes(&NCR_Q720_driver_template);
 }
 
 module_init(NCR_Q720_init);
diff -Nru a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
--- a/drivers/scsi/a2091.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/a2091.c	Sat Jul 19 12:54:25 2003
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/sched.h>
 #include <linux/version.h>
 #include <linux/init.h>
diff -Nru a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
--- a/drivers/scsi/a3000.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/a3000.c	Sat Jul 19 12:54:26 2003
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/sched.h>
 #include <linux/version.h>
 #include <linux/ioport.h>
diff -Nru a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
--- a/drivers/scsi/aacraid/aachba.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/aacraid/aachba.c	Sat Jul 19 12:54:24 2003
@@ -33,7 +33,7 @@
 #include <linux/completion.h>
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include "scsi.h"
 #include "hosts.h"
 
diff -Nru a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
--- a/drivers/scsi/aacraid/commctrl.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/aacraid/commctrl.c	Sat Jul 19 12:54:24 2003
@@ -37,7 +37,7 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/completion.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
 #include "scsi.h"
diff -Nru a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
--- a/drivers/scsi/aacraid/comminit.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/scsi/aacraid/comminit.c	Sat Jul 19 12:54:22 2003
@@ -37,7 +37,7 @@
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/completion.h>
 #include <linux/mm.h>
 #include <asm/semaphore.h>
diff -Nru a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
--- a/drivers/scsi/aacraid/commsup.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/aacraid/commsup.c	Sat Jul 19 12:54:26 2003
@@ -41,7 +41,7 @@
 #include <linux/slab.h>
 #include <linux/completion.h>
 #include <asm/semaphore.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include "scsi.h"
 #include "hosts.h"
 
diff -Nru a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
--- a/drivers/scsi/aacraid/dpcsup.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/aacraid/dpcsup.c	Sat Jul 19 12:54:25 2003
@@ -38,7 +38,7 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/completion.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <asm/semaphore.h>
 #include "scsi.h"
 #include "hosts.h"
diff -Nru a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
--- a/drivers/scsi/aacraid/linit.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/aacraid/linit.c	Sat Jul 19 12:54:24 2003
@@ -50,7 +50,7 @@
 #include <linux/completion.h>
 #include <linux/interrupt.h>
 #include <asm/semaphore.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include "scsi.h"
 #include "hosts.h"
 #include <scsi/scsicam.h>
diff -Nru a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
--- a/drivers/scsi/aacraid/rx.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/scsi/aacraid/rx.c	Sat Jul 19 12:54:30 2003
@@ -36,7 +36,7 @@
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/completion.h>
 #include <linux/interrupt.h>
diff -Nru a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
--- a/drivers/scsi/aacraid/sa.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/aacraid/sa.c	Sat Jul 19 12:54:25 2003
@@ -36,7 +36,7 @@
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/completion.h>
 #include <linux/interrupt.h>
diff -Nru a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
--- a/drivers/scsi/advansys.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/advansys.c	Sat Jul 19 12:54:24 2003
@@ -798,7 +798,7 @@
 #include <linux/mm.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/stat.h>
 #include <linux/spinlock.h>
 
diff -Nru a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
--- a/drivers/scsi/aha152x.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/scsi/aha152x.c	Sat Jul 19 12:54:22 2003
@@ -225,7 +225,7 @@
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <linux/version.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include "scsi.h"
 #include "hosts.h"
 #include <asm/system.h>
@@ -241,9 +241,7 @@
 #include <linux/isapnp.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
-#include <linux/blk.h>
 #include <asm/semaphore.h>
-#include <asm/io.h>
 #include <scsi/scsicam.h>
 
 #include "scsi.h"
@@ -941,7 +939,8 @@
 	struct Scsi_Host *shpnt = lookup_irq(irqno);
 
 	if (!shpnt) {
-        	printk(KERN_ERR "aha152x%d: catched software interrupt %d for unknown controller.\n", HOSTNO, irqno);
+		/* no point using HOSTNO here! */
+        	printk(KERN_ERR "aha152x: catched software interrupt %d for unknown controller.\n", irqno);
 		return IRQ_NONE;
 	}
 
@@ -1049,6 +1048,10 @@
 
 	printk(KERN_INFO "aha152x%d: trying software interrupt, ",
 			 shost->host_no);
+
+	/* need to have host registered before triggering any interrupt */
+	aha152x_host[registered_count] = shost;
+	mb();
 	SETPORT(DMACNTRL0, SWINT|INTEN);
 	mdelay(1000);
 	free_irq(shost->irq, shost);
@@ -1064,7 +1067,7 @@
 
 		printk(KERN_ERR "aha152x%d: IRQ %d possibly wrong.  "
 				"Please verify.\n", shost->host_no, shost->irq);
-		goto out_release_region;
+		goto out_unregister_host;
 	}
 	printk("ok.\n");
 
@@ -1077,12 +1080,12 @@
 				"aha152x", shost) < 0) {
 		printk(KERN_ERR "aha152x%d: failed to reassign interrupt.\n",
 				shost->host_no);
-		goto out_release_region;
+		goto out_unregister_host;
 	}
-
-	aha152x_host[registered_count] = shost;
 	return shost;	/* the pcmcia stub needs the return value; */
 
+out_unregister_host:
+	aha152x_host[registered_count] = NULL;
 out_release_region:
 	release_region(shost->io_port, IO_RANGE);
 out_unregister:
diff -Nru a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
--- a/drivers/scsi/aha1542.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/aha1542.c	Sat Jul 19 12:54:25 2003
@@ -38,7 +38,7 @@
 #include <linux/spinlock.h>
 #include <linux/pci.h>
 #include <linux/isapnp.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/mca.h>
 #include <linux/mca-legacy.h>
 
diff -Nru a/drivers/scsi/aha1542.h b/drivers/scsi/aha1542.h
--- a/drivers/scsi/aha1542.h	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/aha1542.h	Sat Jul 19 12:54:26 2003
@@ -130,7 +130,6 @@
 };
 
 static int aha1542_detect(Scsi_Host_Template *);
-static int aha1542_command(Scsi_Cmnd *);
 static int aha1542_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 static int aha1542_abort(Scsi_Cmnd * SCpnt);
 static int aha1542_bus_reset(Scsi_Cmnd * SCpnt);
diff -Nru a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
--- a/drivers/scsi/aha1740.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/scsi/aha1740.c	Sat Jul 19 12:54:23 2003
@@ -34,7 +34,7 @@
  * are deemed to be part of the source code.
  */
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -375,7 +375,7 @@
 #endif
 
 	/* locate an available ecb */
-	spin_lock_irqsave(&SCpnt->device->host->host_lock, flags);
+	spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
 	ecbno = host->last_ecb_used + 1; /* An optimization */
 	if (ecbno >= AHA1740_ECBS)
 		ecbno = 0;
@@ -394,7 +394,7 @@
 						    doubles as reserved flag */
 
 	host->last_ecb_used = ecbno;    
-	spin_unlock_irqrestore(&SCpnt->device->host->host_lock, flags);
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
 
 #ifdef DEBUG
 	printk("Sending command (%d %x)...", ecbno, done);
@@ -491,7 +491,7 @@
 		unsigned int base = SCpnt->device->host->io_port;
 		DEB(printk("aha1740[%d] critical section\n",ecbno));
 
-		spin_lock_irqsave(&SCpnt->device->host->host_lock, flags);
+		spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
 		for (loopcnt = 0; ; loopcnt++) {
 			if (inb(G2STAT(base)) & G2STAT_MBXOUT) break;
 			if (loopcnt == LOOPCNT_WARN) {
@@ -511,7 +511,7 @@
 				panic("aha1740.c: attn wait failed!\n");
 		}
 		outb(ATTN_START | (target & 7), ATTN(base)); /* Start it up */
-		spin_unlock_irqrestore(&SCpnt->device->host->host_lock, flags);
+		spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
 		DEB(printk("aha1740[%d] request queued.\n",ecbno));
 	} else
 		printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n");
@@ -594,7 +594,7 @@
 	if (!request_region(slotbase, SLOTSIZE, "aha1740")) /* See if in use */
 		return -EBUSY;
 	if (!aha1740_test_port(slotbase))
-		goto err_release;
+		goto err_release_region;
 	aha1740_getconfig(slotbase,&irq_level,&translation);
 	if ((inb(G2STAT(slotbase)) &
 	     (G2STAT_MBXOUT|G2STAT_BUSY)) != G2STAT_MBXOUT) {
@@ -609,7 +609,7 @@
 	shpnt = scsi_host_alloc(&aha1740_template,
 			      sizeof(struct aha1740_hostdata));
 	if(shpnt == NULL)
-		goto err_release;
+		goto err_release_region;
 
 	shpnt->base = 0;
 	shpnt->io_port = slotbase;
@@ -625,21 +625,27 @@
 	if (!host->ecb_dma_addr) {
 		printk (KERN_ERR "aha1740_probe: Couldn't map ECB, giving up\n");
 		scsi_unregister (shpnt);
-		goto err_release;
+		goto err_host_put;
 	}
 	
 	DEB(printk("aha1740_probe: enable interrupt channel %d\n",irq_level));
 	if (request_irq(irq_level,aha1740_intr_handle,0,"aha1740",shpnt)) {
 		printk(KERN_ERR "aha1740_probe: Unable to allocate IRQ %d.\n",
 		       irq_level);
-		goto err_release;
+		goto err_unmap;
 	}
 
 	eisa_set_drvdata (edev, shpnt);
-	scsi_add_host (shpnt, dev);
+	scsi_add_host (shpnt, dev); /* XXX handle failure */
+	scsi_scan_host (shpnt);
 	return 0;
 
- err_release:
+ err_unmap:
+	dma_unmap_single (&edev->dev, host->ecb_dma_addr,
+			  sizeof (host->ecb), DMA_BIDIRECTIONAL);
+ err_host_put:
+	scsi_host_put (shpnt);
+ err_release_region:
 	release_region(slotbase, SLOTSIZE);
 
 	return -ENODEV;
diff -Nru a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c	Sat Jul 19 12:54:25 2003
@@ -2173,7 +2173,8 @@
 	ahd_unlock(ahd, &s);
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-	scsi_add_host(host, &ahd->dev_softc->dev);
+	scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */
+	scsi_scan_host(host);
 #endif
 	return (0);
 }
diff -Nru a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h	Sat Jul 19 12:54:25 2003
@@ -43,7 +43,6 @@
 #define _AIC79XX_LINUX_H_
 
 #include <linux/types.h>
-#include <linux/blk.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c	Sat Jul 19 12:54:22 2003
@@ -139,7 +139,7 @@
 #endif
 
 #include <linux/mm.h>		/* For fetching system memory size */
-#include <linux/blk.h>		/* For block_size() */
+#include <linux/blkdev.h>		/* For block_size() */
 
 /*
  * Lock protecting manipulation of the ahc softc list.
@@ -1811,7 +1811,8 @@
 	ahc_unlock(ahc, &s);
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-	scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL));
+	scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL)); /* XXX handle failure */
+	scsi_scan_host(host);
 #endif
 	return (0);
 }
diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h	Sat Jul 19 12:54:24 2003
@@ -60,7 +60,6 @@
 #define _AIC7XXX_LINUX_H_
 
 #include <linux/types.h>
-#include <linux/blk.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
diff -Nru a/drivers/scsi/aic7xxx/aiclib.c b/drivers/scsi/aic7xxx/aiclib.c
--- a/drivers/scsi/aic7xxx/aiclib.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/aic7xxx/aiclib.c	Sat Jul 19 12:54:25 2003
@@ -30,7 +30,6 @@
  * $Id$
  */
 
-#include <linux/blk.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/version.h>
diff -Nru a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
--- a/drivers/scsi/aic7xxx_old.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/aic7xxx_old.c	Sat Jul 19 12:54:24 2003
@@ -233,11 +233,10 @@
 #include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/smp.h>
-#include <linux/blk.h>
 #include <linux/interrupt.h>
 #include "scsi.h"
 #include "hosts.h"
diff -Nru a/drivers/scsi/amiga7xx.c b/drivers/scsi/amiga7xx.c
--- a/drivers/scsi/amiga7xx.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/amiga7xx.c	Sat Jul 19 12:54:24 2003
@@ -9,7 +9,7 @@
  */
 #include <linux/types.h>
 #include <linux/mm.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/sched.h>
 #include <linux/version.h>
 #include <linux/config.h>
diff -Nru a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
--- a/drivers/scsi/arm/acornscsi.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/arm/acornscsi.c	Sat Jul 19 12:54:25 2003
@@ -138,7 +138,7 @@
 #include <linux/errno.h>
 #include <linux/proc_fs.h>
 #include <linux/ioport.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -3043,9 +3043,13 @@
 	acornscsi_resetcard(ashost);
 
 	ret = scsi_add_host(host, &ec->dev);
-	if (ret == 0)
-		goto out;
+	if (ret)
+		goto err_7;
+
+	scsi_scan_host(host);
+	goto out;
 
+ err_7:
 	free_irq(host->irq, ashost);
  err_6:
 	release_region(host->io_port, 2048);
diff -Nru a/drivers/scsi/arm/arxescsi.c b/drivers/scsi/arm/arxescsi.c
--- a/drivers/scsi/arm/arxescsi.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/arm/arxescsi.c	Sat Jul 19 12:54:25 2003
@@ -19,7 +19,7 @@
  *  22-10-2000  SH		Updated for new registering scheme.
  */
 #include <linux/module.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
diff -Nru a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c
--- a/drivers/scsi/arm/cumana_1.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/scsi/arm/cumana_1.c	Sat Jul 19 12:54:22 2003
@@ -8,7 +8,7 @@
 #include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/init.h>
 
 #include <asm/ecard.h>
@@ -297,9 +297,13 @@
 	printk("\n");
 
 	ret = scsi_add_host(host, &ec->dev);
-	if (ret == 0)
-		goto out;
+	if (ret)
+		goto out_free_irq;
+
+	scsi_scan_host(host);
+	goto out;
 
+ out_free_irq:
 	free_irq(host->irq, host);
  out_release:
 	release_region(host->io_port, host->n_io_port);
diff -Nru a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c
--- a/drivers/scsi/arm/cumana_2.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/arm/cumana_2.c	Sat Jul 19 12:54:26 2003
@@ -17,7 +17,7 @@
  *   02-04-2000	RMK	0.0.4	Updated for new error handling code.
  */
 #include <linux/module.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
diff -Nru a/drivers/scsi/arm/ecoscsi.c b/drivers/scsi/arm/ecoscsi.c
--- a/drivers/scsi/arm/ecoscsi.c	Sat Jul 19 12:54:29 2003
+++ b/drivers/scsi/arm/ecoscsi.c	Sat Jul 19 12:54:29 2003
@@ -27,7 +27,7 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/init.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -205,7 +205,8 @@
 	NCR5380_print_options(host);
 	printk("\n");
 
-	scsi_add_host(host, NULL);
+	scsi_add_host(host, NULL); /* XXX handle failure */
+	scsi_scan_host(host);
 	return 0;
 
 release_reg:
diff -Nru a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
--- a/drivers/scsi/arm/eesox.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/scsi/arm/eesox.c	Sat Jul 19 12:54:30 2003
@@ -23,7 +23,7 @@
  *				error handling code.
  */
 #include <linux/module.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
diff -Nru a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
--- a/drivers/scsi/arm/fas216.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/arm/fas216.c	Sat Jul 19 12:54:24 2003
@@ -35,7 +35,7 @@
  *			condition status from targets.
  */
 #include <linux/module.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
@@ -2861,6 +2861,8 @@
 	ret = scsi_add_host(host, dev);
 	if (ret)
 		fas216_writeb(info, REG_CMD, CMD_RESETCHIP);
+	else
+		scsi_scan_host(host);
 
 	return ret;
 }
diff -Nru a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c
--- a/drivers/scsi/arm/oak.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/scsi/arm/oak.c	Sat Jul 19 12:54:21 2003
@@ -9,7 +9,7 @@
 #include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/init.h>
 
 #include <asm/ecard.h>
@@ -158,9 +158,13 @@
 	printk("\n");
 
 	ret = scsi_add_host(host, &ec->dev);
-	if (ret == 0)
-		goto out;
+	if (ret)
+		goto out_release;
+
+	scsi_scan_host(host);
+	goto out;
 
+ out_release:
 	release_region(host->io_port, host->n_io_port);
  unreg:
 	scsi_host_put(host);
diff -Nru a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
--- a/drivers/scsi/arm/powertec.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/arm/powertec.c	Sat Jul 19 12:54:26 2003
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 #include <linux/module.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
diff -Nru a/drivers/scsi/arm/queue.c b/drivers/scsi/arm/queue.c
--- a/drivers/scsi/arm/queue.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/scsi/arm/queue.c	Sat Jul 19 12:54:23 2003
@@ -15,7 +15,7 @@
  *   30-Aug-2000 RMK	Use Linux list handling and spinlocks
  */
 #include <linux/module.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/slab.h>
diff -Nru a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
--- a/drivers/scsi/atari_scsi.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/scsi/atari_scsi.c	Sat Jul 19 12:54:30 2003
@@ -86,7 +86,7 @@
 #include <linux/ctype.h>
 #include <linux/delay.h>
 #include <linux/mm.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
diff -Nru a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
--- a/drivers/scsi/atp870u.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/atp870u.c	Sat Jul 19 12:54:24 2003
@@ -26,7 +26,7 @@
 #include <linux/proc_fs.h>
 #include <linux/spinlock.h>
 #include <linux/pci.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/stat.h>
 
 #include <asm/system.h>
diff -Nru a/drivers/scsi/blz1230.c b/drivers/scsi/blz1230.c
--- a/drivers/scsi/blz1230.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/blz1230.c	Sat Jul 19 12:54:26 2003
@@ -22,7 +22,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/interrupt.h>
diff -Nru a/drivers/scsi/blz2060.c b/drivers/scsi/blz2060.c
--- a/drivers/scsi/blz2060.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/blz2060.c	Sat Jul 19 12:54:25 2003
@@ -22,7 +22,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/interrupt.h>
diff -Nru a/drivers/scsi/bvme6000.c b/drivers/scsi/bvme6000.c
--- a/drivers/scsi/bvme6000.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/scsi/bvme6000.c	Sat Jul 19 12:54:23 2003
@@ -5,7 +5,7 @@
  */
 #include <linux/types.h>
 #include <linux/mm.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/sched.h>
 #include <linux/version.h>
 #include <linux/zorro.h>
diff -Nru a/drivers/scsi/constants.c b/drivers/scsi/constants.c
--- a/drivers/scsi/constants.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/constants.c	Sat Jul 19 12:54:26 2003
@@ -9,7 +9,7 @@
 #include <linux/module.h>
 
 #include <linux/config.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/kernel.h>
 #include "scsi.h"
 #include "hosts.h"
diff -Nru a/drivers/scsi/cpqfcTScontrol.c b/drivers/scsi/cpqfcTScontrol.c
--- a/drivers/scsi/cpqfcTScontrol.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/scsi/cpqfcTScontrol.c	Sat Jul 19 12:54:22 2003
@@ -30,7 +30,7 @@
 
 #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>  // request_region() prototype
diff -Nru a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c
--- a/drivers/scsi/cpqfcTSinit.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/scsi/cpqfcTSinit.c	Sat Jul 19 12:54:22 2003
@@ -35,7 +35,7 @@
 #include <linux/interrupt.h>  
 #include <linux/module.h>
 #include <linux/version.h> 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/types.h>
diff -Nru a/drivers/scsi/cpqfcTSworker.c b/drivers/scsi/cpqfcTSworker.c
--- a/drivers/scsi/cpqfcTSworker.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/cpqfcTSworker.c	Sat Jul 19 12:54:26 2003
@@ -26,7 +26,7 @@
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/stat.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/smp_lock.h>
diff -Nru a/drivers/scsi/cyberstorm.c b/drivers/scsi/cyberstorm.c
--- a/drivers/scsi/cyberstorm.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/cyberstorm.c	Sat Jul 19 12:54:26 2003
@@ -25,7 +25,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/interrupt.h>
diff -Nru a/drivers/scsi/cyberstormII.c b/drivers/scsi/cyberstormII.c
--- a/drivers/scsi/cyberstormII.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/scsi/cyberstormII.c	Sat Jul 19 12:54:27 2003
@@ -21,7 +21,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/interrupt.h>
diff -Nru a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
--- a/drivers/scsi/dc395x.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/scsi/dc395x.c	Sat Jul 19 12:54:23 2003
@@ -50,7 +50,7 @@
 #include <linux/moduleparam.h>
 #include <linux/delay.h>
 #include <linux/ctype.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <asm/io.h>
 #include "scsi.h"
 #include "hosts.h"
@@ -6214,7 +6214,8 @@
 	pci_set_drvdata(pdev, scsi_host);
 
 	/* get the scsi mid level to scan for new devices on the bus */
-	scsi_add_host(scsi_host, &pdev->dev);
+	scsi_add_host(scsi_host, &pdev->dev);	/* XXX handle failure */
+	scsi_scan_host(scsi_host);
 
 	return 0;
 }
diff -Nru a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c
--- a/drivers/scsi/dec_esp.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/dec_esp.c	Sat Jul 19 12:54:26 2003
@@ -24,7 +24,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 
diff -Nru a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c
--- a/drivers/scsi/dmx3191d.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/dmx3191d.c	Sat Jul 19 12:54:25 2003
@@ -22,7 +22,7 @@
 
 #include <asm/io.h>
 #include <asm/system.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
diff -Nru a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
--- a/drivers/scsi/dpt_i2o.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/scsi/dpt_i2o.c	Sat Jul 19 12:54:27 2003
@@ -47,7 +47,7 @@
 #include <linux/config.h>	/* for CONFIG_PCI */
 #include <linux/pci.h>		/* for PCI support */
 #include <linux/proc_fs.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/delay.h>	/* for udelay */
 #include <linux/interrupt.h>
 #include <linux/kernel.h>	/* for printk */
diff -Nru a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c
--- a/drivers/scsi/dtc.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/dtc.c	Sat Jul 19 12:54:26 2003
@@ -76,7 +76,7 @@
 #include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/stat.h>
 #include <linux/string.h>
diff -Nru a/drivers/scsi/eata.c b/drivers/scsi/eata.c
--- a/drivers/scsi/eata.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/scsi/eata.c	Sat Jul 19 12:54:27 2003
@@ -486,7 +486,7 @@
 #include <asm/system.h>
 #include <asm/byteorder.h>
 #include <linux/proc_fs.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/interrupt.h>
 #include <linux/stat.h>
 #include <linux/pci.h>
diff -Nru a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
--- a/drivers/scsi/eata_pio.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/eata_pio.c	Sat Jul 19 12:54:26 2003
@@ -58,7 +58,7 @@
 #include <linux/interrupt.h>
 #include <linux/stat.h>
 #include <linux/config.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/spinlock.h>
 #include <asm/io.h>
 
diff -Nru a/drivers/scsi/esp.c b/drivers/scsi/esp.c
--- a/drivers/scsi/esp.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/scsi/esp.c	Sat Jul 19 12:54:30 2003
@@ -19,7 +19,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/init.h>
diff -Nru a/drivers/scsi/fastlane.c b/drivers/scsi/fastlane.c
--- a/drivers/scsi/fastlane.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/fastlane.c	Sat Jul 19 12:54:24 2003
@@ -30,7 +30,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/interrupt.h>
diff -Nru a/drivers/scsi/fcal.c b/drivers/scsi/fcal.c
--- a/drivers/scsi/fcal.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/scsi/fcal.c	Sat Jul 19 12:54:22 2003
@@ -9,7 +9,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/init.h>
diff -Nru a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
--- a/drivers/scsi/fd_mcs.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/fd_mcs.c	Sat Jul 19 12:54:24 2003
@@ -79,7 +79,7 @@
 
 #include <linux/module.h>
 #include <linux/interrupt.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
diff -Nru a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
--- a/drivers/scsi/fdomain.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/fdomain.c	Sat Jul 19 12:54:26 2003
@@ -270,7 +270,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
 #include <linux/string.h>
diff -Nru a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
--- a/drivers/scsi/g_NCR5380.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/scsi/g_NCR5380.c	Sat Jul 19 12:54:23 2003
@@ -105,7 +105,7 @@
 #include <asm/io.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include "scsi.h"
 #include "hosts.h"
 #include "g_NCR5380.h"
diff -Nru a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
--- a/drivers/scsi/gdth.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/gdth.c	Sat Jul 19 12:54:25 2003
@@ -357,11 +357,8 @@
 #include <asm/spinlock.h>
 #endif
 
-#if LINUX_VERSION_CODE >= 0x010300
-#include <linux/blk.h>
-#else
-#include "../block/blk.h"
-#endif
+#include <linux/blkdev.h>
+
 #include "scsi.h"
 #include "hosts.h"
 #if LINUX_VERSION_CODE < 0x020503
diff -Nru a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c
--- a/drivers/scsi/gvp11.c	Sat Jul 19 12:54:28 2003
+++ b/drivers/scsi/gvp11.c	Sat Jul 19 12:54:28 2003
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/sched.h>
 #include <linux/version.h>
 #include <linux/init.h>
diff -Nru a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
--- a/drivers/scsi/hosts.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/scsi/hosts.c	Sat Jul 19 12:54:22 2003
@@ -81,19 +81,15 @@
 	printk(KERN_INFO "scsi%d : %s\n", shost->host_no,
 			sht->info ? sht->info(shost) : sht->name);
 
-	error = scsi_sysfs_add_host(shost, dev);
-
 	if (!shost->can_queue) {
 		printk(KERN_ERR "%s: can_queue = 0 no longer supported\n",
 				sht->name);
 		error = -EINVAL;
 	}
 
-	if (!error) {
+	error = scsi_sysfs_add_host(shost, dev);
+	if (!error)
 		scsi_proc_host_add(shost);
-		scsi_scan_host(shost);
-	}
-			
 	return error;
 }
 
@@ -151,12 +147,6 @@
 		dump_stack();
         }
 
-	/* if its not set in the template, use the default */
-	if (!sht->shost_attrs)
-		 sht->shost_attrs = scsi_sysfs_shost_attrs;
-	if (!sht->sdev_attrs)
-		 sht->sdev_attrs = scsi_sysfs_sdev_attrs;
-
 	shost = kmalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask);
 	if (!shost)
 		return NULL;
@@ -283,8 +273,8 @@
  **/
 void scsi_host_get(struct Scsi_Host *shost)
 {
-	get_device(&shost->host_gendev);
-	class_device_get(&shost->class_dev);
+	get_device(&shost->shost_gendev);
+	class_device_get(&shost->shost_classdev);
 }
 
 /**
@@ -293,6 +283,6 @@
  **/
 void scsi_host_put(struct Scsi_Host *shost)
 {
-	class_device_put(&shost->class_dev);
-	put_device(&shost->host_gendev);
+	class_device_put(&shost->shost_classdev);
+	put_device(&shost->shost_gendev);
 }
diff -Nru a/drivers/scsi/i91uscsi.c b/drivers/scsi/i91uscsi.c
--- a/drivers/scsi/i91uscsi.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/scsi/i91uscsi.c	Sat Jul 19 12:54:23 2003
@@ -81,7 +81,7 @@
 
 #include <linux/jiffies.h>
 #include <linux/delay.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <asm/io.h>
 
 #include "i91uscsi.h"
diff -Nru a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
--- a/drivers/scsi/ibmmca.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/scsi/ibmmca.c	Sat Jul 19 12:54:23 2003
@@ -32,7 +32,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/mca.h>
diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
--- a/drivers/scsi/ide-scsi.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/ide-scsi.c	Sat Jul 19 12:54:26 2003
@@ -978,8 +978,10 @@
 		idescsi_setup (drive, idescsi);
 		drive->disk->fops = &idescsi_ops;
 		err = scsi_add_host(host, &idescsi_primary);
-		if (!err)
+		if (!err) {
+			scsi_scan_host(host);
 			return 0;
+		}
 		/* fall through on error */
 		ide_unregister_subdriver(drive);
 	}
diff -Nru a/drivers/scsi/imm.c b/drivers/scsi/imm.c
--- a/drivers/scsi/imm.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/scsi/imm.c	Sat Jul 19 12:54:30 2003
@@ -24,7 +24,7 @@
 void imm_reset_pulse(unsigned int base);
 static int device_check(int host_no);
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <asm/io.h>
 #include <linux/parport.h>
 #include <linux/workqueue.h>
diff -Nru a/drivers/scsi/imm.h b/drivers/scsi/imm.h
--- a/drivers/scsi/imm.h	Sat Jul 19 12:54:21 2003
+++ b/drivers/scsi/imm.h	Sat Jul 19 12:54:21 2003
@@ -75,7 +75,7 @@
 #include  <linux/delay.h>
 #include  <linux/proc_fs.h>
 #include  <linux/stat.h>
-#include  <linux/blk.h>
+#include  <linux/blkdev.h>
 #include  <linux/sched.h>
 #include  <linux/interrupt.h>
 
diff -Nru a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c
--- a/drivers/scsi/in2000.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/in2000.c	Sat Jul 19 12:54:26 2003
@@ -114,7 +114,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/blk.h>
 #include <linux/blkdev.h>
 #include <linux/interrupt.h>
 #include <linux/string.h>
diff -Nru a/drivers/scsi/ini9100u.c b/drivers/scsi/ini9100u.c
--- a/drivers/scsi/ini9100u.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/ini9100u.c	Sat Jul 19 12:54:24 2003
@@ -119,7 +119,7 @@
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/init.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/spinlock.h>
 #include <linux/stat.h>
 #include <linux/config.h>
diff -Nru a/drivers/scsi/inia100.c b/drivers/scsi/inia100.c
--- a/drivers/scsi/inia100.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/inia100.c	Sat Jul 19 12:54:24 2003
@@ -74,7 +74,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/spinlock.h>
 #include <linux/stat.h>
 #include <linux/kernel.h>
diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c
--- a/drivers/scsi/ips.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/scsi/ips.c	Sat Jul 19 12:54:21 2003
@@ -167,7 +167,7 @@
 #include <linux/reboot.h>
 #include <linux/interrupt.h>
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/types.h>
 
 #include <scsi/sg.h>
diff -Nru a/drivers/scsi/ips.h b/drivers/scsi/ips.h
--- a/drivers/scsi/ips.h	Sat Jul 19 12:54:23 2003
+++ b/drivers/scsi/ips.h	Sat Jul 19 12:54:23 2003
@@ -111,7 +111,7 @@
    #else
       #define IPS_REGISTER_HOSTS(SHT)      (!ips_detect(SHT))
       #define IPS_UNREGISTER_HOSTS(SHT)
-      #define IPS_ADD_HOST(shost,device)   scsi_add_host(shost,device)
+      #define IPS_ADD_HOST(shost,device)   do { scsi_add_host(shost,device); scsi_scan_host(shost); } while (0)
       #define IPS_REMOVE_HOST(shost)       scsi_remove_host(shost)
       #define IPS_SCSI_SET_DEVICE(sh,ha)   scsi_set_device(sh, &(ha)->pcidev->dev)
       #define IPS_PRINTK(level, pcidev, format, arg...)                 \
diff -Nru a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c
--- a/drivers/scsi/jazz_esp.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/scsi/jazz_esp.c	Sat Jul 19 12:54:22 2003
@@ -11,7 +11,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 
diff -Nru a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
--- a/drivers/scsi/lasi700.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/scsi/lasi700.c	Sat Jul 19 12:54:22 2003
@@ -128,7 +128,8 @@
 	}
 
 	dev_set_drvdata(&dev->dev, host);
-	scsi_add_host(host, &dev->dev);
+	scsi_add_host(host, &dev->dev); /* XXX handle failure */
+	scsi_scan_host(host);
 
 	return 0;
 
@@ -165,7 +166,6 @@
 lasi700_exit(void)
 {
 	unregister_parisc_driver(&lasi700_driver);
-	scsi_sysfs_release_attributes(&lasi700_template);
 }
 
 module_init(lasi700_init);
diff -Nru a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
--- a/drivers/scsi/mac53c94.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/scsi/mac53c94.c	Sat Jul 19 12:54:22 2003
@@ -12,7 +12,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/spinlock.h>
diff -Nru a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
--- a/drivers/scsi/mac_esp.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/mac_esp.c	Sat Jul 19 12:54:25 2003
@@ -19,7 +19,7 @@
 #include <linux/ctype.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/init.h>
diff -Nru a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
--- a/drivers/scsi/mac_scsi.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/scsi/mac_scsi.c	Sat Jul 19 12:54:22 2003
@@ -39,7 +39,7 @@
 #include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/interrupt.h>
 
 #include <asm/io.h>
diff -Nru a/drivers/scsi/mca_53c9x.c b/drivers/scsi/mca_53c9x.c
--- a/drivers/scsi/mca_53c9x.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/mca_53c9x.c	Sat Jul 19 12:54:24 2003
@@ -37,7 +37,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/mca-legacy.h>
diff -Nru a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
--- a/drivers/scsi/megaraid.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/scsi/megaraid.c	Sat Jul 19 12:54:21 2003
@@ -32,7 +32,7 @@
 
 #include <linux/mm.h>
 #include <linux/fs.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/delay.h>
diff -Nru a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
--- a/drivers/scsi/mesh.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/mesh.c	Sat Jul 19 12:54:26 2003
@@ -21,7 +21,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/interrupt.h>
diff -Nru a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c
--- a/drivers/scsi/mvme147.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/mvme147.c	Sat Jul 19 12:54:24 2003
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/sched.h>
 #include <linux/version.h>
 #include <linux/interrupt.h>
diff -Nru a/drivers/scsi/mvme16x.c b/drivers/scsi/mvme16x.c
--- a/drivers/scsi/mvme16x.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/scsi/mvme16x.c	Sat Jul 19 12:54:27 2003
@@ -5,7 +5,7 @@
  */
 #include <linux/types.h>
 #include <linux/mm.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/sched.h>
 #include <linux/version.h>
 
diff -Nru a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
--- a/drivers/scsi/ncr53c8xx.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/ncr53c8xx.c	Sat Jul 19 12:54:24 2003
@@ -140,7 +140,7 @@
 #include <linux/timer.h>
 #include <linux/stat.h>
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,35)
 #include <linux/init.h>
diff -Nru a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
--- a/drivers/scsi/nsp32.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/nsp32.c	Sat Jul 19 12:54:24 2003
@@ -25,7 +25,7 @@
 #include <linux/timer.h>
 #include <linux/ioport.h>
 #include <linux/major.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -1820,7 +1820,8 @@
 		goto free_irq;
         }
 
-	scsi_add_host(host, &pdev->dev);
+	scsi_add_host(host, &pdev->dev); /* XXX handle failure */
+	scsi_scan_host(host);
 	pci_set_drvdata(pdev, host);
 	return 0;
 
diff -Nru a/drivers/scsi/oktagon_esp.c b/drivers/scsi/oktagon_esp.c
--- a/drivers/scsi/oktagon_esp.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/scsi/oktagon_esp.c	Sat Jul 19 12:54:21 2003
@@ -20,7 +20,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/reboot.h>
diff -Nru a/drivers/scsi/osst.c b/drivers/scsi/osst.c
--- a/drivers/scsi/osst.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/osst.c	Sat Jul 19 12:54:25 2003
@@ -46,7 +46,7 @@
 #include <linux/spinlock.h>
 #include <linux/vmalloc.h>
 #include <linux/version.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/devfs_fs_kernel.h>
 #include <asm/uaccess.h>
 #include <asm/dma.h>
diff -Nru a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c
--- a/drivers/scsi/pas16.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/scsi/pas16.c	Sat Jul 19 12:54:21 2003
@@ -117,7 +117,8 @@
 #include <linux/proc_fs.h>
 #include <linux/sched.h>
 #include <asm/io.h>
-#include <linux/blk.h>
+#include <asm/dma.h>
+#include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/stat.h>
diff -Nru a/drivers/scsi/pc980155.c b/drivers/scsi/pc980155.c
--- a/drivers/scsi/pc980155.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/scsi/pc980155.c	Sat Jul 19 12:54:22 2003
@@ -11,7 +11,7 @@
  */
 
 #include <linux/module.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/types.h>
diff -Nru a/drivers/scsi/pci2000.c b/drivers/scsi/pci2000.c
--- a/drivers/scsi/pci2000.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/pci2000.c	Sat Jul 19 12:54:26 2003
@@ -35,7 +35,7 @@
  ****************************************************************************/
 #define PCI2000_VERSION		"1.20"
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
diff -Nru a/drivers/scsi/pci2220i.c b/drivers/scsi/pci2220i.c
--- a/drivers/scsi/pci2220i.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/scsi/pci2220i.c	Sat Jul 19 12:54:21 2003
@@ -50,7 +50,7 @@
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/timer.h>
 #include <linux/spinlock.h>
 
diff -Nru a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
--- a/drivers/scsi/pcmcia/aha152x_stub.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/scsi/pcmcia/aha152x_stub.c	Sat Jul 19 12:54:27 2003
@@ -44,7 +44,7 @@
 #include <linux/ioport.h>
 #include <scsi/scsi.h>
 #include <linux/major.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <scsi/scsi_ioctl.h>
 
 #include "scsi.h"
@@ -278,7 +278,8 @@
 	goto cs_failed;
     }
 
-    scsi_add_host(host, NULL);
+    scsi_add_host(host, NULL); /* XXX handle failure */
+    scsi_scan_host(host);
 
     sprintf(info->node.dev_name, "scsi%d", host->host_no);
     link->dev = &info->node;
diff -Nru a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
--- a/drivers/scsi/pcmcia/fdomain_stub.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/pcmcia/fdomain_stub.c	Sat Jul 19 12:54:25 2003
@@ -41,7 +41,7 @@
 #include <linux/ioport.h>
 #include <scsi/scsi.h>
 #include <linux/major.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <scsi/scsi_ioctl.h>
 
 #include "scsi.h"
@@ -254,7 +254,8 @@
 	goto cs_failed;
     }
  
-    scsi_add_host(host, NULL);
+    scsi_add_host(host, NULL); /* XXX handle failure */
+    scsi_scan_host(host);
 
     sprintf(info->node.dev_name, "scsi%d", host->host_no);
     link->dev = &info->node;
diff -Nru a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
--- a/drivers/scsi/pcmcia/nsp_cs.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/scsi/pcmcia/nsp_cs.c	Sat Jul 19 12:54:30 2003
@@ -44,7 +44,7 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/major.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/stat.h>
 
 #include <asm/io.h>
@@ -1773,7 +1773,8 @@
 		       req.Base+req.Size-1);
 	printk("\n");
 
-	scsi_add_host(host, NULL);
+	scsi_add_host(host, NULL); /* XXX handle failure */
+	scsi_scan_host(host);
 	link->state &= ~DEV_CONFIG_PENDING;
 	return;
 
diff -Nru a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
--- a/drivers/scsi/pcmcia/qlogic_stub.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/pcmcia/qlogic_stub.c	Sat Jul 19 12:54:25 2003
@@ -42,7 +42,7 @@
 #include <asm/io.h>
 #include <scsi/scsi.h>
 #include <linux/major.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <scsi/scsi_ioctl.h>
 
 #include "scsi.h"
@@ -270,7 +270,8 @@
 	link->dev = &info->node;
 	info->host = host;
 
-	scsi_add_host(host, NULL);
+	scsi_add_host(host, NULL); /* XXX handle failure */
+	scsi_scan_host(host);
 
 out:
 	link->state &= ~DEV_CONFIG_PENDING;
diff -Nru a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
--- a/drivers/scsi/pluto.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/pluto.c	Sat Jul 19 12:54:24 2003
@@ -9,7 +9,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/init.h>
diff -Nru a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
--- a/drivers/scsi/ppa.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/ppa.c	Sat Jul 19 12:54:25 2003
@@ -15,7 +15,7 @@
 /* The following #define is to avoid a clash with hosts.c */
 #define PPA_CODE 1
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <asm/io.h>
 #include <linux/parport.h>
 #include <linux/workqueue.h>
diff -Nru a/drivers/scsi/ppa.h b/drivers/scsi/ppa.h
--- a/drivers/scsi/ppa.h	Sat Jul 19 12:54:27 2003
+++ b/drivers/scsi/ppa.h	Sat Jul 19 12:54:27 2003
@@ -82,7 +82,7 @@
 #include  <linux/delay.h>
 #include  <linux/proc_fs.h>
 #include  <linux/stat.h>
-#include  <linux/blk.h>
+#include  <linux/blkdev.h>
 #include  <linux/sched.h>
 #include  <linux/interrupt.h>
 
diff -Nru a/drivers/scsi/psi240i.c b/drivers/scsi/psi240i.c
--- a/drivers/scsi/psi240i.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/psi240i.c	Sat Jul 19 12:54:26 2003
@@ -26,7 +26,7 @@
 
 #include <linux/module.h>
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/string.h>
diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
--- a/drivers/scsi/qla1280.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/scsi/qla1280.c	Sat Jul 19 12:54:30 2003
@@ -252,7 +252,7 @@
 #include <linux/timer.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/workqueue.h>
 #include <linux/stat.h>
 #include <linux/slab.h>
@@ -327,7 +327,7 @@
 /* 3.16 */
 #ifdef QLA_64BIT_PTR
 #define pci_dma_lo32(a)		(a & 0xffffffff)
-#define pci_dma_hi32(a)		(a >> 32)
+#define pci_dma_hi32(a)		((a >> 16)>>16)
 #else
 #define pci_dma_lo32(a)		(a & 0xffffffff)
 #define pci_dma_hi32(a)		0
diff -Nru a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c
--- a/drivers/scsi/qlogicfas.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/scsi/qlogicfas.c	Sat Jul 19 12:54:30 2003
@@ -127,7 +127,7 @@
 #endif
 
 #include <linux/module.h>
-#include <linux/blk.h>		/* to get disk capacity */
+#include <linux/blkdev.h>		/* to get disk capacity */
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/init.h>
@@ -140,6 +140,7 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/dma.h>
 
 #include "scsi.h"
 #include "hosts.h"
diff -Nru a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c
--- a/drivers/scsi/qlogicfc.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/qlogicfc.c	Sat Jul 19 12:54:26 2003
@@ -50,7 +50,7 @@
  *
  */
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
diff -Nru a/drivers/scsi/qlogicisp.c b/drivers/scsi/qlogicisp.c
--- a/drivers/scsi/qlogicisp.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/scsi/qlogicisp.c	Sat Jul 19 12:54:30 2003
@@ -20,7 +20,7 @@
  * General Public License for more details.
  */
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
diff -Nru a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
--- a/drivers/scsi/qlogicpti.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/qlogicpti.c	Sat Jul 19 12:54:26 2003
@@ -17,7 +17,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/init.h>
diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h
--- a/drivers/scsi/scsi.h	Sat Jul 19 12:54:23 2003
+++ b/drivers/scsi/scsi.h	Sat Jul 19 12:54:23 2003
@@ -174,11 +174,6 @@
 #define SCSI_MLQUEUE_DEVICE_BUSY 0x1056
 #define SCSI_MLQUEUE_EH_RETRY    0x1057
 
-extern int scsi_sysfs_modify_sdev_attribute(struct device_attribute ***dev_attrs,
-					    struct device_attribute *attr);
-extern int scsi_sysfs_modify_shost_attribute(struct class_device_attribute ***class_attrs,
-					     struct class_device_attribute *attr);
-
 /*
  * Legacy dma direction interfaces.
  *
diff -Nru a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
--- a/drivers/scsi/scsi_debug.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/scsi_debug.c	Sat Jul 19 12:54:25 2003
@@ -41,7 +41,7 @@
 #include <linux/vmalloc.h>
 #include <linux/moduleparam.h>
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include "scsi.h"
 #include "hosts.h"
 #include <scsi/scsicam.h>
@@ -687,7 +687,7 @@
 	pcontrol = (cmd[2] & 0xc0) >> 6;
 	pcode = cmd[2] & 0x3f;
 	msense_6 = (MODE_SENSE == cmd[0]);
-	alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[6]);
+	alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]);
 	/* printk(KERN_INFO "msense: dbd=%d pcontrol=%d pcode=%d "
 		"msense_6=%d alloc_len=%d\n", dbd, pcontrol, pcode, "
 		"msense_6, alloc_len); */
@@ -1701,7 +1701,8 @@
                 printk(KERN_ERR "%s: scsi_add_host failed\n", __FUNCTION__);
                 error = -ENODEV;
 		scsi_host_put(hpnt);
-        }
+        } else
+		scsi_scan_host(hpnt);
 
 
         return error;
diff -Nru a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
--- a/drivers/scsi/scsi_ioctl.c	Sat Jul 19 12:54:29 2003
+++ b/drivers/scsi/scsi_ioctl.c	Sat Jul 19 12:54:29 2003
@@ -18,7 +18,7 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include "scsi.h"
 #include "hosts.h"
 #include <scsi/scsi_ioctl.h>
diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/scsi_lib.c	Sat Jul 19 12:54:25 2003
@@ -8,7 +8,7 @@
  */
 
 #include <linux/bio.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/completion.h>
 #include <linux/kernel.h>
 #include <linux/mempool.h>
@@ -444,22 +444,8 @@
  */
 static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(q->queue_lock, flags);
-	cmd->request->special = cmd;
-	if (blk_rq_tagged(cmd->request))
-		blk_queue_end_tag(q, cmd->request);
-
-	/*
-	 * set REQ_SPECIAL - we have a command
-	 * clear REQ_DONTPREP - we assume the sg table has been 
-	 *	nuked so we need to set it up again.
-	 */
-	cmd->request->flags |= REQ_SPECIAL;
 	cmd->request->flags &= ~REQ_DONTPREP;
-	__elv_add_request(q, cmd->request, 0, 0);
-	spin_unlock_irqrestore(q->queue_lock, flags);
+	blk_insert_request(q, cmd->request, 1, cmd);
 
 	scsi_run_queue(q);
 }
@@ -1213,9 +1199,7 @@
 	 * later time.
 	 */
 	spin_lock_irq(q->queue_lock);
-	if (blk_rq_tagged(req))
-		blk_queue_end_tag(q, req);
-	__elv_add_request(q, req, 0, 0);
+	blk_requeue_request(q, req);
 	sdev->device_busy--;
 	if(sdev->device_busy == 0)
 		blk_plug_device(q);
@@ -1426,17 +1410,17 @@
 	if(scsi_status_is_good(sreq->sr_result)) {
 		data->header_length = header_length;
 		if(use_10_for_ms) {
-			data->length = buffer[0]*256 + buffer[1];
+			data->length = buffer[0]*256 + buffer[1] + 2;
 			data->medium_type = buffer[2];
 			data->device_specific = buffer[3];
 			data->longlba = buffer[4] & 0x01;
 			data->block_descriptor_length = buffer[6]*256
 				+ buffer[7];
 		} else {
-			data->length = buffer[0];
+			data->length = buffer[0] + 1;
 			data->medium_type = buffer[1];
-			data->device_specific = buffer[3];
-			data->block_descriptor_length = buffer[4];
+			data->device_specific = buffer[2];
+			data->block_descriptor_length = buffer[3];
 		}
 	}
 
diff -Nru a/drivers/scsi/scsi_module.c b/drivers/scsi/scsi_module.c
--- a/drivers/scsi/scsi_module.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/scsi_module.c	Sat Jul 19 12:54:24 2003
@@ -40,6 +40,7 @@
 		error = scsi_add_host(shost, NULL);
 		if (error)
 			goto fail;
+		scsi_scan_host(shost);
 	}
 	return 0;
  fail:
diff -Nru a/drivers/scsi/scsi_pc98.c b/drivers/scsi/scsi_pc98.c
--- a/drivers/scsi/scsi_pc98.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/scsi/scsi_pc98.c	Sat Jul 19 12:54:21 2003
@@ -8,7 +8,7 @@
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/genhd.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <asm/pc9800.h>
 
 #include "scsi.h"
diff -Nru a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
--- a/drivers/scsi/scsi_priv.h	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/scsi_priv.h	Sat Jul 19 12:54:26 2003
@@ -102,7 +102,6 @@
 #endif /* CONFIG_PROC_FS */
 
 /* scsi_scan.c */
-extern void scsi_scan_host(struct Scsi_Host *);
 extern void scsi_forget_host(struct Scsi_Host *);
 extern void scsi_free_sdev(struct scsi_device *);
 extern void scsi_free_shost(struct Scsi_Host *);
@@ -116,11 +115,6 @@
 extern void scsi_sysfs_remove_host(struct Scsi_Host *);
 extern int scsi_sysfs_register(void);
 extern void scsi_sysfs_unregister(void);
-
-/* definitions for the linker default sections covering the host
- * class and device attributes */
-extern struct class_device_attribute *scsi_sysfs_shost_attrs[];
-extern struct device_attribute *scsi_sysfs_sdev_attrs[];
 
 extern struct class shost_class;
 extern struct bus_type scsi_bus_type;
diff -Nru a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
--- a/drivers/scsi/scsi_proc.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/scsi/scsi_proc.c	Sat Jul 19 12:54:22 2003
@@ -23,7 +23,7 @@
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/errno.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/seq_file.h>
 #include <asm/uaccess.h>
 
diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
--- a/drivers/scsi/scsi_scan.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/scsi/scsi_scan.c	Sat Jul 19 12:54:27 2003
@@ -29,7 +29,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 
 #include "scsi.h"
 #include "hosts.h"
@@ -464,8 +464,7 @@
 	while (i >= 0 && type[i] == ' ')
 		type[i--] = '\0';
 
-	snprintf(sdev->sdev_driverfs_dev.name, DEVICE_NAME_SIZE, "SCSI %s",
-		 type);
+	snprintf(sdev->sdev_gendev.name, DEVICE_NAME_SIZE, "SCSI %s", type);
 }
 
 /**
diff -Nru a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c
--- a/drivers/scsi/scsi_syms.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/scsi_syms.c	Sat Jul 19 12:54:25 2003
@@ -11,7 +11,7 @@
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/fs.h>
 
 #include <asm/system.h>
@@ -34,6 +34,7 @@
 EXPORT_SYMBOL(scsi_register_interface);
 EXPORT_SYMBOL(scsi_host_alloc);
 EXPORT_SYMBOL(scsi_add_host);
+EXPORT_SYMBOL(scsi_scan_host);
 EXPORT_SYMBOL(scsi_remove_host);
 EXPORT_SYMBOL(scsi_host_get);
 EXPORT_SYMBOL(scsi_host_put);
diff -Nru a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
--- a/drivers/scsi/scsi_sysfs.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/scsi/scsi_sysfs.c	Sat Jul 19 12:54:23 2003
@@ -45,7 +45,7 @@
 shost_rd_attr(sg_tablesize, "%hu\n");
 shost_rd_attr(unchecked_isa_dma, "%d\n");
 
-struct class_device_attribute *scsi_sysfs_shost_attrs[] = {
+static struct class_device_attribute *scsi_sysfs_shost_attrs[] = {
 	&class_device_attr_unique_id,
 	&class_device_attr_host_busy,
 	&class_device_attr_cmd_per_lun,
@@ -204,7 +204,7 @@
 static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field)
 
 /* Default template for device attributes.  May NOT be modified */
-struct device_attribute *scsi_sysfs_sdev_attrs[] = {
+static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
 	&dev_attr_device_blocked,
 	&dev_attr_queue_depth,
 	&dev_attr_type,
@@ -228,6 +228,42 @@
 	scsi_free_sdev(sdev);
 }
 
+static struct device_attribute *attr_overridden(
+		struct device_attribute **attrs,
+		struct device_attribute *attr)
+{
+	int i;
+
+	if (!attrs)
+		return NULL;
+	for (i = 0; attrs[i]; i++)
+		if (!strcmp(attrs[i]->attr.name, attr->attr.name))
+			return attrs[i];
+	return NULL;
+}
+
+static int attr_add(struct device *dev, struct device_attribute *attr)
+{
+	struct device_attribute *base_attr;
+
+	/*
+	 * Spare the caller from having to copy things it's not interested in.
+	 */
+	base_attr = attr_overridden(scsi_sysfs_sdev_attrs, attr);
+	if (base_attr) {
+		/* extend permissions */
+		attr->attr.mode |= base_attr->attr.mode;
+
+		/* override null show/store with default */
+		if (!attr->show)
+			attr->show = base_attr->show;
+		if (!attr->store)
+			attr->store = base_attr->store;
+	}
+
+	return device_create_file(dev, attr);
+}
+
 /**
  * scsi_device_register - register a scsi device with the scsi bus
  * @sdev:	scsi_device to register
@@ -239,20 +275,20 @@
 {
 	int error = 0, i;
 
-	device_initialize(&sdev->sdev_driverfs_dev);
-	sprintf(sdev->sdev_driverfs_dev.bus_id,"%d:%d:%d:%d",
+	device_initialize(&sdev->sdev_gendev);
+	sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d",
 		sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
-	sdev->sdev_driverfs_dev.parent = &sdev->host->host_gendev;
-	sdev->sdev_driverfs_dev.bus = &scsi_bus_type;
-	sdev->sdev_driverfs_dev.release = scsi_device_release;
+	sdev->sdev_gendev.parent = &sdev->host->shost_gendev;
+	sdev->sdev_gendev.bus = &scsi_bus_type;
+	sdev->sdev_gendev.release = scsi_device_release;
 
 	class_device_initialize(&sdev->sdev_classdev);
-	sdev->sdev_classdev.dev = &sdev->sdev_driverfs_dev;
+	sdev->sdev_classdev.dev = &sdev->sdev_gendev;
 	sdev->sdev_classdev.class = &sdev_class;
 	snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE, "%d:%d:%d:%d",
 		sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
 
-	error = device_add(&sdev->sdev_driverfs_dev);
+	error = device_add(&sdev->sdev_gendev);
 	if (error) {
 		printk(KERN_INFO "error 1\n");
 		return error;
@@ -260,16 +296,28 @@
 	error = class_device_add(&sdev->sdev_classdev);
 	if (error) {
 		printk(KERN_INFO "error 2\n");
-		device_unregister(&sdev->sdev_driverfs_dev);
+		device_unregister(&sdev->sdev_gendev);
 		return error;
 	}
 
-	for (i = 0; !error && sdev->host->hostt->sdev_attrs[i] != NULL; i++)
-		error = device_create_file(&sdev->sdev_driverfs_dev,
-					   sdev->host->hostt->sdev_attrs[i]);
-
-	if (error)
-		scsi_device_unregister(sdev);
+	if (sdev->host->hostt->sdev_attrs) {
+		for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) {
+			error = attr_add(&sdev->sdev_gendev,
+					sdev->host->hostt->sdev_attrs[i]);
+			if (error)
+				scsi_device_unregister(sdev);
+		}
+	}
+	
+	for (i = 0; scsi_sysfs_sdev_attrs[i]; i++) {
+		if (!attr_overridden(sdev->host->hostt->sdev_attrs,
+					scsi_sysfs_sdev_attrs[i])) {
+			error = device_create_file(&sdev->sdev_gendev,
+					scsi_sysfs_sdev_attrs[i]);
+			if (error)
+				scsi_device_unregister(sdev);
+		}
+	}
 
 	return error;
 }
@@ -280,12 +328,8 @@
  **/
 void scsi_device_unregister(struct scsi_device *sdev)
 {
-	int i;
-
-	for (i = 0; sdev->host->hostt->sdev_attrs[i] != NULL; i++)
-		device_remove_file(&sdev->sdev_driverfs_dev, sdev->host->hostt->sdev_attrs[i]);
 	class_device_unregister(&sdev->sdev_classdev);
-	device_unregister(&sdev->sdev_driverfs_dev);
+	device_unregister(&sdev->sdev_gendev);
 }
 
 int scsi_register_driver(struct device_driver *drv)
@@ -315,20 +359,57 @@
 
 void scsi_sysfs_init_host(struct Scsi_Host *shost)
 {
-	device_initialize(&shost->host_gendev);
-	snprintf(shost->host_gendev.bus_id, BUS_ID_SIZE, "host%d",
+	device_initialize(&shost->shost_gendev);
+	snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d",
 		shost->host_no);
-	snprintf(shost->host_gendev.name, DEVICE_NAME_SIZE, "%s",
+	snprintf(shost->shost_gendev.name, DEVICE_NAME_SIZE, "%s",
 		shost->hostt->proc_name);
-	shost->host_gendev.release = scsi_host_release;
+	shost->shost_gendev.release = scsi_host_release;
 
-	class_device_initialize(&shost->class_dev);
-	shost->class_dev.dev = &shost->host_gendev;
-	shost->class_dev.class = &shost_class;
-	snprintf(shost->class_dev.class_id, BUS_ID_SIZE, "host%d",
+	class_device_initialize(&shost->shost_classdev);
+	shost->shost_classdev.dev = &shost->shost_gendev;
+	shost->shost_classdev.class = &shost_class;
+	snprintf(shost->shost_classdev.class_id, BUS_ID_SIZE, "host%d",
 		  shost->host_no);
 }
 
+static struct class_device_attribute *class_attr_overridden(
+		struct class_device_attribute **attrs,
+		struct class_device_attribute *attr)
+{
+	int i;
+
+	if (!attrs)
+		return NULL;
+	for (i = 0; attrs[i]; i++)
+		if (!strcmp(attrs[i]->attr.name, attr->attr.name))
+			return attrs[i];
+	return NULL;
+}
+
+static int class_attr_add(struct class_device *classdev,
+		struct class_device_attribute *attr)
+{
+	struct class_device_attribute *base_attr;
+
+	/*
+	 * Spare the caller from having to copy things it's not interested in.
+	 */
+	base_attr = class_attr_overridden(scsi_sysfs_shost_attrs, attr);
+	if (base_attr) {
+		/* extend permissions */
+		attr->attr.mode |= base_attr->attr.mode;
+
+		/* override null show/store with default */
+		if (!attr->show)
+			attr->show = base_attr->show;
+		if (!attr->store)
+			attr->store = base_attr->store;
+	}
+
+	return class_device_create_file(classdev, attr);
+}
+
 /**
  * scsi_sysfs_add_host - add scsi host to subsystem
  * @shost:     scsi host struct to add to subsystem
@@ -336,31 +417,44 @@
  **/
 int scsi_sysfs_add_host(struct Scsi_Host *shost, struct device *dev)
 {
-	int i, error;
+	int error, i;
 
-	if (!shost->host_gendev.parent)
-		shost->host_gendev.parent = dev ? dev : &legacy_bus;
+	if (!shost->shost_gendev.parent)
+		shost->shost_gendev.parent = dev ? dev : &legacy_bus;
 
-	error = device_add(&shost->host_gendev);
+	error = device_add(&shost->shost_gendev);
 	if (error)
 		return error;
 
-	error = class_device_add(&shost->class_dev);
+	error = class_device_add(&shost->shost_classdev);
 	if (error)
 		goto clean_device;
 
-	for (i = 0; !error && shost->hostt->shost_attrs[i] != NULL; i++)
-		error = class_device_create_file(&shost->class_dev,
-					   shost->hostt->shost_attrs[i]);
-	if (error)
-		goto clean_class;
+	if (shost->hostt->shost_attrs) {
+		for (i = 0; shost->hostt->shost_attrs[i]; i++) {
+			error = class_attr_add(&shost->shost_classdev,
+					shost->hostt->shost_attrs[i]);
+			if (error)
+				goto clean_class;
+		}
+	}
+
+	for (i = 0; scsi_sysfs_shost_attrs[i]; i++) {
+		if (!class_attr_overridden(shost->hostt->shost_attrs,
+					scsi_sysfs_shost_attrs[i])) {
+			error = class_device_create_file(&shost->shost_classdev,
+					scsi_sysfs_shost_attrs[i]);
+			if (error)
+				goto clean_class;
+		}
+	}
 
 	return error;
 
 clean_class:
-	class_device_del(&shost->class_dev);
+	class_device_del(&shost->shost_classdev);
 clean_device:
-	device_del(&shost->host_gendev);
+	device_del(&shost->shost_gendev);
 
 	return error;
 }
@@ -371,133 +465,6 @@
  **/
 void scsi_sysfs_remove_host(struct Scsi_Host *shost)
 {
-	class_device_del(&shost->class_dev);
-	device_del(&shost->host_gendev);
-}
-
-/** scsi_sysfs_modify_shost_attribute - modify or add a host class attribute
- *
- * @class_attrs:host class attribute list to be added to or modified
- * @attr:	individual attribute to change or added
- *
- * returns zero if successful or error if not
- **/
-int scsi_sysfs_modify_shost_attribute(
-			struct class_device_attribute ***class_attrs,
-			struct class_device_attribute *attr)
-{
-	int modify = -1;
-	int num_attrs;
-
-	if(*class_attrs == NULL)
-		*class_attrs = scsi_sysfs_shost_attrs;
-
-	for(num_attrs=0; (*class_attrs)[num_attrs] != NULL; num_attrs++)
-		if(strcmp((*class_attrs)[num_attrs]->attr.name,
-				attr->attr.name) == 0)
-			modify = num_attrs;
-
-	if(*class_attrs == scsi_sysfs_shost_attrs || modify < 0) {
-		/* note: need space for null at the end as well */
-		struct class_device_attribute **tmp_attrs =
-				kmalloc(sizeof(*tmp_attrs) *
-					  (num_attrs + (modify >= 0 ? 1 : 2)),
-					GFP_KERNEL);
-		if(tmp_attrs == NULL)
-			return -ENOMEM;
-		memcpy(tmp_attrs, *class_attrs, sizeof(*tmp_attrs) *
-				(num_attrs + 1));
-		if(*class_attrs != scsi_sysfs_shost_attrs)
-			kfree(*class_attrs);
-		*class_attrs = tmp_attrs;
-	}
-	if(modify >= 0) {
-		/* spare the caller from having to copy things it's
-		 * not interested in */
-		struct class_device_attribute *old_attr =
-			(*class_attrs)[modify];
-		/* extend permissions */
-		attr->attr.mode |= old_attr->attr.mode;
-
-		/* override null show/store with default */
-		if(attr->show == NULL)
-			attr->show = old_attr->show;
-		if(attr->store == NULL)
-			attr->store = old_attr->store;
-		(*class_attrs)[modify] = attr;
-	} else {
-		(*class_attrs)[num_attrs++] = attr;
-		(*class_attrs)[num_attrs] = NULL;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(scsi_sysfs_modify_shost_attribute);
-
-/** scsi_sysfs_modify_sdev_attribute - modify or add a host device attribute
- *
- * @dev_attrs:	pointer to the attribute list to be added to or modified
- * @attr:	individual attribute to change or added
- *
- * returns zero if successful or error if not
- **/
-int scsi_sysfs_modify_sdev_attribute(struct device_attribute ***dev_attrs,
-				     struct device_attribute *attr)
-{
-	int modify = -1;
-	int num_attrs;
-
-	if(*dev_attrs == NULL)
-		*dev_attrs = scsi_sysfs_sdev_attrs;
-
-	for(num_attrs=0; (*dev_attrs)[num_attrs] != NULL; num_attrs++)
-		if(strcmp((*dev_attrs)[num_attrs]->attr.name,
-				attr->attr.name) == 0)
-			modify = num_attrs;
-
-	if(*dev_attrs == scsi_sysfs_sdev_attrs || modify < 0) {
-		/* note: need space for null at the end as well */
-		struct device_attribute **tmp_attrs =
-				kmalloc(sizeof(*tmp_attrs) *
-					  (num_attrs + (modify >= 0 ? 1 : 2)),
-					GFP_KERNEL);
-		if(tmp_attrs == NULL)
-			return -ENOMEM;
-		memcpy(tmp_attrs, *dev_attrs, sizeof(*tmp_attrs) *
-				(num_attrs + 1));
-		if(*dev_attrs != scsi_sysfs_sdev_attrs)
-			kfree(*dev_attrs);
-		*dev_attrs = tmp_attrs;
-	}
-	if(modify >= 0) {
-		/* spare the caller from having to copy things it's
-		 * not interested in */
-		struct device_attribute *old_attr =
-			(*dev_attrs)[modify];
-		/* extend permissions */
-		attr->attr.mode |= old_attr->attr.mode;
-
-		/* override null show/store with default */
-		if(attr->show == NULL)
-			attr->show = old_attr->show;
-		if(attr->store == NULL)
-			attr->store = old_attr->store;
-		(*dev_attrs)[modify] = attr;
-	} else {
-		(*dev_attrs)[num_attrs++] = attr;
-		(*dev_attrs)[num_attrs] = NULL;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(scsi_sysfs_modify_sdev_attribute);
-
-void scsi_sysfs_release_attributes(struct scsi_host_template *hostt)
-{
-	if(hostt->sdev_attrs != scsi_sysfs_sdev_attrs)
-		kfree(hostt->sdev_attrs);
-
-	if(hostt->shost_attrs != scsi_sysfs_shost_attrs)
-		kfree(hostt->shost_attrs);
+	class_device_del(&shost->shost_classdev);
+	device_del(&shost->shost_gendev);
 }
-EXPORT_SYMBOL(scsi_sysfs_release_attributes);
diff -Nru a/drivers/scsi/scsicam.c b/drivers/scsi/scsicam.c
--- a/drivers/scsi/scsicam.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/scsicam.c	Sat Jul 19 12:54:25 2003
@@ -15,7 +15,7 @@
 #include <linux/fs.h>
 #include <linux/genhd.h>
 #include <linux/kernel.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/buffer_head.h>
 #include <asm/unaligned.h>
 #include "scsi.h"
diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c
--- a/drivers/scsi/sd.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/sd.c	Sat Jul 19 12:54:26 2003
@@ -43,7 +43,7 @@
 #include <linux/init.h>
 #include <linux/reboot.h>
 #include <linux/vmalloc.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <asm/uaccess.h>
 
@@ -606,35 +606,8 @@
 
 static void sd_rescan(struct device *dev)
 {
-	struct scsi_device *sdp = to_scsi_device(dev);
 	struct scsi_disk *sdkp = dev_get_drvdata(dev);
-	struct gendisk *gd;
-	struct scsi_request *SRpnt;
-	unsigned char *buffer;
-
-	if (!sdkp || sdp->online == FALSE || !sdkp->media_present)
-		return;
-		
-	gd = sdkp->disk;
-	
-	SCSI_LOG_HLQUEUE(3, printk("sd_rescan: disk=%s\n", gd->disk_name));
-	
-	SRpnt = scsi_allocate_request(sdp);
-	if (!SRpnt) {
-		printk(KERN_WARNING "(sd_rescan:) Request allocation "
-		       "failure.\n");
-		return;
-	}
-
-	if (sdkp->device->host->unchecked_isa_dma)
-		buffer = kmalloc(512, GFP_DMA);
-	else
-		buffer = kmalloc(512, GFP_KERNEL);
-
-    	sd_read_capacity(sdkp, gd->disk_name, SRpnt, buffer);
-	set_capacity(gd, sdkp->capacity);	
-	scsi_release_request(SRpnt);
-	kfree(buffer);
+	sd_revalidate_disk(sdkp->disk);
 }
 
 static struct block_device_operations sd_fops = {
@@ -1318,7 +1291,7 @@
 
 	sd_revalidate_disk(gd);
 
-	gd->driverfs_dev = &sdp->sdev_driverfs_dev;
+	gd->driverfs_dev = &sdp->sdev_gendev;
 	gd->flags = GENHD_FL_DRIVERFS;
 	if (sdp->removable)
 		gd->flags |= GENHD_FL_REMOVABLE;
diff -Nru a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c
--- a/drivers/scsi/seagate.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/seagate.c	Sat Jul 19 12:54:24 2003
@@ -95,7 +95,7 @@
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/stat.h>
 
 #include <asm/io.h>
diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c
--- a/drivers/scsi/sg.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/sg.c	Sat Jul 19 12:54:25 2003
@@ -61,7 +61,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include "scsi.h"
 #include "hosts.h"
 #include <scsi/scsi_driver.h>
diff -Nru a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
--- a/drivers/scsi/sgiwd93.c	Sat Jul 19 12:54:29 2003
+++ b/drivers/scsi/sgiwd93.c	Sat Jul 19 12:54:29 2003
@@ -15,7 +15,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/mm.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/version.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
diff -Nru a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c
--- a/drivers/scsi/sim710.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/scsi/sim710.c	Sat Jul 19 12:54:27 2003
@@ -29,7 +29,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/mca.h>
@@ -138,7 +138,8 @@
 		goto out_unregister;
 	}
 
-	scsi_add_host(host, dev);
+	scsi_add_host(host, dev); /* XXX handle failure */
+	scsi_scan_host(host);
 	hostdata->dev = dev;
 
 	return 0;
diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c
--- a/drivers/scsi/sr.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/scsi/sr.c	Sat Jul 19 12:54:23 2003
@@ -43,7 +43,7 @@
 #include <linux/cdrom.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <asm/uaccess.h>
 
 #include "scsi.h"
@@ -533,7 +533,7 @@
 
 	snprintf(disk->devfs_name, sizeof(disk->devfs_name),
 			"%s/cd", sdev->devfs_name);
-	disk->driverfs_dev = &sdev->sdev_driverfs_dev;
+	disk->driverfs_dev = &sdev->sdev_gendev;
 	register_cdrom(&cd->cdi);
 	set_capacity(disk, cd->capacity);
 	disk->private_data = &cd->driver;
diff -Nru a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
--- a/drivers/scsi/sr_ioctl.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/sr_ioctl.c	Sat Jul 19 12:54:26 2003
@@ -4,7 +4,7 @@
 #include <linux/fs.h>
 #include <linux/errno.h>
 #include <linux/string.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <linux/cdrom.h>
 #include <asm/io.h>
diff -Nru a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c
--- a/drivers/scsi/sr_vendor.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/sr_vendor.c	Sat Jul 19 12:54:25 2003
@@ -39,7 +39,7 @@
 #include <linux/string.h>
 #include <linux/bcd.h>
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include "scsi.h"
 #include "hosts.h"
 #include <scsi/scsi_ioctl.h>
diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c
--- a/drivers/scsi/st.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/st.c	Sat Jul 19 12:54:26 2003
@@ -32,7 +32,7 @@
 #include <linux/ioctl.h>
 #include <linux/fcntl.h>
 #include <linux/spinlock.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/moduleparam.h>
 #include <linux/devfs_fs_kernel.h>
 #include <asm/uaccess.h>
diff -Nru a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c
--- a/drivers/scsi/sun3_scsi.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/scsi/sun3_scsi.c	Sat Jul 19 12:54:22 2003
@@ -61,7 +61,7 @@
 #include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
diff -Nru a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c
--- a/drivers/scsi/sun3_scsi_vme.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/scsi/sun3_scsi_vme.c	Sat Jul 19 12:54:30 2003
@@ -23,7 +23,7 @@
 #include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
diff -Nru a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c
--- a/drivers/scsi/sun3x_esp.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/sun3x_esp.c	Sat Jul 19 12:54:26 2003
@@ -9,7 +9,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/delay.h>
diff -Nru a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c
--- a/drivers/scsi/sym53c416.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/scsi/sym53c416.c	Sat Jul 19 12:54:23 2003
@@ -40,7 +40,7 @@
 #include <asm/dma.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/version.h>
 #include <linux/isapnp.h>
 #include "scsi.h"
diff -Nru a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c
--- a/drivers/scsi/sym53c8xx.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/sym53c8xx.c	Sat Jul 19 12:54:26 2003
@@ -123,7 +123,7 @@
 #include <linux/timer.h>
 #include <linux/stat.h>
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,35)
 #include <linux/init.h>
@@ -1327,7 +1327,7 @@
 #define SetScsiAbortResult(cmd) SetScsiResult(cmd, DID_ABORT, 0xff)
 #endif
 
-static void sym53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t sym53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs);
 static void sym53c8xx_timeout(unsigned long np);
 
 #define initverbose (driver_setup.verbose)
@@ -7374,7 +7374,7 @@
 		}
 		if (cp->xerr_status & XE_BAD_PHASE) {
 			PRINT_ADDR(cmd);
-			printk ("illegal scsi phase (4/5).\n");
+			printk ("invalid scsi phase (4/5).\n");
 		}
 		if (cp->xerr_status & XE_SODL_UNRUN) {
 			PRINT_ADDR(cmd);
@@ -13660,7 +13660,7 @@
 **   routine for each host that uses this IRQ.
 */
 
-static void sym53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t sym53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs)
 {
      unsigned long flags;
      ncb_p np = (ncb_p) dev_id;
@@ -13685,6 +13685,7 @@
           ncr_flush_done_cmds(done_list);
           NCR_UNLOCK_SCSI_DONE(done_list->device->host, flags);
      }
+     return IRQ_HANDLED;
 }
 
 /*
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c	Sat Jul 19 12:54:30 2003
@@ -1110,6 +1110,7 @@
 	int sts = -1;
 	struct sym_eh_wait eh, *ep = &eh;
 	char devname[20];
+	unsigned long flags;
 
 	sprintf(devname, "%s:%d:%d", sym_name(np), cmd->device->id, cmd->device->lun);
 
@@ -1201,7 +1202,11 @@
 		ep->timer.data = (u_long)cmd;
 		ep->timed_out = 1;	/* Be pessimistic for once :) */
 		add_timer(&ep->timer);
+		local_save_flags(flags);
+		spin_unlock_irq(cmd->device->host->host_lock);
 		down(&ep->sem);
+		local_irq_restore(flags);
+		spin_lock(cmd->device->host->host_lock);
 		if (ep->timed_out)
 			sts = -2;
 	}
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h	Sat Jul 19 12:54:30 2003
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h	Sat Jul 19 12:54:30 2003
@@ -84,7 +84,7 @@
 #include <linux/stat.h>
 #include <linux/interrupt.h>
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 
 #ifdef __sparc__
 #  include <asm/irq.h>
diff -Nru a/drivers/scsi/t128.c b/drivers/scsi/t128.c
--- a/drivers/scsi/t128.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/scsi/t128.c	Sat Jul 19 12:54:27 2003
@@ -110,7 +110,7 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <asm/io.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/interrupt.h>
 #include <linux/stat.h>
 #include <linux/init.h>
diff -Nru a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
--- a/drivers/scsi/tmscsim.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/scsi/tmscsim.c	Sat Jul 19 12:54:30 2003
@@ -224,7 +224,7 @@
 #include <linux/mm.h>
 #include <linux/config.h>
 #include <linux/version.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/timer.h>
 
 #include "scsi.h"
diff -Nru a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
--- a/drivers/scsi/u14-34f.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/scsi/u14-34f.c	Sat Jul 19 12:54:24 2003
@@ -414,7 +414,7 @@
 #include <asm/system.h>
 #include <asm/byteorder.h>
 #include <linux/proc_fs.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/interrupt.h>
 #include <linux/stat.h>
 #include <linux/pci.h>
diff -Nru a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c
--- a/drivers/scsi/ultrastor.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/scsi/ultrastor.c	Sat Jul 19 12:54:25 2003
@@ -128,7 +128,7 @@
  */
 
 #include <linux/module.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/interrupt.h>
 #include <linux/stddef.h>
 #include <linux/string.h>
diff -Nru a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
--- a/drivers/scsi/wd33c93.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/wd33c93.c	Sat Jul 19 12:54:26 2003
@@ -79,7 +79,7 @@
 #include <linux/delay.h>
 #include <linux/version.h>
 #include <linux/init.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <asm/irq.h>
 
 #include "scsi.h"
diff -Nru a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
--- a/drivers/scsi/wd7000.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/scsi/wd7000.c	Sat Jul 19 12:54:30 2003
@@ -174,7 +174,7 @@
 #include <linux/spinlock.h>
 #include <linux/ioport.h>
 #include <linux/proc_fs.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/init.h>
 #include <linux/stat.h>
 
diff -Nru a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
--- a/drivers/scsi/zalon.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/scsi/zalon.c	Sat Jul 19 12:54:26 2003
@@ -7,7 +7,7 @@
 #include <linux/types.h>
 #include <linux/stat.h>
 #include <linux/mm.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/sched.h>
 #include <linux/version.h>
 #include <linux/config.h>
@@ -85,7 +85,7 @@
 {
 	struct gsc_irq gsc_irq;
 	u32 zalon_vers;
-	int irq;
+	int irq, error = -ENODEV;
 	unsigned long zalon = dev->hpa;
 	unsigned long io_port = zalon + GSC_SCSI_ZALON_OFFSET;
 	static int unit = 0;
@@ -147,11 +147,18 @@
 
 	dev_set_drvdata(&dev->dev, host);
 
-	scsi_add_host(host, &dev->dev);
+	error = scsi_add_host(host, &dev->dev);
+	if (error)
+		goto fail_free_irq;
 
+	scsi_scan_host(host);
 	return 0;
+
+ fail_free_irq:
+	free_irq(irq, host);
  fail:
-	return -ENODEV;
+	ncr53c8xx_release(host);
+	return error;
 }
 
 static struct parisc_device_id zalon_tbl[] = {
diff -Nru a/drivers/serial/Kconfig b/drivers/serial/Kconfig
--- a/drivers/serial/Kconfig	Sat Jul 19 12:54:28 2003
+++ b/drivers/serial/Kconfig	Sat Jul 19 12:54:28 2003
@@ -404,14 +404,19 @@
 	  on your Sparc system as the console, you can do so by answering
 	  Y to this option.
 
-config V850E_NB85E_UART
+config V850E_UART
 	bool "NEC V850E on-chip UART support"
-	depends on V850E_NB85E || V850E2_ANNA || V850E_AS85EP1
+	depends on V850E_MA1 || V850E_ME2 || V850E_TEG || V850E2_ANNA || V850E_AS85EP1
 	default y
 
-config V850E_NB85E_UART_CONSOLE
+config V850E_UARTB
+        bool
+	depends V850E_UART && V850E_ME2
+	default y
+
+config V850E_UART_CONSOLE
 	bool "Use NEC V850E on-chip UART for console"
-	depends on V850E_NB85E_UART
+	depends on V850E_UART
 
 config SERIAL98
 	tristate "PC-9800 8251-based primary serial port support"
@@ -426,12 +431,12 @@
 
 config SERIAL_CORE
 	tristate
-	default m if SERIAL_AMBA!=y && SERIAL_CLPS711X!=y && SERIAL_21285!=y && !SERIAL_SA1100 && !SERIAL_ANAKIN && !SERIAL_UART00 && SERIAL_8250!=y && SERIAL_MUX!=y && !SERIAL_ROCKETPORT && !SERIAL_SUNCORE && !V850E_NB85E_UART && (SERIAL_AMBA=m || SERIAL_CLPS711X=m || SERIAL_21285=m || SERIAL_8250=m || SERIAL_MUX=m || SERIAL98=m)
-	default y if SERIAL_AMBA=y || SERIAL_CLPS711X=y || SERIAL_21285=y || SERIAL_SA1100 || SERIAL_ANAKIN || SERIAL_UART00 || SERIAL_8250=y || SERIAL_MUX=y || SERIAL_ROCKETPORT || SERIAL_SUNCORE || V850E_NB85E_UART || SERIAL98=y
+	default m if SERIAL_AMBA!=y && SERIAL_CLPS711X!=y && SERIAL_21285!=y && !SERIAL_SA1100 && !SERIAL_ANAKIN && !SERIAL_UART00 && SERIAL_8250!=y && SERIAL_MUX!=y && !SERIAL_ROCKETPORT && !SERIAL_SUNCORE && !V850E_UART && (SERIAL_AMBA=m || SERIAL_CLPS711X=m || SERIAL_21285=m || SERIAL_8250=m || SERIAL_MUX=m || SERIAL98=m)
+	default y if SERIAL_AMBA=y || SERIAL_CLPS711X=y || SERIAL_21285=y || SERIAL_SA1100 || SERIAL_ANAKIN || SERIAL_UART00 || SERIAL_8250=y || SERIAL_MUX=y || SERIAL_ROCKETPORT || SERIAL_SUNCORE || V850E_UART || SERIAL98=y
 
 config SERIAL_CORE_CONSOLE
 	bool
-	depends on SERIAL_AMBA_CONSOLE || SERIAL_CLPS711X_CONSOLE || SERIAL_21285_CONSOLE || SERIAL_SA1100_CONSOLE || SERIAL_ANAKIN_CONSOLE || SERIAL_UART00_CONSOLE || SERIAL_8250_CONSOLE || SERIAL_MUX_CONSOLE || SERIAL_SUNZILOG_CONSOLE || SERIAL_SUNSU_CONSOLE || SERIAL_SUNSAB_CONSOLE || V850E_NB85E_UART_CONSOLE || SERIAL98_CONSOLE
+	depends on SERIAL_AMBA_CONSOLE || SERIAL_CLPS711X_CONSOLE || SERIAL_21285_CONSOLE || SERIAL_SA1100_CONSOLE || SERIAL_ANAKIN_CONSOLE || SERIAL_UART00_CONSOLE || SERIAL_8250_CONSOLE || SERIAL_MUX_CONSOLE || SERIAL_SUNZILOG_CONSOLE || SERIAL_SUNSU_CONSOLE || SERIAL_SUNSAB_CONSOLE || V850E_UART_CONSOLE || SERIAL98_CONSOLE
 	default y
 
 config SERIAL_68328
diff -Nru a/drivers/serial/Makefile b/drivers/serial/Makefile
--- a/drivers/serial/Makefile	Sat Jul 19 12:54:25 2003
+++ b/drivers/serial/Makefile	Sat Jul 19 12:54:25 2003
@@ -29,5 +29,5 @@
 obj-$(CONFIG_SERIAL_68328) += 68328serial.o
 obj-$(CONFIG_SERIAL_68360) += 68360serial.o
 obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o
-obj-$(CONFIG_V850E_NB85E_UART) += nb85e_uart.o
+obj-$(CONFIG_V850E_UART) += v850e_uart.o
 obj-$(CONFIG_SERIAL98) += serial98.o
diff -Nru a/drivers/serial/core.c b/drivers/serial/core.c
--- a/drivers/serial/core.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/serial/core.c	Sat Jul 19 12:54:23 2003
@@ -1667,23 +1667,25 @@
 		return ret + 1;
 	}
 
-	status = port->ops->get_mctrl(port);
-
-	ret += sprintf(buf + ret, " tx:%d rx:%d",
-			port->icount.tx, port->icount.rx);
-	if (port->icount.frame)
-		ret += sprintf(buf + ret, " fe:%d",
-			port->icount.frame);
-	if (port->icount.parity)
-		ret += sprintf(buf + ret, " pe:%d",
-			port->icount.parity);
-	if (port->icount.brk)
-		ret += sprintf(buf + ret, " brk:%d",
-			port->icount.brk);
-	if (port->icount.overrun)
-		ret += sprintf(buf + ret, " oe:%d",
-			port->icount.overrun);
+	if(capable(CAP_SYS_ADMIN))
+	{
+		status = port->ops->get_mctrl(port);
 
+		ret += sprintf(buf + ret, " tx:%d rx:%d",
+				port->icount.tx, port->icount.rx);
+		if (port->icount.frame)
+			ret += sprintf(buf + ret, " fe:%d",
+				port->icount.frame);
+		if (port->icount.parity)
+			ret += sprintf(buf + ret, " pe:%d",
+				port->icount.parity);
+		if (port->icount.brk)
+			ret += sprintf(buf + ret, " brk:%d",
+				port->icount.brk);
+		if (port->icount.overrun)
+			ret += sprintf(buf + ret, " oe:%d",
+				port->icount.overrun);
+	
 #define INFOBIT(bit,str) \
 	if (port->mctrl & (bit)) \
 		strncat(stat_buf, (str), sizeof(stat_buf) - \
@@ -1693,19 +1695,22 @@
 		strncat(stat_buf, (str), sizeof(stat_buf) - \
 		       strlen(stat_buf) - 2)
 
-	stat_buf[0] = '\0';
-	stat_buf[1] = '\0';
-	INFOBIT(TIOCM_RTS, "|RTS");
-	STATBIT(TIOCM_CTS, "|CTS");
-	INFOBIT(TIOCM_DTR, "|DTR");
-	STATBIT(TIOCM_DSR, "|DSR");
-	STATBIT(TIOCM_CAR, "|CD");
-	STATBIT(TIOCM_RNG, "|RI");
-	if (stat_buf[0])
-		stat_buf[0] = ' ';
-	strcat(stat_buf, "\n");
-
-	ret += sprintf(buf + ret, stat_buf);
+		stat_buf[0] = '\0';
+		stat_buf[1] = '\0';
+		INFOBIT(TIOCM_RTS, "|RTS");
+		STATBIT(TIOCM_CTS, "|CTS");
+		INFOBIT(TIOCM_DTR, "|DTR");
+		STATBIT(TIOCM_DSR, "|DSR");
+		STATBIT(TIOCM_CAR, "|CD");
+		STATBIT(TIOCM_RNG, "|RI");
+		if (stat_buf[0])
+			stat_buf[0] = ' ';
+		strcat(stat_buf, "\n");
+	
+		ret += sprintf(buf + ret, stat_buf);
+	}
+#undef STATBIT
+#undef INFOBIT
 	return ret;
 }
 
diff -Nru a/drivers/serial/nb85e_uart.c b/drivers/serial/nb85e_uart.c
--- a/drivers/serial/nb85e_uart.c	Sat Jul 19 12:54:27 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,610 +0,0 @@
-/*
- * drivers/serial/nb85e_uart.c -- Serial I/O using V850E/NB85E on-chip UART
- *
- *  Copyright (C) 2001,02,03  NEC Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/console.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-
-#include <asm/nb85e_uart.h>
-#include <asm/nb85e_utils.h>
-
-/* Initial UART state.  This may be overridden by machine-dependent headers. */
-#ifndef NB85E_UART_INIT_BAUD
-#define NB85E_UART_INIT_BAUD	115200
-#endif
-#ifndef NB85E_UART_INIT_CFLAGS
-#define NB85E_UART_INIT_CFLAGS	(B115200 | CS8 | CREAD)
-#endif
-
-/* XXX This should be in a header file.  */
-#define NB85E_UART_BRGC_MIN	8
-
-/* A string used for prefixing printed descriptions; since the same UART
-   macro is actually used on other chips than the V850E/NB85E.  This must
-   be a constant string.  */
-#ifndef NB85E_UART_CHIP_NAME
-#define NB85E_UART_CHIP_NAME "V850E/NB85E"
-#endif
-
-
-/* Helper functions for doing baud-rate/frequency calculations.  */
-
-/* Calculate the minimum value for CKSR on this processor.  */
-static inline unsigned cksr_min (void)
-{
-	int min = 0;
-	unsigned freq = NB85E_UART_BASE_FREQ;
-	while (freq > NB85E_UART_CKSR_MAX_FREQ) {
-		freq >>= 1;
-		min++;
-	}
-	return min;
-}
-
-/* Minimum baud rate possible.  */
-#define min_baud() \
-   ((NB85E_UART_BASE_FREQ >> NB85E_UART_CKSR_MAX) / (2 * 255) + 1)
-
-/* Maximum baud rate possible.  The error is quite high at max, though.  */
-#define max_baud() \
-   ((NB85E_UART_BASE_FREQ >> cksr_min()) / (2 * NB85E_UART_BRGC_MIN))
-
-
-/* Low-level UART functions.  */
-
-/* These masks define which control bits affect TX/RX modes, respectively.  */
-#define RX_BITS \
-  (NB85E_UART_ASIM_PS_MASK | NB85E_UART_ASIM_CL_8 | NB85E_UART_ASIM_ISRM)
-#define TX_BITS \
-  (NB85E_UART_ASIM_PS_MASK | NB85E_UART_ASIM_CL_8 | NB85E_UART_ASIM_SL_2)
-
-/* The UART require various delays after writing control registers.  */
-static inline void nb85e_uart_delay (unsigned cycles)
-{
-	/* The loop takes 2 insns, so loop CYCLES / 2 times.  */
-	register unsigned count = cycles >> 1;
-	while (--count != 0)
-		/* nothing */;
-}
-
-/* Configure and turn on uart channel CHAN, using the termios `control
-   modes' bits in CFLAGS, and a baud-rate of BAUD.  */
-void nb85e_uart_configure (unsigned chan, unsigned cflags, unsigned baud)
-{
-	int flags;
-	unsigned new_config = 0; /* What we'll write to the control reg. */
-	unsigned new_clk_divlog2; /* New baud-rate generate clock divider. */
-	unsigned new_brgen_count; /* New counter max for baud-rate generator.*/
-	/* These are the current values corresponding to the above.  */
-	unsigned old_config, old_clk_divlog2, old_brgen_count;
-
-	/* Calculate new baud-rate generator config values.  */
-
-	/* Calculate the log2 clock divider and baud-rate counter values
-	   (note that the UART divides the resulting clock by 2, so
-	   multiply BAUD by 2 here to compensate).  */
-	calc_counter_params (NB85E_UART_BASE_FREQ, baud * 2,
-			     cksr_min(), NB85E_UART_CKSR_MAX, 8/*bits*/,
-			     &new_clk_divlog2, &new_brgen_count);
-
-	/* Figure out new configuration of control register.  */
-	if (cflags & CSTOPB)
-		/* Number of stop bits, 1 or 2.  */
-		new_config |= NB85E_UART_ASIM_SL_2;
-	if ((cflags & CSIZE) == CS8)
-		/* Number of data bits, 7 or 8.  */
-		new_config |= NB85E_UART_ASIM_CL_8;
-	if (! (cflags & PARENB))
-		/* No parity check/generation.  */
-		new_config |= NB85E_UART_ASIM_PS_NONE;
-	else if (cflags & PARODD)
-		/* Odd parity check/generation.  */
-		new_config |= NB85E_UART_ASIM_PS_ODD;
-	else
-		/* Even parity check/generation.  */
-		new_config |= NB85E_UART_ASIM_PS_EVEN;
-	if (cflags & CREAD)
-		/* Reading enabled.  */
-		new_config |= NB85E_UART_ASIM_RXE;
-
-	new_config |= NB85E_UART_ASIM_TXE; /* Writing is always enabled.  */
-	new_config |= NB85E_UART_ASIM_CAE;
-	new_config |= NB85E_UART_ASIM_ISRM; /* Errors generate a read-irq.  */
-
-	/* Disable interrupts while we're twiddling the hardware.  */
-	local_irq_save (flags);
-
-#ifdef NB85E_UART_PRE_CONFIGURE
-	NB85E_UART_PRE_CONFIGURE (chan, cflags, baud);
-#endif
-
-	old_config = NB85E_UART_ASIM (chan);
-	old_clk_divlog2 = NB85E_UART_CKSR (chan);
-	old_brgen_count = NB85E_UART_BRGC (chan);
-
-	if (new_clk_divlog2 != old_clk_divlog2
-	    || new_brgen_count != old_brgen_count)
-	{
-		/* The baud rate has changed.  First, disable the UART.  */
-		NB85E_UART_ASIM (chan) = 0;
-		old_config = 0;
-		/* Reprogram the baud-rate generator.  */
-		NB85E_UART_CKSR (chan) = new_clk_divlog2;
-		NB85E_UART_BRGC (chan) = new_brgen_count;
-	}
-
-	if (! (old_config & NB85E_UART_ASIM_CAE)) {
-		/* If we are enabling the uart for the first time, start
-		   by turning on the enable bit, which must be done
-		   before turning on any other bits.  */
-		NB85E_UART_ASIM (chan) = NB85E_UART_ASIM_CAE;
-		/* Enabling the uart also resets it.  */
-		old_config = NB85E_UART_ASIM_CAE;
-	}
-
-	if (new_config != old_config) {
-		/* Which of the TXE/RXE bits we'll temporarily turn off
-		   before changing other control bits.  */
-		unsigned temp_disable = 0;
-		/* Which of the TXE/RXE bits will be enabled.  */
-		unsigned enable = 0;
-		unsigned changed_bits = new_config ^ old_config;
-
-		/* Which of RX/TX will be enabled in the new configuration.  */
-		if (new_config & RX_BITS)
-			enable |= (new_config & NB85E_UART_ASIM_RXE);
-		if (new_config & TX_BITS)
-			enable |= (new_config & NB85E_UART_ASIM_TXE);
-
-		/* Figure out which of RX/TX needs to be disabled; note
-		   that this will only happen if they're not already
-		   disabled.  */
-		if (changed_bits & RX_BITS)
-			temp_disable |= (old_config & NB85E_UART_ASIM_RXE);
-		if (changed_bits & TX_BITS)
-			temp_disable |= (old_config & NB85E_UART_ASIM_TXE);
-
-		/* We have to turn off RX and/or TX mode before changing
-		   any associated control bits.  */
-		if (temp_disable)
-			NB85E_UART_ASIM (chan) = old_config & ~temp_disable;
-
-		/* Write the new control bits, while RX/TX are disabled. */ 
-		if (changed_bits & ~enable)
-			NB85E_UART_ASIM (chan) = new_config & ~enable;
-
-		/* The UART may not be reset properly unless we
-		   wait at least 2 `basic-clocks' until turning
-		   on the TXE/RXE bits again.  A `basic clock'
-		   is the clock used by the baud-rate generator, i.e.,
-		   the cpu clock divided by the 2^new_clk_divlog2.  */
-		nb85e_uart_delay (1 << (new_clk_divlog2 + 1));
-
-		/* Write the final version, with enable bits turned on.  */
-		NB85E_UART_ASIM (chan) = new_config;
-	}
-
-	local_irq_restore (flags);
-}
-
-
-/*  Low-level console. */
-
-#ifdef CONFIG_V850E_NB85E_UART_CONSOLE
-
-static void nb85e_uart_cons_write (struct console *co,
-				   const char *s, unsigned count)
-{
-	if (count > 0) {
-		unsigned chan = co->index;
-		unsigned irq = IRQ_INTST (chan);
-		int irq_was_enabled, irq_was_pending, flags;
-
-		/* We don't want to get `transmission completed' (INTST)
-		   interrupts, since we're busy-waiting, so we disable
-		   them while sending (we don't disable interrupts
-		   entirely because sending over a serial line is really
-		   slow).  We save the status of INTST and restore it
-		   when we're done so that using printk doesn't
-		   interfere with normal serial transmission (other than
-		   interleaving the output, of course!).  This should
-		   work correctly even if this function is interrupted
-		   and the interrupt printks something.  */
-
-		/* Disable interrupts while fiddling with INTST.  */
-		local_irq_save (flags);
-		/* Get current INTST status.  */
-		irq_was_enabled = nb85e_intc_irq_enabled (irq);
-		irq_was_pending = nb85e_intc_irq_pending (irq);
-		/* Disable INTST if necessary.  */
-		if (irq_was_enabled)
-			nb85e_intc_disable_irq (irq);
-		/* Turn interrupts back on.  */
-		local_irq_restore (flags);
-
-		/* Send characters.  */
-		while (count > 0) {
-			int ch = *s++;
-
-			if (ch == '\n') {
-				/* We don't have the benefit of a tty
-				   driver, so translate NL into CR LF.  */
-				nb85e_uart_wait_for_xmit_ok (chan);
-				nb85e_uart_putc (chan, '\r');
-			}
-
-			nb85e_uart_wait_for_xmit_ok (chan);
-			nb85e_uart_putc (chan, ch);
-
-			count--;
-		}
-
-		/* Restore saved INTST status.  */
-		if (irq_was_enabled) {
-			/* Wait for the last character we sent to be
-			   completely transmitted (as we'll get an INTST
-			   interrupt at that point).  */
-			nb85e_uart_wait_for_xmit_done (chan);
-			/* Clear pending interrupts received due
-			   to our transmission, unless there was already
-			   one pending, in which case we want the
-			   handler to be called.  */
-			if (! irq_was_pending)
-				nb85e_intc_clear_pending_irq (irq);
-			/* ... and then turn back on handling.  */
-			nb85e_intc_enable_irq (irq);
-		}
-	}
-}
-
-extern struct uart_driver nb85e_uart_driver;
-static struct console nb85e_uart_cons =
-{
-    .name	= "ttyS",
-    .write	= nb85e_uart_cons_write,
-    .device	= uart_console_device,
-    .flags	= CON_PRINTBUFFER,
-    .cflag	= NB85E_UART_INIT_CFLAGS,
-    .index	= -1,
-    .data	= &nb85e_uart_driver,
-};
-
-void nb85e_uart_cons_init (unsigned chan)
-{
-	nb85e_uart_configure (chan, NB85E_UART_INIT_CFLAGS,
-			      NB85E_UART_INIT_BAUD);
-	nb85e_uart_cons.index = chan;
-	register_console (&nb85e_uart_cons);
-	printk ("Console: %s on-chip UART channel %d\n",
-		NB85E_UART_CHIP_NAME, chan);
-}
-
-#define NB85E_UART_CONSOLE &nb85e_uart_cons
-
-#else /* !CONFIG_V850E_NB85E_UART_CONSOLE */
-#define NB85E_UART_CONSOLE 0
-#endif /* CONFIG_V850E_NB85E_UART_CONSOLE */
-
-/* TX/RX interrupt handlers.  */
-
-static void nb85e_uart_stop_tx (struct uart_port *port, unsigned tty_stop);
-
-void nb85e_uart_tx (struct uart_port *port)
-{
-	struct circ_buf *xmit = &port->info->xmit;
-	int stopped = uart_tx_stopped (port);
-
-	if (nb85e_uart_xmit_ok (port->line)) {
-		int tx_ch;
-
-		if (port->x_char) {
-			tx_ch = port->x_char;
-			port->x_char = 0;
-		} else if (!uart_circ_empty (xmit) && !stopped) {
-			tx_ch = xmit->buf[xmit->tail];
-			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		} else
-			goto no_xmit;
-
-		nb85e_uart_putc (port->line, tx_ch);
-		port->icount.tx++;
-
-		if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS)
-			uart_write_wakeup (port);
-	}
-
- no_xmit:
-	if (uart_circ_empty (xmit) || stopped)
-		nb85e_uart_stop_tx (port, stopped);
-}
-
-static void nb85e_uart_tx_irq (int irq, void *data, struct pt_regs *regs)
-{
-	struct uart_port *port = data;
-	nb85e_uart_tx (port);
-}
-
-static void nb85e_uart_rx_irq (int irq, void *data, struct pt_regs *regs)
-{
-	struct uart_port *port = data;
-	unsigned ch_stat = TTY_NORMAL;
-	unsigned ch = NB85E_UART_RXB (port->line);
-	unsigned err = NB85E_UART_ASIS (port->line);
-
-	if (err) {
-		if (err & NB85E_UART_ASIS_OVE) {
-			ch_stat = TTY_OVERRUN;
-			port->icount.overrun++;
-		} else if (err & NB85E_UART_ASIS_FE) {
-			ch_stat = TTY_FRAME;
-			port->icount.frame++;
-		} else if (err & NB85E_UART_ASIS_PE) {
-			ch_stat = TTY_PARITY;
-			port->icount.parity++;
-		}
-	}
-
-	port->icount.rx++;
-
-	tty_insert_flip_char (port->info->tty, ch, ch_stat);
-	tty_schedule_flip (port->info->tty);
-}
-
-/* Control functions for the serial framework.  */
-
-static void nb85e_uart_nop (struct uart_port *port) { }
-static int nb85e_uart_success (struct uart_port *port) { return 0; }
-
-static unsigned nb85e_uart_tx_empty (struct uart_port *port)
-{
-	return TIOCSER_TEMT;	/* Can't detect.  */
-}
-
-static void nb85e_uart_set_mctrl (struct uart_port *port, unsigned mctrl)
-{
-#ifdef NB85E_UART_SET_RTS
-	NB85E_UART_SET_RTS (port->line, (mctrl & TIOCM_RTS));
-#endif
-}
-
-static unsigned nb85e_uart_get_mctrl (struct uart_port *port)
-{
-	/* We don't support DCD or DSR, so consider them permanently active. */
-	int mctrl = TIOCM_CAR | TIOCM_DSR;
-
-	/* We may support CTS.  */
-#ifdef NB85E_UART_CTS
-	mctrl |= NB85E_UART_CTS(port->line) ? TIOCM_CTS : 0;
-#else
-	mctrl |= TIOCM_CTS;
-#endif
-
-	return mctrl;
-}
-
-static void nb85e_uart_start_tx (struct uart_port *port, unsigned tty_start)
-{
-	nb85e_intc_disable_irq (IRQ_INTST (port->line));
-	nb85e_uart_tx (port);
-	nb85e_intc_enable_irq (IRQ_INTST (port->line));
-}
-
-static void nb85e_uart_stop_tx (struct uart_port *port, unsigned tty_stop)
-{
-	nb85e_intc_disable_irq (IRQ_INTST (port->line));
-}
-
-static void nb85e_uart_start_rx (struct uart_port *port)
-{
-	nb85e_intc_enable_irq (IRQ_INTSR (port->line));
-}
-
-static void nb85e_uart_stop_rx (struct uart_port *port)
-{
-	nb85e_intc_disable_irq (IRQ_INTSR (port->line));
-}
-
-static void nb85e_uart_break_ctl (struct uart_port *port, int break_ctl)
-{
-	/* Umm, do this later.  */
-}
-
-static int nb85e_uart_startup (struct uart_port *port)
-{
-	int err;
-
-	/* Alloc RX irq.  */
-	err = request_irq (IRQ_INTSR (port->line), nb85e_uart_rx_irq,
-			   SA_INTERRUPT, "nb85e_uart", port);
-	if (err)
-		return err;
-
-	/* Alloc TX irq.  */
-	err = request_irq (IRQ_INTST (port->line), nb85e_uart_tx_irq,
-			   SA_INTERRUPT, "nb85e_uart", port);
-	if (err) {
-		free_irq (IRQ_INTSR (port->line), port);
-		return err;
-	}
-
-	nb85e_uart_start_rx (port);
-
-	return 0;
-}
-
-static void nb85e_uart_shutdown (struct uart_port *port)
-{
-	/* Disable port interrupts.  */
-	free_irq (IRQ_INTST (port->line), port);
-	free_irq (IRQ_INTSR (port->line), port);
-
-	/* Turn off xmit/recv enable bits.  */
-	NB85E_UART_ASIM (port->line)
-		&= ~(NB85E_UART_ASIM_TXE | NB85E_UART_ASIM_RXE);
-	/* Then reset the channel.  */
-	NB85E_UART_ASIM (port->line) = 0;
-}
-
-static void
-nb85e_uart_set_termios (struct uart_port *port, struct termios *termios,
-		        struct termios *old)
-{
-	unsigned cflags = termios->c_cflag;
-
-	/* Restrict flags to legal values.  */
-	if ((cflags & CSIZE) != CS7 && (cflags & CSIZE) != CS8)
-		/* The new value of CSIZE is invalid, use the old value.  */
-		cflags = (cflags & ~CSIZE)
-			| (old ? (old->c_cflag & CSIZE) : CS8);
-
-	termios->c_cflag = cflags;
-
-	nb85e_uart_configure (port->line, cflags,
-			      uart_get_baud_rate (port, termios, old,
-						  min_baud(), max_baud()));
-}
-
-static const char *nb85e_uart_type (struct uart_port *port)
-{
-	return port->type == PORT_NB85E_UART ? "nb85e_uart" : 0;
-}
-
-static void nb85e_uart_config_port (struct uart_port *port, int flags)
-{
-	if (flags & UART_CONFIG_TYPE)
-		port->type = PORT_NB85E_UART;
-}
-
-static int
-nb85e_uart_verify_port (struct uart_port *port, struct serial_struct *ser)
-{
-	if (ser->type != PORT_UNKNOWN && ser->type != PORT_NB85E_UART)
-		return -EINVAL;
-	if (ser->irq != IRQ_INTST (port->line))
-		return -EINVAL;
-	return 0;
-}
-
-static struct uart_ops nb85e_uart_ops = {
-	.tx_empty	= nb85e_uart_tx_empty,
-	.get_mctrl	= nb85e_uart_get_mctrl,
-	.set_mctrl	= nb85e_uart_set_mctrl,
-	.start_tx	= nb85e_uart_start_tx,
-	.stop_tx	= nb85e_uart_stop_tx,
-	.stop_rx	= nb85e_uart_stop_rx,
-	.enable_ms	= nb85e_uart_nop,
-	.break_ctl	= nb85e_uart_break_ctl,
-	.startup	= nb85e_uart_startup,
-	.shutdown	= nb85e_uart_shutdown,
-	.set_termios	= nb85e_uart_set_termios,
-	.type		= nb85e_uart_type,
-	.release_port	= nb85e_uart_nop,
-	.request_port	= nb85e_uart_success,
-	.config_port	= nb85e_uart_config_port,
-	.verify_port	= nb85e_uart_verify_port,
-};
-
-/* Initialization and cleanup.  */
-
-static struct uart_driver nb85e_uart_driver = {
-	.owner			= THIS_MODULE,
-	.driver_name		= "nb85e_uart",
-	.devfs_name		= "tts/",
-	.dev_name		= "ttyS",
-	.major			= TTY_MAJOR,
-	.minor			= NB85E_UART_MINOR_BASE,
-	.nr			= NB85E_UART_NUM_CHANNELS,
-	.cons			= NB85E_UART_CONSOLE,
-};
-
-
-static struct uart_port nb85e_uart_ports[NB85E_UART_NUM_CHANNELS];
-
-static int __init nb85e_uart_init (void)
-{
-	int rval;
-
-	printk (KERN_INFO "%s on-chip UART\n", NB85E_UART_CHIP_NAME);
-
-	rval = uart_register_driver (&nb85e_uart_driver);
-	if (rval == 0) {
-		unsigned chan;
-
-		for (chan = 0; chan < NB85E_UART_NUM_CHANNELS; chan++) {
-			struct uart_port *port = &nb85e_uart_ports[chan];
-			
-			memset (port, 0, sizeof *port);
-
-			port->ops = &nb85e_uart_ops;
-			port->line = chan;
-			port->iotype = SERIAL_IO_MEM;
-			port->flags = UPF_BOOT_AUTOCONF;
-
-			/* We actually use multiple IRQs, but the serial
-			   framework seems to mainly use this for
-			   informational purposes anyway.  Here we use the TX
-			   irq.  */
-			port->irq = IRQ_INTST (chan);
-
-			/* The serial framework doesn't really use these
-			   membase/mapbase fields for anything useful, but
-			   it requires that they be something non-zero to
-			   consider the port `valid', and also uses them
-			   for informational purposes.  */
-			port->membase = (void *)NB85E_UART_BASE_ADDR (chan);
-			port->mapbase = NB85E_UART_BASE_ADDR (chan);
-
-			/* The framework insists on knowing the uart's master
-			   clock freq, though it doesn't seem to do anything
-			   useful for us with it.  We must make it at least
-			   higher than (the maximum baud rate * 16), otherwise
-			   the framework will puke during its internal
-			   calculations, and force the baud rate to be 9600.
-			   To be accurate though, just repeat the calculation
-			   we use when actually setting the speed.
-
-			   The `* 8' means `* 16 / 2':  16 to account for for
-			   the serial framework's built-in bias, and 2 because
-			   there's an additional / 2 in the hardware.  */
-			port->uartclk =
-				(NB85E_UART_BASE_FREQ >> cksr_min()) * 8;
-
-			uart_add_one_port (&nb85e_uart_driver, port);
-		}
-	}
-
-	return rval;
-}
-
-static void __exit nb85e_uart_exit (void)
-{
-	unsigned chan;
-
-	for (chan = 0; chan < NB85E_UART_NUM_CHANNELS; chan++)
-		uart_remove_one_port (&nb85e_uart_driver,
-				      &nb85e_uart_ports[chan]);
-
-	uart_unregister_driver (&nb85e_uart_driver);
-}
-
-module_init (nb85e_uart_init);
-module_exit (nb85e_uart_exit);
-
-MODULE_AUTHOR ("Miles Bader");
-MODULE_DESCRIPTION ("NEC " NB85E_UART_CHIP_NAME " on-chip UART");
-MODULE_LICENSE ("GPL");
diff -Nru a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
--- a/drivers/serial/sunsu.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/serial/sunsu.c	Sat Jul 19 12:54:23 2003
@@ -102,6 +102,7 @@
 	int			l1_down;
 #ifdef CONFIG_SERIO
 	struct serio		serio;
+	int			serio_open;
 #endif
 };
 
@@ -1021,12 +1022,13 @@
 
 static int sunsu_serio_open(struct serio *serio)
 {
+	struct uart_sunsu_port *up = serio->driver;
 	unsigned long flags;
 	int ret;
 
 	spin_lock_irqsave(&sunsu_serio_lock, flags);
-	if (serio->private == NULL) {
-		serio->private = (void *) -1L;
+	if (!up->serio_open) {
+		up->serio_open = 1;
 		ret = 0;
 	} else
 		ret = -EBUSY;
@@ -1037,10 +1039,11 @@
 
 static void sunsu_serio_close(struct serio *serio)
 {
+	struct uart_sunsu_port *up = serio->driver;
 	unsigned long flags;
 
 	spin_lock_irqsave(&sunsu_serio_lock, flags);
-	serio->private = NULL;
+	up->serio_open = 0;
 	spin_unlock_irqrestore(&sunsu_serio_lock, flags);
 }
 
diff -Nru a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
--- a/drivers/serial/sunzilog.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/serial/sunzilog.c	Sat Jul 19 12:54:30 2003
@@ -112,6 +112,7 @@
 
 #ifdef CONFIG_SERIO
 	struct serio			serio;
+	int				serio_open;
 #endif
 };
 
@@ -1311,12 +1312,13 @@
 
 static int sunzilog_serio_open(struct serio *serio)
 {
+	struct uart_sunzilog_port *up = serio->driver;
 	unsigned long flags;
 	int ret;
 
 	spin_lock_irqsave(&sunzilog_serio_lock, flags);
-	if (serio->private == NULL) {
-		serio->private = (void *) -1L;
+	if (!up->serio_open) {
+		up->serio_open = 1;
 		ret = 0;
 	} else
 		ret = -EBUSY;
@@ -1327,10 +1329,11 @@
 
 static void sunzilog_serio_close(struct serio *serio)
 {
+	struct uart_sunzilog_port *up = serio->driver;
 	unsigned long flags;
 
 	spin_lock_irqsave(&sunzilog_serio_lock, flags);
-	serio->private = NULL;
+	up->serio_open = 0;
 	spin_unlock_irqrestore(&sunzilog_serio_lock, flags);
 }
 
diff -Nru a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/serial/v850e_uart.c	Sat Jul 19 12:54:27 2003
@@ -0,0 +1,549 @@
+/*
+ * drivers/serial/v850e_uart.c -- Serial I/O using V850E on-chip UART or UARTB
+ *
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+/* This driver supports both the original V850E UART interface (called
+   merely `UART' in the docs) and the newer `UARTB' interface, which is
+   roughly a superset of the first one.  The selection is made at
+   configure time -- if CONFIG_V850E_UARTB is defined, then UARTB is
+   presumed, otherwise the old UART -- as these are on-CPU UARTS, a system
+   can never have both.
+
+   The UARTB interface also has a 16-entry FIFO mode, which is not
+   yet supported by this driver.  */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/console.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/v850e_uart.h>
+
+/* Initial UART state.  This may be overridden by machine-dependent headers. */
+#ifndef V850E_UART_INIT_BAUD
+#define V850E_UART_INIT_BAUD	115200
+#endif
+#ifndef V850E_UART_INIT_CFLAGS
+#define V850E_UART_INIT_CFLAGS	(B115200 | CS8 | CREAD)
+#endif
+
+/* A string used for prefixing printed descriptions; since the same UART
+   macro is actually used on other chips than the V850E.  This must be a
+   constant string.  */
+#ifndef V850E_UART_CHIP_NAME
+#define V850E_UART_CHIP_NAME	"V850E"
+#endif
+
+#define V850E_UART_MINOR_BASE	64	   /* First tty minor number */
+
+
+/* Low-level UART functions.  */
+
+/* Configure and turn on uart channel CHAN, using the termios `control
+   modes' bits in CFLAGS, and a baud-rate of BAUD.  */
+void v850e_uart_configure (unsigned chan, unsigned cflags, unsigned baud)
+{
+	int flags;
+	v850e_uart_speed_t old_speed;
+	v850e_uart_config_t old_config;
+	v850e_uart_speed_t new_speed = v850e_uart_calc_speed (baud);
+	v850e_uart_config_t new_config = v850e_uart_calc_config (cflags);
+
+	/* Disable interrupts while we're twiddling the hardware.  */
+	local_irq_save (flags);
+
+#ifdef V850E_UART_PRE_CONFIGURE
+	V850E_UART_PRE_CONFIGURE (chan, cflags, baud);
+#endif
+
+	old_config = V850E_UART_CONFIG (chan);
+	old_speed = v850e_uart_speed (chan);
+
+	if (! v850e_uart_speed_eq (old_speed, new_speed)) {
+		/* The baud rate has changed.  First, disable the UART.  */
+		V850E_UART_CONFIG (chan) = V850E_UART_CONFIG_FINI;
+		old_config = 0;	/* Force the uart to be re-initialized. */
+
+		/* Reprogram the baud-rate generator.  */
+		v850e_uart_set_speed (chan, new_speed);
+	}
+
+	if (! (old_config & V850E_UART_CONFIG_ENABLED)) {
+		/* If we are using the uart for the first time, start by
+		   enabling it, which must be done before turning on any
+		   other bits.  */
+		V850E_UART_CONFIG (chan) = V850E_UART_CONFIG_INIT;
+		/* See the initial state.  */
+		old_config = V850E_UART_CONFIG (chan);
+	}
+
+	if (new_config != old_config) {
+		/* Which of the TXE/RXE bits we'll temporarily turn off
+		   before changing other control bits.  */
+		unsigned temp_disable = 0;
+		/* Which of the TXE/RXE bits will be enabled.  */
+		unsigned enable = 0;
+		unsigned changed_bits = new_config ^ old_config;
+
+		/* Which of RX/TX will be enabled in the new configuration.  */
+		if (new_config & V850E_UART_CONFIG_RX_BITS)
+			enable |= (new_config & V850E_UART_CONFIG_RX_ENABLE);
+		if (new_config & V850E_UART_CONFIG_TX_BITS)
+			enable |= (new_config & V850E_UART_CONFIG_TX_ENABLE);
+
+		/* Figure out which of RX/TX needs to be disabled; note
+		   that this will only happen if they're not already
+		   disabled.  */
+		if (changed_bits & V850E_UART_CONFIG_RX_BITS)
+			temp_disable
+				|= (old_config & V850E_UART_CONFIG_RX_ENABLE);
+		if (changed_bits & V850E_UART_CONFIG_TX_BITS)
+			temp_disable
+				|= (old_config & V850E_UART_CONFIG_TX_ENABLE);
+
+		/* We have to turn off RX and/or TX mode before changing
+		   any associated control bits.  */
+		if (temp_disable)
+			V850E_UART_CONFIG (chan) = old_config & ~temp_disable;
+
+		/* Write the new control bits, while RX/TX are disabled. */ 
+		if (changed_bits & ~enable)
+			V850E_UART_CONFIG (chan) = new_config & ~enable;
+
+		v850e_uart_config_delay (new_config, new_speed);
+
+		/* Write the final version, with enable bits turned on.  */
+		V850E_UART_CONFIG (chan) = new_config;
+	}
+
+	local_irq_restore (flags);
+}
+
+
+/*  Low-level console. */
+
+#ifdef CONFIG_V850E_UART_CONSOLE
+
+static void v850e_uart_cons_write (struct console *co,
+				   const char *s, unsigned count)
+{
+	if (count > 0) {
+		unsigned chan = co->index;
+		unsigned irq = V850E_UART_TX_IRQ (chan);
+		int irq_was_enabled, irq_was_pending, flags;
+
+		/* We don't want to get `transmission completed'
+		   interrupts, since we're busy-waiting, so we disable them
+		   while sending (we don't disable interrupts entirely
+		   because sending over a serial line is really slow).  We
+		   save the status of the tx interrupt and restore it when
+		   we're done so that using printk doesn't interfere with
+		   normal serial transmission (other than interleaving the
+		   output, of course!).  This should work correctly even if
+		   this function is interrupted and the interrupt printks
+		   something.  */
+
+		/* Disable interrupts while fiddling with tx interrupt.  */
+		local_irq_save (flags);
+		/* Get current tx interrupt status.  */
+		irq_was_enabled = v850e_intc_irq_enabled (irq);
+		irq_was_pending = v850e_intc_irq_pending (irq);
+		/* Disable tx interrupt if necessary.  */
+		if (irq_was_enabled)
+			v850e_intc_disable_irq (irq);
+		/* Turn interrupts back on.  */
+		local_irq_restore (flags);
+
+		/* Send characters.  */
+		while (count > 0) {
+			int ch = *s++;
+
+			if (ch == '\n') {
+				/* We don't have the benefit of a tty
+				   driver, so translate NL into CR LF.  */
+				v850e_uart_wait_for_xmit_ok (chan);
+				v850e_uart_putc (chan, '\r');
+			}
+
+			v850e_uart_wait_for_xmit_ok (chan);
+			v850e_uart_putc (chan, ch);
+
+			count--;
+		}
+
+		/* Restore saved tx interrupt status.  */
+		if (irq_was_enabled) {
+			/* Wait for the last character we sent to be
+			   completely transmitted (as we'll get an
+			   interrupt interrupt at that point).  */
+			v850e_uart_wait_for_xmit_done (chan);
+			/* Clear pending interrupts received due
+			   to our transmission, unless there was already
+			   one pending, in which case we want the
+			   handler to be called.  */
+			if (! irq_was_pending)
+				v850e_intc_clear_pending_irq (irq);
+			/* ... and then turn back on handling.  */
+			v850e_intc_enable_irq (irq);
+		}
+	}
+}
+
+extern struct uart_driver v850e_uart_driver;
+static struct console v850e_uart_cons =
+{
+    .name	= "ttyS",
+    .write	= v850e_uart_cons_write,
+    .device	= uart_console_device,
+    .flags	= CON_PRINTBUFFER,
+    .cflag	= V850E_UART_INIT_CFLAGS,
+    .index	= -1,
+    .data	= &v850e_uart_driver,
+};
+
+void v850e_uart_cons_init (unsigned chan)
+{
+	v850e_uart_configure (chan, V850E_UART_INIT_CFLAGS,
+			      V850E_UART_INIT_BAUD);
+	v850e_uart_cons.index = chan;
+	register_console (&v850e_uart_cons);
+	printk ("Console: %s on-chip UART channel %d\n",
+		V850E_UART_CHIP_NAME, chan);
+}
+
+/* This is what the init code actually calls.  */
+static int v850e_uart_console_init (void)
+{
+	v850e_uart_cons_init (V850E_UART_CONSOLE_CHANNEL);
+	return 0;
+}
+console_initcall(v850e_uart_console_init);
+
+#define V850E_UART_CONSOLE &v850e_uart_cons
+
+#else /* !CONFIG_V850E_UART_CONSOLE */
+#define V850E_UART_CONSOLE 0
+#endif /* CONFIG_V850E_UART_CONSOLE */
+
+/* TX/RX interrupt handlers.  */
+
+static void v850e_uart_stop_tx (struct uart_port *port, unsigned tty_stop);
+
+void v850e_uart_tx (struct uart_port *port)
+{
+	struct circ_buf *xmit = &port->info->xmit;
+	int stopped = uart_tx_stopped (port);
+
+	if (v850e_uart_xmit_ok (port->line)) {
+		int tx_ch;
+
+		if (port->x_char) {
+			tx_ch = port->x_char;
+			port->x_char = 0;
+		} else if (!uart_circ_empty (xmit) && !stopped) {
+			tx_ch = xmit->buf[xmit->tail];
+			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		} else
+			goto no_xmit;
+
+		v850e_uart_putc (port->line, tx_ch);
+		port->icount.tx++;
+
+		if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS)
+			uart_write_wakeup (port);
+	}
+
+ no_xmit:
+	if (uart_circ_empty (xmit) || stopped)
+		v850e_uart_stop_tx (port, stopped);
+}
+
+static irqreturn_t v850e_uart_tx_irq(int irq, void *data, struct pt_regs *regs)
+{
+	struct uart_port *port = data;
+	v850e_uart_tx (port);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t v850e_uart_rx_irq(int irq, void *data, struct pt_regs *regs)
+{
+	struct uart_port *port = data;
+	unsigned ch_stat = TTY_NORMAL;
+	unsigned ch = v850e_uart_getc (port->line);
+	unsigned err = v850e_uart_err (port->line);
+
+	if (err) {
+		if (err & V850E_UART_ERR_OVERRUN) {
+			ch_stat = TTY_OVERRUN;
+			port->icount.overrun++;
+		} else if (err & V850E_UART_ERR_FRAME) {
+			ch_stat = TTY_FRAME;
+			port->icount.frame++;
+		} else if (err & V850E_UART_ERR_PARITY) {
+			ch_stat = TTY_PARITY;
+			port->icount.parity++;
+		}
+	}
+
+	port->icount.rx++;
+
+	tty_insert_flip_char (port->info->tty, ch, ch_stat);
+	tty_schedule_flip (port->info->tty);
+
+	return IRQ_HANDLED;
+}
+
+
+/* Control functions for the serial framework.  */
+
+static void v850e_uart_nop (struct uart_port *port) { }
+static int v850e_uart_success (struct uart_port *port) { return 0; }
+
+static unsigned v850e_uart_tx_empty (struct uart_port *port)
+{
+	return TIOCSER_TEMT;	/* Can't detect.  */
+}
+
+static void v850e_uart_set_mctrl (struct uart_port *port, unsigned mctrl)
+{
+#ifdef V850E_UART_SET_RTS
+	V850E_UART_SET_RTS (port->line, (mctrl & TIOCM_RTS));
+#endif
+}
+
+static unsigned v850e_uart_get_mctrl (struct uart_port *port)
+{
+	/* We don't support DCD or DSR, so consider them permanently active. */
+	int mctrl = TIOCM_CAR | TIOCM_DSR;
+
+	/* We may support CTS.  */
+#ifdef V850E_UART_CTS
+	mctrl |= V850E_UART_CTS(port->line) ? TIOCM_CTS : 0;
+#else
+	mctrl |= TIOCM_CTS;
+#endif
+
+	return mctrl;
+}
+
+static void v850e_uart_start_tx (struct uart_port *port, unsigned tty_start)
+{
+	v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line));
+	v850e_uart_tx (port);
+	v850e_intc_enable_irq (V850E_UART_TX_IRQ (port->line));
+}
+
+static void v850e_uart_stop_tx (struct uart_port *port, unsigned tty_stop)
+{
+	v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line));
+}
+
+static void v850e_uart_start_rx (struct uart_port *port)
+{
+	v850e_intc_enable_irq (V850E_UART_RX_IRQ (port->line));
+}
+
+static void v850e_uart_stop_rx (struct uart_port *port)
+{
+	v850e_intc_disable_irq (V850E_UART_RX_IRQ (port->line));
+}
+
+static void v850e_uart_break_ctl (struct uart_port *port, int break_ctl)
+{
+	/* Umm, do this later.  */
+}
+
+static int v850e_uart_startup (struct uart_port *port)
+{
+	int err;
+
+	/* Alloc RX irq.  */
+	err = request_irq (V850E_UART_RX_IRQ (port->line), v850e_uart_rx_irq,
+			   SA_INTERRUPT, "v850e_uart", port);
+	if (err)
+		return err;
+
+	/* Alloc TX irq.  */
+	err = request_irq (V850E_UART_TX_IRQ (port->line), v850e_uart_tx_irq,
+			   SA_INTERRUPT, "v850e_uart", port);
+	if (err) {
+		free_irq (V850E_UART_RX_IRQ (port->line), port);
+		return err;
+	}
+
+	v850e_uart_start_rx (port);
+
+	return 0;
+}
+
+static void v850e_uart_shutdown (struct uart_port *port)
+{
+	/* Disable port interrupts.  */
+	free_irq (V850E_UART_TX_IRQ (port->line), port);
+	free_irq (V850E_UART_RX_IRQ (port->line), port);
+
+	/* Turn off xmit/recv enable bits.  */
+	V850E_UART_CONFIG (port->line)
+		&= ~(V850E_UART_CONFIG_TX_ENABLE
+		     | V850E_UART_CONFIG_RX_ENABLE);
+	/* Then reset the channel.  */
+	V850E_UART_CONFIG (port->line) = 0;
+}
+
+static void
+v850e_uart_set_termios (struct uart_port *port, struct termios *termios,
+		        struct termios *old)
+{
+	unsigned cflags = termios->c_cflag;
+
+	/* Restrict flags to legal values.  */
+	if ((cflags & CSIZE) != CS7 && (cflags & CSIZE) != CS8)
+		/* The new value of CSIZE is invalid, use the old value.  */
+		cflags = (cflags & ~CSIZE)
+			| (old ? (old->c_cflag & CSIZE) : CS8);
+
+	termios->c_cflag = cflags;
+
+	v850e_uart_configure (port->line, cflags,
+			      uart_get_baud_rate (port, termios, old,
+						  v850e_uart_min_baud(),
+						  v850e_uart_max_baud()));
+}
+
+static const char *v850e_uart_type (struct uart_port *port)
+{
+	return port->type == PORT_V850E_UART ? "v850e_uart" : 0;
+}
+
+static void v850e_uart_config_port (struct uart_port *port, int flags)
+{
+	if (flags & UART_CONFIG_TYPE)
+		port->type = PORT_V850E_UART;
+}
+
+static int
+v850e_uart_verify_port (struct uart_port *port, struct serial_struct *ser)
+{
+	if (ser->type != PORT_UNKNOWN && ser->type != PORT_V850E_UART)
+		return -EINVAL;
+	if (ser->irq != V850E_UART_TX_IRQ (port->line))
+		return -EINVAL;
+	return 0;
+}
+
+static struct uart_ops v850e_uart_ops = {
+	.tx_empty	= v850e_uart_tx_empty,
+	.get_mctrl	= v850e_uart_get_mctrl,
+	.set_mctrl	= v850e_uart_set_mctrl,
+	.start_tx	= v850e_uart_start_tx,
+	.stop_tx	= v850e_uart_stop_tx,
+	.stop_rx	= v850e_uart_stop_rx,
+	.enable_ms	= v850e_uart_nop,
+	.break_ctl	= v850e_uart_break_ctl,
+	.startup	= v850e_uart_startup,
+	.shutdown	= v850e_uart_shutdown,
+	.set_termios	= v850e_uart_set_termios,
+	.type		= v850e_uart_type,
+	.release_port	= v850e_uart_nop,
+	.request_port	= v850e_uart_success,
+	.config_port	= v850e_uart_config_port,
+	.verify_port	= v850e_uart_verify_port,
+};
+
+/* Initialization and cleanup.  */
+
+static struct uart_driver v850e_uart_driver = {
+	.owner			= THIS_MODULE,
+	.driver_name		= "v850e_uart",
+	.devfs_name		= "tts/",
+	.dev_name		= "ttyS",
+	.major			= TTY_MAJOR,
+	.minor			= V850E_UART_MINOR_BASE,
+	.nr			= V850E_UART_NUM_CHANNELS,
+	.cons			= V850E_UART_CONSOLE,
+};
+
+
+static struct uart_port v850e_uart_ports[V850E_UART_NUM_CHANNELS];
+
+static int __init v850e_uart_init (void)
+{
+	int rval;
+
+	printk (KERN_INFO "%s on-chip UART\n", V850E_UART_CHIP_NAME);
+
+	rval = uart_register_driver (&v850e_uart_driver);
+	if (rval == 0) {
+		unsigned chan;
+
+		for (chan = 0; chan < V850E_UART_NUM_CHANNELS; chan++) {
+			struct uart_port *port = &v850e_uart_ports[chan];
+			
+			memset (port, 0, sizeof *port);
+
+			port->ops = &v850e_uart_ops;
+			port->line = chan;
+			port->iotype = SERIAL_IO_MEM;
+			port->flags = UPF_BOOT_AUTOCONF;
+
+			/* We actually use multiple IRQs, but the serial
+			   framework seems to mainly use this for
+			   informational purposes anyway.  Here we use the TX
+			   irq.  */
+			port->irq = V850E_UART_TX_IRQ (chan);
+
+			/* The serial framework doesn't really use these
+			   membase/mapbase fields for anything useful, but
+			   it requires that they be something non-zero to
+			   consider the port `valid', and also uses them
+			   for informational purposes.  */
+			port->membase = (void *)V850E_UART_BASE_ADDR (chan);
+			port->mapbase = V850E_UART_BASE_ADDR (chan);
+
+			/* The framework insists on knowing the uart's master
+			   clock freq, though it doesn't seem to do anything
+			   useful for us with it.  We must make it at least
+			   higher than (the maximum baud rate * 16), otherwise
+			   the framework will puke during its internal
+			   calculations, and force the baud rate to be 9600.
+			   To be accurate though, just repeat the calculation
+			   we use when actually setting the speed.  */
+			port->uartclk = v850e_uart_max_clock() * 16;
+
+			uart_add_one_port (&v850e_uart_driver, port);
+		}
+	}
+
+	return rval;
+}
+
+static void __exit v850e_uart_exit (void)
+{
+	unsigned chan;
+
+	for (chan = 0; chan < V850E_UART_NUM_CHANNELS; chan++)
+		uart_remove_one_port (&v850e_uart_driver,
+				      &v850e_uart_ports[chan]);
+
+	uart_unregister_driver (&v850e_uart_driver);
+}
+
+module_init (v850e_uart_init);
+module_exit (v850e_uart_exit);
+
+MODULE_AUTHOR ("Miles Bader");
+MODULE_DESCRIPTION ("NEC " V850E_UART_CHIP_NAME " on-chip UART");
+MODULE_LICENSE ("GPL");
diff -Nru a/drivers/telephony/Kconfig b/drivers/telephony/Kconfig
--- a/drivers/telephony/Kconfig	Sat Jul 19 12:54:23 2003
+++ b/drivers/telephony/Kconfig	Sat Jul 19 12:54:23 2003
@@ -39,7 +39,7 @@
 
 config PHONE_IXJ_PCMCIA
 	tristate "QuickNet Internet LineJack/PhoneJack PCMCIA support"
-	depends on PHONE_IXJ
+	depends on PHONE_IXJ && PCMCIA
 	help
 	  Say Y here to configure in PCMCIA service support for the Quicknet
 	  cards manufactured by Quicknet Technologies, Inc.  This changes the
diff -Nru a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
--- a/drivers/telephony/ixj.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/telephony/ixj.c	Sat Jul 19 12:54:22 2003
@@ -23,6 +23,7 @@
  * Fixes:           David Huggins-Daines, <dhd@cepstral.com>
  *                  Fabio Ferrari, <fabio.ferrari@digitro.com.br>
  *                  Artis Kugevics, <artis@mt.lv>
+ *                  Daniele Bellucci, <bellucda@tiscali.it>
  *
  * More information about the hardware related to this driver can be found  
  * at our website:    http://www.quicknet.net
@@ -45,6 +46,10 @@
 
 /*
  * $Log: ixj.c,v $
+ *
+ * Revision 4.8  2003/07/09 19:39:00  Daniele Bellucci
+ * Audit some copy_*_user and minor cleanup.
+ *
  * Revision 4.7  2001/08/13 06:19:33  craigs
  * Added additional changes from Alan Cox and John Anderson for
  * 2.2 to 2.4 cleanup and bounds checking
@@ -363,12 +368,9 @@
 static IXJ *ixj_alloc(void)
 {
 	int cnt;
-	for(cnt=0; cnt<IXJMAX; cnt++)
-	{
+	for(cnt=0; cnt<IXJMAX; cnt++) {
 		if(!ixj[cnt].DSPbase)
-		{
 			return &ixj[cnt];
-		}
 	}
 	return NULL;
 }
@@ -6260,9 +6262,11 @@
 		break;
 	case IXJCTL_CIDCW:
 		if(arg) {
-			copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID));
-		}
-		else {
+			if (copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID))) {
+				retval = -EFAULT;
+				break;
+			}
+		} else {
 			memset(&j->cid_send, 0, sizeof(PHONE_CID));
 		}
 		ixj_write_cidcw(j);
@@ -6273,14 +6277,12 @@
                 /* Fall through */
  	case PHONE_RING_START:
 		if(arg) {
-			if(copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID)))
-			{
+			if (copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID))) {
 				retval = -EFAULT;
 				break;
 			}
 			ixj_write_cid(j);
-		}
-		else {
+		} else {
 			memset(&j->cid_send, 0, sizeof(PHONE_CID));
 		}
 		ixj_ring_start(j);
@@ -6696,7 +6698,8 @@
 	case IXJCTL_SET_FILTER_RAW:
 		if (copy_from_user(&jfr, (char *) arg, sizeof(jfr))) 
 			retval = -EFAULT;
-		retval = ixj_init_filter_raw(j, &jfr);
+		else
+			retval = ixj_init_filter_raw(j, &jfr);
 		break;
 	case IXJCTL_GET_FILTER_HIST:
 		if(arg<0||arg>3)
@@ -6705,8 +6708,10 @@
 			retval = j->filter_hist[arg];
 		break;
 	case IXJCTL_INIT_TONE:
-		copy_from_user(&ti, (char *) arg, sizeof(ti));
-		retval = ixj_init_tone(j, &ti);
+		if (copy_from_user(&ti, (char *) arg, sizeof(ti)))
+			retval = -EFAULT;
+		else
+			retval = ixj_init_tone(j, &ti);
 		break;
 	case IXJCTL_TONE_CADENCE:
 		retval = ixj_build_cadence(j, (IXJ_CADENCE *) arg);
@@ -6715,8 +6720,10 @@
 		retval = ixj_build_filter_cadence(j, (IXJ_FILTER_CADENCE *) arg);
 		break;
 	case IXJCTL_SIGCTL:
-		if (copy_from_user(&j->sigdef, (char *)arg, sizeof(IXJ_SIGDEF)))
+		if (copy_from_user(&j->sigdef, (char *)arg, sizeof(IXJ_SIGDEF))) {
 			retval = -EFAULT;
+			break;
+		}
 		j->ixj_signals[j->sigdef.event] = j->sigdef.signal;
 		if(j->sigdef.event < 33) {
 			raise = 1;
@@ -7693,7 +7700,7 @@
 MODULE_AUTHOR("Ed Okerson <eokerson@quicknet.net>");
 MODULE_LICENSE("GPL");
 
-void ixj_exit(void)
+static void __exit ixj_exit(void)
 {
         cleanup();
 }
@@ -7852,7 +7859,7 @@
 	return probe;
 }
 
-int __init ixj_init(void)
+static int __init ixj_init(void)
 {
 	int cnt = 0;
 	int probe = 0;   
diff -Nru a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c
--- a/drivers/usb/class/bluetty.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/usb/class/bluetty.c	Sat Jul 19 12:54:26 2003
@@ -1320,7 +1320,8 @@
 
 	bluetooth_tty_driver->owner = THIS_MODULE;
 	bluetooth_tty_driver->driver_name = "usb-bluetooth";
-	bluetooth_tty_driver->name = "usb/ttub/";
+	bluetooth_tty_driver->name = "ttyUB";
+	bluetooth_tty_driver->devfs_name = "usb/ttub/";
 	bluetooth_tty_driver->major = BLUETOOTH_TTY_MAJOR;
 	bluetooth_tty_driver->minor_start = 0;
 	bluetooth_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
diff -Nru a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
--- a/drivers/usb/class/cdc-acm.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/usb/class/cdc-acm.c	Sat Jul 19 12:54:25 2003
@@ -765,7 +765,8 @@
 		return -ENOMEM;
 	acm_tty_driver->owner = THIS_MODULE,
 	acm_tty_driver->driver_name = "acm",
-	acm_tty_driver->name = "usb/acm/",
+	acm_tty_driver->name = "ttyACM",
+	acm_tty_driver->devfs_name = "usb/acm/",
 	acm_tty_driver->major = ACM_TTY_MAJOR,
 	acm_tty_driver->minor_start = 0,
 	acm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL,
diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
--- a/drivers/usb/class/usblp.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/usb/class/usblp.c	Sat Jul 19 12:54:23 2003
@@ -359,7 +359,6 @@
 	file->private_data = usblp;
 
 	usblp->writeurb->transfer_buffer_length = 0;
-	usblp->writeurb->status = 0;
 	usblp->wcomplete = 1; /* we begin writeable */
 	usblp->rcomplete = 0;
 
@@ -833,22 +832,15 @@
 	init_waitqueue_head(&usblp->wait);
 	usblp->ifnum = intf->altsetting->desc.bInterfaceNumber;
 
-	retval = usb_register_dev(intf, &usblp_class);
-	if (retval) {
-		err("Not able to get a minor for this device.");
-		goto abort;
-	}
-	usblp->minor = intf->minor;
-
 	usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!usblp->writeurb) {
 		err("out of memory");
-		goto abort_minor;
+		goto abort;
 	}
 	usblp->readurb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!usblp->readurb) {
 		err("out of memory");
-		goto abort_minor;
+		goto abort;
 	}
 
 	/* Malloc device ID string buffer to the largest expected length,
@@ -856,7 +848,7 @@
 	 * could change in length. */
 	if (!(usblp->device_id_string = kmalloc(USBLP_DEVICE_ID_SIZE, GFP_KERNEL))) {
 		err("out of memory for device_id_string");
-		goto abort_minor;
+		goto abort;
 	}
 
 	usblp->writebuf = usblp->readbuf = NULL;
@@ -868,19 +860,19 @@
 	if (!(usblp->writebuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE,
 				GFP_KERNEL, &usblp->writeurb->transfer_dma))) {
 		err("out of memory for write buf");
-		goto abort_minor;
+		goto abort;
 	}
 	if (!(usblp->readbuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE,
 				GFP_KERNEL, &usblp->readurb->transfer_dma))) {
 		err("out of memory for read buf");
-		goto abort_minor;
+		goto abort;
 	}
 
 	/* Allocate buffer for printer status */
 	usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL);
 	if (!usblp->statusbuf) {
 		err("out of memory for statusbuf");
-		goto abort_minor;
+		goto abort;
 	}
 
 	/* Lookup quirks for this printer. */
@@ -894,12 +886,12 @@
 		dbg("incompatible printer-class device 0x%4.4X/0x%4.4X",
 			dev->descriptor.idVendor,
 			dev->descriptor.idProduct);
-		goto abort_minor;
+		goto abort;
 	}
 
 	/* Setup the selected alternate setting and endpoints. */
 	if (usblp_set_protocol(usblp, protocol) < 0)
-		goto abort_minor;
+		goto abort;
 
 	/* Retrieve and store the device ID string. */
 	usblp_cache_device_id_string(usblp);
@@ -920,10 +912,17 @@
 
 	usblp->present = 1;
 
+	retval = usb_register_dev(intf, &usblp_class);
+	if (retval) {
+		err("Not able to get a minor for this device.");
+		goto abort_intfdata;
+	}
+	usblp->minor = intf->minor;
+
 	return 0;
 
-abort_minor:
-	usb_deregister_dev(intf, &usblp_class);
+abort_intfdata:
+	usb_set_intfdata (intf, NULL);
 abort:
 	if (usblp) {
 		if (usblp->writebuf)
diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
--- a/drivers/usb/core/hcd-pci.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/usb/core/hcd-pci.c	Sat Jul 19 12:54:25 2003
@@ -81,7 +81,7 @@
 	
         if (!dev->irq) {
         	err ("Found HC with no IRQ.  Check BIOS/PCI %s setup!",
-			dev->slot_name);
+			pci_name(dev));
    	        return -ENODEV;
         }
 	
@@ -99,7 +99,7 @@
 			retval = -EFAULT;
 clean_1:
 			release_mem_region (resource, len);
-			err ("init %s fail, %d", dev->slot_name, retval);
+			err ("init %s fail, %d", pci_name(dev), retval);
 			return retval;
 		}
 
@@ -136,7 +136,7 @@
 			goto clean_1;
 		} else {
 			release_region (resource, len);
-			err ("init %s fail, %d", dev->slot_name, retval);
+			err ("init %s fail, %d", pci_name(dev), retval);
 			return retval;
 		}
 	}
@@ -144,7 +144,7 @@
 	hcd->driver = driver;
 	hcd->description = driver->description;
 	hcd->pdev = dev;
-	hcd->self.bus_name = dev->slot_name;
+	hcd->self.bus_name = pci_name(dev);
 	hcd->product_desc = dev->dev.name;
 	hcd->self.controller = &dev->dev;
 	hcd->controller = hcd->self.controller;
@@ -279,6 +279,7 @@
 /**
  * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD
  * @dev: USB Host Controller being suspended
+ * @state: state that the controller is going into
  *
  * Store this function in the HCD's struct pci_driver as suspend().
  */
diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
--- a/drivers/usb/core/hcd.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/usb/core/hcd.c	Sat Jul 19 12:54:25 2003
@@ -1293,7 +1293,8 @@
 	}
 
 	/* then kill any current requests */
-	spin_lock_irqsave (&hcd_data_lock, flags);
+	local_irq_save (flags);
+	spin_lock (&hcd_data_lock);
 	list_for_each_entry (urb, &dev->urb_list, urb_list) {
 		int	tmp = urb->pipe;
 
@@ -1311,13 +1312,13 @@
 		if (urb->status != -EINPROGRESS)
 			continue;
 		usb_get_urb (urb);
-		spin_unlock_irqrestore (&hcd_data_lock, flags);
+		spin_unlock (&hcd_data_lock);
 
-		spin_lock_irqsave (&urb->lock, flags);
+		spin_lock (&urb->lock);
 		tmp = urb->status;
 		if (tmp == -EINPROGRESS)
 			urb->status = -ESHUTDOWN;
-		spin_unlock_irqrestore (&urb->lock, flags);
+		spin_unlock (&urb->lock);
 
 		/* kick hcd unless it's already returning this */
 		if (tmp == -EINPROGRESS) {
@@ -1340,7 +1341,8 @@
 		/* list contents may have changed */
 		goto rescan;
 	}
-	spin_unlock_irqrestore (&hcd_data_lock, flags);
+	spin_unlock (&hcd_data_lock);
+	local_irq_restore (flags);
 
 	/* synchronize with the hardware, so old configuration state
 	 * clears out immediately (and will be freed).
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/usb/core/usb.c	Sat Jul 19 12:54:25 2003
@@ -80,6 +80,23 @@
 
 static int usb_generic_driver_data;
 
+/* deallocate hcd/hardware state ... and nuke all pending urbs */
+static void nuke_urbs(struct usb_device *dev)
+{
+	void (*disable)(struct usb_device *, int);
+	int i;
+
+	if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->disable)
+		return;
+	dbg("nuking urbs assigned to %s", dev->dev.bus_id);
+
+	disable = dev->bus->op->disable;
+	for (i = 0; i < 15; i++) {
+		disable(dev, i);
+		disable(dev, USB_DIR_IN | i);
+	}
+}
+
 /* needs to be called with BKL held */
 int usb_device_probe(struct device *dev)
 {
@@ -116,6 +133,9 @@
 
 	down(&driver->serialize);
 
+	/* release all urbs for this device */
+	nuke_urbs(interface_to_usbdev(intf));
+
 	if (intf->driver && intf->driver->disconnect)
 		intf->driver->disconnect(intf);
 
@@ -896,6 +916,9 @@
 			usb_disconnect(child);
 	}
 
+	/* deallocate hcd/hardware state ... and nuke all pending urbs */
+	nuke_urbs(dev);
+
 	/* disconnect() drivers from interfaces (a key side effect) */
 	dev_dbg (&dev->dev, "unregistering interfaces\n");
 	if (dev->actconfig) {
@@ -905,16 +928,6 @@
 			/* remove this interface */
 			interface = &dev->actconfig->interface[i];
 			device_unregister(&interface->dev);
-		}
-	}
-
-	/* deallocate hcd/hardware state */
-	if (ops->disable) {
-		void	(*disable)(struct usb_device *, int) = ops->disable;
-
-		for (i = 0; i < 15; i++) {
-			disable (dev, i);
-			disable (dev, USB_DIR_IN | i);
 		}
 	}
 
diff -Nru a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
--- a/drivers/usb/gadget/ether.c	Sat Jul 19 12:54:29 2003
+++ b/drivers/usb/gadget/ether.c	Sat Jul 19 12:54:29 2003
@@ -1,5 +1,5 @@
 /*
- * ether.c -- CDC 1.1 Ethernet gadget driver
+ * ether.c -- Ethernet gadget driver, with CDC and non-CDC options
  *
  * Copyright (C) 2003 David Brownell
  *
@@ -58,21 +58,23 @@
 /*-------------------------------------------------------------------------*/
 
 /*
- * "Communications Device Class" (CDC) Ethernet class driver
+ * Ethernet gadget driver -- with CDC and non-CDC options
  *
  * CDC Ethernet is the standard USB solution for sending Ethernet frames
  * using USB.  Real hardware tends to use the same framing protocol but look
  * different for control features.  And Microsoft pushes their own approach
  * (RNDIS) instead of the standard.
+ *
+ * There's some hardware that can't talk CDC.  We make that hardware
+ * implement a "minimalist" vendor-agnostic CDC core:  same framing, but
+ * link-level setup only requires activating the configuration.
  */
 
-#define DRIVER_DESC		"CDC Ethernet Gadget"
-#define DRIVER_VERSION		"29 April 2003"
+#define DRIVER_DESC		"Ethernet Gadget"
+#define DRIVER_VERSION		"Bastille Day 2003"
 
 static const char shortname [] = "ether";
 static const char driver_desc [] = DRIVER_DESC;
-static const char control_name [] = "Communications Control";
-static const char data_name [] = "CDC Ethernet Data";
 
 #define MIN_PACKET	sizeof(struct ethhdr)
 #define	MAX_PACKET	ETH_DATA_LEN	/* biggest packet we'll rx/tx */
@@ -92,8 +94,7 @@
 	const struct usb_endpoint_descriptor
 				*in, *out, *status;
 
-	struct semaphore	mutex;
-	struct net_device	net;
+	struct net_device	*net;
 	struct net_device_stats	stats;
 	atomic_t		tx_qlen;
 
@@ -112,7 +113,7 @@
 
 static unsigned qmult = 4;
 
-#define HS_FACTOR	15
+#define HS_FACTOR	5
 
 #define qlen(gadget) \
 	(qmult*((gadget->speed == USB_SPEED_HIGH) ? HS_FACTOR : 1))
@@ -128,7 +129,7 @@
 
 /* Thanks to NetChip Technologies for donating this product ID.
  *
- * DO NOT REUSE THESE IDs with any other driver!!  Ever!!
+ * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
  * Instead:  allocate your own, using normal USB-IF procedures.
  */
 #define DRIVER_VENDOR_NUM	0x0525		/* NetChip */
@@ -158,6 +159,11 @@
  * for some reason doesn't handle full speed bulk maxpacket of 64.
  */
 
+#define DEV_CONFIG_VALUE	3	/* some hardware cares */
+
+/* #undef on hardware that can't implement CDC */
+#define	DEV_CONFIG_CDC
+
 /*
  * NetChip 2280, PCI based.
  *
@@ -172,7 +178,7 @@
 #define DRIVER_VERSION_NUM	0x0101
 #define EP0_MAXPACKET		64
 static const char EP_OUT_NAME [] = "ep-a";
-#define EP_OUT_NUM	2
+#define EP_OUT_NUM	1
 static const char EP_IN_NAME [] = "ep-b";
 #define EP_IN_NUM	2
 static const char EP_STATUS_NAME [] = "ep-f";
@@ -194,22 +200,21 @@
 #endif
 
 /*
- * PXA-250 UDC:  widely used in second gen Linux-capable PDAs.
+ * PXA-2xx UDC:  widely used in second gen Linux-capable ARM PDAs
+ * and other products.
  *
- * no limitations except from set_interface: docs say "no" to a third
- * interface. and the interrupt-only endpoints don't toggle, so we'll
- * just use a bulk-capable one instead.
+ * multiple interfaces (or altsettings) aren't usable.  so this hardware
+ * can't implement CDC, which needs both capabilities.
  */
-#ifdef	CONFIG_USB_ETH_PXA250
-#define CHIP			"pxa250"
+#ifdef	CONFIG_USB_ETH_PXA2XX
+#undef	DEV_CONFIG_CDC
+#define CHIP			"pxa2xx"
 #define DRIVER_VERSION_NUM	0x0103
 #define EP0_MAXPACKET		16
-static const char EP_OUT_NAME [] = "ep12out-bulk";
-#define EP_OUT_NUM	12
-static const char EP_IN_NAME [] = "ep11in-bulk";
-#define EP_IN_NUM	11
-static const char EP_STATUS_NAME [] = "ep6in-bulk";
-#define EP_STATUS_NUM	6
+static const char EP_OUT_NAME [] = "ep2out-bulk";
+#define EP_OUT_NUM	2
+static const char EP_IN_NAME [] = "ep1in-bulk";
+#define EP_IN_NUM	1
 /* doesn't support bus-powered operation */
 #define SELFPOWER USB_CONFIG_ATT_SELFPOWER
 /* supports remote wakeup, but this driver doesn't */
@@ -247,6 +252,29 @@
 #	error Configure some USB peripheral controller driver!
 #endif
 
+/* We normally expect hardware that can talk CDC.  That involves
+ * using multiple interfaces and altsettings, and maybe a status
+ * interrupt.  Driver binding to be done according to USB-IF class,
+ * though you can use different VENDOR and PRODUCT numbers if you
+ * want (and they're officially assigned).
+ * 
+ * For hardware that can't talk CDC, we use the same vendor ID that
+ * ARM Linux has used for ethernet-over-usb, both with sa1100 and
+ * with pxa250.  We're protocol-compatible, if the host-side drivers
+ * use the endpoint descriptors.  DRIVER_VERSION_NUM is nonzero, so
+ * drivers that need to hard-wire endpoint numbers have a hook.
+ */
+#ifdef	DEV_CONFIG_CDC
+#define	DEV_CONFIG_CLASS	USB_CLASS_COMM
+#else	
+#define	DEV_CONFIG_CLASS	USB_CLASS_VENDOR_SPEC
+#undef	EP_STATUS_NUM
+#undef	DRIVER_VENDOR_NUM
+#undef	DRIVER_PRODUCT_NUM
+#define	DRIVER_VENDOR_NUM	0x049f
+#define	DRIVER_PRODUCT_NUM	0x505a
+#endif /* CONFIG_CDC_ETHER */
+
 /* power usage is config specific.
  * hardware that supports remote wakeup defaults to disabling it.
  */
@@ -274,7 +302,8 @@
 /*-------------------------------------------------------------------------*/
 
 #define xprintk(d,level,fmt,args...) \
-	dev_printk(level , &(d)->gadget->dev , fmt , ## args)
+	printk(level "%s %s: " fmt , shortname , (d)->gadget->dev.bus_id , \
+		## args)
 
 #ifdef DEBUG
 #undef DEBUG
@@ -309,7 +338,7 @@
 /*
  * DESCRIPTORS ... most are static, but strings and (full) configuration
  * descriptors are built on demand.  Notice how most of the cdc descriptors
- * add no value to simple (typical) configurations.
+ * aren't needed in the "minimalist" mode.
  */
 
 #define STRING_MANUFACTURER		1
@@ -323,15 +352,14 @@
 /*
  * This device advertises one configuration.
  */
-#define	CONFIG_CDC_ETHER	3
-
 static const struct usb_device_descriptor
 device_desc = {
 	.bLength =		sizeof device_desc,
 	.bDescriptorType =	USB_DT_DEVICE,
 
 	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
-	.bDeviceClass =		USB_CLASS_COMM,
+
+	.bDeviceClass =		DEV_CONFIG_CLASS,
 	.bDeviceSubClass =	0,
 	.bDeviceProtocol =	0,
 	.bMaxPacketSize0 =	EP0_MAXPACKET,
@@ -350,13 +378,26 @@
 	.bDescriptorType =	USB_DT_CONFIG,
 
 	/* compute wTotalLength on the fly */
+#ifdef	DEV_CONFIG_CDC
 	.bNumInterfaces =	2,
-	.bConfigurationValue =	CONFIG_CDC_ETHER,
+#else
+	.bNumInterfaces =	1,
+#endif
+	.bConfigurationValue =	DEV_CONFIG_VALUE,
 	.iConfiguration =	STRING_PRODUCT,
 	.bmAttributes =		USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP,
 	.bMaxPower =		(MAX_USB_POWER + 1) / 2,
 };
 
+#ifdef	DEV_CONFIG_CDC
+
+/*
+ * Compared to the "minimalist" non-CDC model, the CDC model adds
+ * three class descriptors, two interface descrioptors, and a status
+ * endpoint.  Both have a "data" interface and two bulk endpoints.
+ * There are also differences in how control requests are handled.
+ */
+
 /* master comm interface optionally has a status notification endpoint */
 
 static const struct usb_interface_descriptor
@@ -446,7 +487,7 @@
  * some drivers (like current Linux cdc-ether!) "need" it to exist even
  * if they ignore the connect/disconnect notifications that real aether
  * can provide.  more advanced cdc configurations might want to support
- * encapsulated commands.
+ * encapsulated commands (vendor-specific, using control-OUT).
  */
  
 #define LOG2_STATUS_INTERVAL_MSEC	6
@@ -494,6 +535,29 @@
 	.bInterfaceProtocol =	0,
 	.iInterface =		STRING_DATA,
 };
+#else
+
+/*
+ * "Minimalist" non-CDC option is a simple vendor-neutral model that most
+ * full speed controllers can handle:  one interface, two bulk endpoints.
+ */
+
+static const struct usb_interface_descriptor
+data_intf = {
+	.bLength =		sizeof data_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	.bInterfaceNumber =	0,
+	.bAlternateSetting =	0,
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
+	.bInterfaceSubClass =	0,
+	.bInterfaceProtocol =	0,
+	.iInterface =		STRING_DATA,
+};
+
+#endif	/* DEV_CONFIG_CDC */
+
 
 static const struct usb_endpoint_descriptor
 fs_source_desc = {
@@ -563,12 +627,12 @@
 	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
 
 	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
-	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
+	.bDeviceClass =		DEV_CONFIG_CLASS,
 
 	/* assumes ep0 uses the same value for both speeds ... */
 	.bMaxPacketSize0 =	EP0_MAXPACKET,
 
-	.bNumConfigurations =	2,
+	.bNumConfigurations =	1,
 };
 
 /* maxpacket and other transfer characteristics vary by speed. */
@@ -581,16 +645,24 @@
 
 #endif	/* !HIGHSPEED */
 
+/*-------------------------------------------------------------------------*/
+
+/* descriptors that are built on-demand */
+
+#ifdef	DEV_CONFIG_CDC
 /* address that the host will use ... usually assigned at random */
 static char				ethaddr [2 * ETH_ALEN + 1];
+#endif
 
 /* static strings, in iso 8859/1 */
 static struct usb_string		strings [] = {
 	{ STRING_MANUFACTURER,	UTS_SYSNAME " " UTS_RELEASE "/" CHIP, },
 	{ STRING_PRODUCT,	driver_desc, },
+#ifdef	DEV_CONFIG_CDC
 	{ STRING_ETHADDR,	ethaddr, },
-	{ STRING_CONTROL,	control_name, },
-	{ STRING_DATA,		data_name, },
+	{ STRING_CONTROL,	"CDC Communications Control", },
+#endif
+	{ STRING_DATA,		"Ethernet Data", },
 	{  }		/* end of list */
 };
 
@@ -607,14 +679,18 @@
 config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index)
 {
 	const unsigned	config_len = USB_DT_CONFIG_SIZE
-				+ 3 * USB_DT_INTERFACE_SIZE
+#ifdef DEV_CONFIG_CDC
+				+ 2 * USB_DT_INTERFACE_SIZE
 				+ sizeof header_desc
 				+ sizeof union_desc
 				+ sizeof ether_desc
 #ifdef	EP_STATUS_NUM
 				+ USB_DT_ENDPOINT_SIZE
 #endif
+#endif /* DEV_CONFIG_CDC */
+				+ USB_DT_INTERFACE_SIZE
 				+ 2 * USB_DT_ENDPOINT_SIZE;
+
 #ifdef HIGHSPEED
 	int		hs;
 #endif
@@ -636,6 +712,7 @@
 		hs = !hs;
 #endif
 
+#ifdef DEV_CONFIG_CDC
 	/* control interface, class descriptors, optional status endpoint */
 	memcpy (buf, &control_intf, USB_DT_INTERFACE_SIZE);
 	buf += USB_DT_INTERFACE_SIZE;
@@ -660,6 +737,7 @@
 	/* default data altsetting has no endpoints */
 	memcpy (buf, &data_nop_intf, USB_DT_INTERFACE_SIZE);
 	buf += USB_DT_INTERFACE_SIZE;
+#endif /* DEV_CONFIG_CDC */
 
 	/* the "real" data interface has two endpoints */
 	memcpy (buf, &data_intf, USB_DT_INTERFACE_SIZE);
@@ -684,6 +762,8 @@
 
 /*-------------------------------------------------------------------------*/
 
+static void eth_start (struct eth_dev *dev, int gfp_flags);
+
 static int
 set_ether_config (struct eth_dev *dev, int gfp_flags)
 {
@@ -694,7 +774,8 @@
 	gadget_for_each_ep (ep, gadget) {
 		const struct usb_endpoint_descriptor	*d;
 
-		/* NOTE:  the host isn't allowed to use these two data
+#ifdef	DEV_CONFIG_CDC
+		/* With CDC,  the host isn't allowed to use these two data
 		 * endpoints in the default altsetting for the interface.
 		 * so we don't activate them yet.
 		 */
@@ -714,10 +795,11 @@
 			dev->out_ep = ep;
 			dev->out = d;
 			continue;
+		}
 
 #ifdef	EP_STATUS_NUM
 		/* optional status/notification endpoint */
-		} else if (strcmp (ep->name, EP_STATUS_NAME) == 0) {
+		else if (strcmp (ep->name, EP_STATUS_NAME) == 0) {
 			d = ep_desc (gadget, &hs_status_desc, &fs_status_desc);
 			result = usb_ep_enable (ep, d);
 			if (result == 0) {
@@ -726,16 +808,57 @@
 				dev->status = d;
 				continue;
 			}
+		}
 #endif
 
+#else	/* !CONFIG_CDC_ETHER */
+
+		/* non-CDC is simpler:  if the device is there,
+		 * it's live with rx and tx endpoints.
+		 */
+		/* one endpoint writes data back IN to the host */
+		if (strcmp (ep->name, EP_IN_NAME) == 0) {
+			d = ep_desc (gadget, &hs_source_desc, &fs_source_desc);
+			result = usb_ep_enable (ep, d);
+			if (result == 0) {
+				ep->driver_data = dev;
+				dev->in_ep = ep;
+				dev->in = d;
+				continue;
+			}
+
+		/* one endpoint just reads OUT packets */
+		} else if (strcmp (ep->name, EP_OUT_NAME) == 0) {
+			d = ep_desc (gadget, &hs_sink_desc, &fs_sink_desc);
+			result = usb_ep_enable (ep, d);
+			if (result == 0) {
+				ep->driver_data = dev;
+				dev->out_ep = ep;
+				dev->out = d;
+				continue;
+			}
+		}
+
+#endif /* !CONFIG_CDC_ETHER */
+
 		/* ignore any other endpoints */
-		} else
+		else
 			continue;
 
 		/* stop on error */
 		ERROR (dev, "can't enable %s, result %d\n", ep->name, result);
 		break;
 	}
+	if (!result && (!dev->in_ep || !dev->out_ep))
+		result = -ENODEV;
+
+#ifndef	DEV_CONFIG_CDC
+	if (result == 0) {
+		netif_carrier_on (dev->net);
+		if (netif_running (dev->net))
+			eth_start (dev, GFP_ATOMIC);
+	}
+#endif /* !CONFIG_CDC_ETHER */
 
 	if (result == 0)
 		DEBUG (dev, "qlen %d\n", qlen (gadget));
@@ -751,8 +874,8 @@
 
 	DEBUG (dev, "%s\n", __FUNCTION__);
 
-	netif_stop_queue (&dev->net);
-	netif_carrier_off (&dev->net);
+	netif_stop_queue (dev->net);
+	netif_carrier_off (dev->net);
 
 	/* just disable endpoints, forcing completion of pending i/o.
 	 * all our completion handlers free their requests in this case.
@@ -797,7 +920,7 @@
 	hw_optimize (gadget);
 
 	switch (number) {
-	case CONFIG_CDC_ETHER:
+	case DEV_CONFIG_VALUE:
 		result = set_ether_config (dev, gfp_flags);
 		break;
 	default:
@@ -807,8 +930,6 @@
 		return result;
 	}
 
-	if (!result && (!dev->in_ep || !dev->out_ep))
-		result = -ENODEV;
 	if (result)
 		eth_reset_config (dev);
 	else {
@@ -896,6 +1017,7 @@
 	 * FIXME ugly idiom, maybe we'd be better with just
 	 * a "cancel the whole queue" primitive since any
 	 * unlink-one primitive has way too many error modes.
+	 * here, we "know" toggle is already clear...
 	 */
 	usb_ep_disable (dev->status_ep);
 	usb_ep_enable (dev->status_ep, dev->status);
@@ -953,8 +1075,6 @@
  */
 #define CDC_SET_ETHERNET_PACKET_FILTER	0x43	/* required */
 
-static void eth_start (struct eth_dev *dev, int gfp_flags);
-
 /*
  * The setup() callback implements all the ep0 functionality that's not
  * handled lower down.  CDC has a number of less-common features:
@@ -1018,6 +1138,17 @@
 		value = eth_set_config (dev, ctrl->wValue, GFP_ATOMIC);
 		spin_unlock (&dev->lock);
 		break;
+#ifdef	CONFIG_USB_ETH_PXA2XX
+	/* PXA UDC prevents us from using SET_INTERFACE in normal ways.
+	 * And it hides GET_CONFIGURATION and GET_INTERFACE too.
+	 */
+	case USB_REQ_SET_INTERFACE:
+		spin_lock (&dev->lock);
+		value = eth_set_config (dev, DEV_CONFIG_VALUE, GFP_ATOMIC);
+		spin_unlock (&dev->lock);
+		break;
+
+#else	/* hardware that that stays out of our way */
 	case USB_REQ_GET_CONFIGURATION:
 		if (ctrl->bRequestType != USB_DIR_IN)
 			break;
@@ -1056,15 +1187,15 @@
 			if (ctrl->wValue == 1) {
 				usb_ep_enable (dev->in_ep, dev->in);
 				usb_ep_enable (dev->out_ep, dev->out);
-				netif_carrier_on (&dev->net);
+				netif_carrier_on (dev->net);
 #ifdef	EP_STATUS_NUM
 				issue_start_status (dev);
 #endif
-				if (netif_running (&dev->net))
+				if (netif_running (dev->net))
 					eth_start (dev, GFP_ATOMIC);
 			} else {
-				netif_stop_queue (&dev->net);
-				netif_carrier_off (&dev->net);
+				netif_stop_queue (dev->net);
+				netif_carrier_off (dev->net);
 			}
 			value = 0;
 			break;
@@ -1079,12 +1210,14 @@
 
 		/* if carrier is on, data interface is active. */
 		*(u8 *)req->buf =
-			((ctrl->wIndex == 1) && netif_carrier_ok (&dev->net))
+			((ctrl->wIndex == 1) && netif_carrier_ok (dev->net))
 				? 1
 				: 0,
 		value = min (ctrl->wLength, (u16) 1);
 		break;
+#endif
 
+#ifdef DEV_CONFIG_CDC
 	case CDC_SET_ETHERNET_PACKET_FILTER:
 		/* see 6.2.30: no data, wIndex = interface,
 		 * wValue = packet filter bitmap
@@ -1099,6 +1232,7 @@
 		 */
 		value = 0;
 		break;
+#endif /* DEV_CONFIG_CDC */
 
 	default:
 		VDEBUG (dev,
@@ -1129,8 +1263,8 @@
 	unsigned long		flags;
 
 	spin_lock_irqsave (&dev->lock, flags);
-	netif_stop_queue (&dev->net);
-	netif_carrier_off (&dev->net);
+	netif_stop_queue (dev->net);
+	netif_carrier_off (dev->net);
 	eth_reset_config (dev);
 	spin_unlock_irqrestore (&dev->lock, flags);
 
@@ -1175,10 +1309,10 @@
 
 		memset (&info, 0, sizeof info);
 		info.cmd = ETHTOOL_GDRVINFO;
-		strncpy (info.driver, shortname, sizeof info.driver);
-		strncpy (info.version, DRIVER_VERSION, sizeof info.version);
-		strncpy (info.fw_version, CHIP, sizeof info.fw_version);
-		strncpy (info.bus_info, dev->gadget->dev.bus_id,
+		strlcpy (info.driver, shortname, sizeof info.driver);
+		strlcpy (info.version, DRIVER_VERSION, sizeof info.version);
+		strlcpy (info.fw_version, CHIP, sizeof info.fw_version);
+		strlcpy (info.bus_info, dev->gadget->dev.bus_id,
 			sizeof info.bus_info);
 		if (copy_to_user (useraddr, &info, sizeof (info)))
 			return -EFAULT;
@@ -1227,7 +1361,7 @@
 	int			retval = 0;
 	size_t			size;
 
-	size = (sizeof (struct ethhdr) + dev->net.mtu + RX_EXTRA);
+	size = (sizeof (struct ethhdr) + dev->net->mtu + RX_EXTRA);
 
 	if ((skb = alloc_skb (size, gfp_flags)) == 0) {
 		DEBUG (dev, "no rx skb\n");
@@ -1241,16 +1375,9 @@
 	req->complete = rx_complete;
 	req->context = skb;
 
-	if (netif_running (&dev->net)) {
-		retval = usb_ep_queue (dev->out_ep, req, gfp_flags);
-		if (retval == -ENOMEM)
-			defer_kevent (dev, WORK_RX_MEMORY);
-		if (retval)
-			DEBUG (dev, "%s %d\n", __FUNCTION__, retval);
-	} else {
-		DEBUG (dev, "%s stopped\n", __FUNCTION__);
-		retval = -ENOLINK;
-	}
+	retval = usb_ep_queue (dev->out_ep, req, gfp_flags);
+	if (retval == -ENOMEM)
+		defer_kevent (dev, WORK_RX_MEMORY);
 	if (retval) {
 		DEBUG (dev, "rx submit --> %d\n", retval);
 		dev_kfree_skb_any (skb);
@@ -1278,8 +1405,8 @@
 			break;
 		}
 
-		skb->dev = &dev->net;
-		skb->protocol = eth_type_trans (skb, &dev->net);
+		skb->dev = dev->net;
+		skb->protocol = eth_type_trans (skb, dev->net);
 		dev->stats.rx_packets++;
 		dev->stats.rx_bytes += skb->len;
 
@@ -1294,9 +1421,7 @@
 	case -ECONNRESET:		// unlink
 	case -ESHUTDOWN:		// disconnect etc
 		VDEBUG (dev, "rx shutdown, code %d\n", status);
-		usb_ep_free_request (dev->out_ep, req);
-		req = 0;
-		break;
+		goto clean;
 
 	/* data overrun */
 	case -EOVERFLOW:
@@ -1311,7 +1436,11 @@
 
 	if (skb)
 		dev_kfree_skb_any (skb);
-
+	if (!netif_running (dev->net)) {
+clean:
+		usb_ep_free_request (dev->out_ep, req);
+		req = 0;
+	}
 	if (req)
 		rx_submit (dev, req, GFP_ATOMIC);
 }
@@ -1323,7 +1452,7 @@
 	if (test_bit (WORK_RX_MEMORY, &dev->todo)) {
 		struct usb_request	*req = 0;
 
-		if (netif_running (&dev->net))
+		if (netif_running (dev->net))
 			req = usb_ep_alloc_request (dev->in_ep, GFP_KERNEL);
 		else
 			clear_bit (WORK_RX_MEMORY, &dev->todo);
@@ -1342,18 +1471,25 @@
 	struct sk_buff	*skb = req->context;
 	struct eth_dev	*dev = ep->driver_data;
 
-	if (req->status)
+	switch (req->status) {
+	default:
 		dev->stats.tx_errors++;
-	else
+		VDEBUG (dev, "tx err %d\n", req->status);
+		/* FALLTHROUGH */
+	case -ECONNRESET:		// unlink
+	case -ESHUTDOWN:		// disconnect etc
+		break;
+	case 0:
 		dev->stats.tx_bytes += skb->len;
+	}
 	dev->stats.tx_packets++;
 
 	usb_ep_free_request (ep, req);
 	dev_kfree_skb_any (skb);
 
 	atomic_inc (&dev->tx_qlen);
-	if (netif_carrier_ok (&dev->net))
-		netif_wake_queue (&dev->net);
+	if (netif_carrier_ok (dev->net))
+		netif_wake_queue (dev->net);
 }
 
 static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
@@ -1437,7 +1573,7 @@
 
 	/* and open the tx floodgates */ 
 	atomic_set (&dev->tx_qlen, size);
-	netif_wake_queue (&dev->net);
+	netif_wake_queue (dev->net);
 }
 
 static int eth_open (struct net_device *net)
@@ -1445,10 +1581,8 @@
 	struct eth_dev		*dev = (struct eth_dev *) net->priv;
 
 	DEBUG (dev, "%s\n", __FUNCTION__);
-	down (&dev->mutex);
-	if (netif_carrier_ok (&dev->net))
+	if (netif_carrier_ok (dev->net))
 		eth_start (dev, GFP_KERNEL);
-	up (&dev->mutex);
 	return 0;
 }
 
@@ -1457,7 +1591,6 @@
 	struct eth_dev		*dev = (struct eth_dev *) net->priv;
 
 	DEBUG (dev, "%s\n", __FUNCTION__);
-	down (&dev->mutex);
 	netif_stop_queue (net);
 
 	DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
@@ -1469,7 +1602,7 @@
 	if (dev->gadget->speed != USB_SPEED_UNKNOWN) {
 		usb_ep_disable (dev->in_ep);
 		usb_ep_disable (dev->out_ep);
-		if (netif_carrier_ok (&dev->net)) {
+		if (netif_carrier_ok (dev->net)) {
 			DEBUG (dev, "host still using in/out endpoints\n");
 			usb_ep_enable (dev->in_ep, dev->in);
 			usb_ep_enable (dev->out_ep, dev->out);
@@ -1480,7 +1613,6 @@
 #endif
 	}
 
-	up (&dev->mutex);
 	return 0;
 }
 
@@ -1492,7 +1624,6 @@
 	struct eth_dev		*dev = get_gadget_data (gadget);
 
 	DEBUG (dev, "unbind\n");
-	down (&dev->mutex);
 
 	/* we've already been disconnected ... no i/o is active */
 	if (dev->req) {
@@ -1500,15 +1631,13 @@
 				dev->req->buf, dev->req->dma,
 				USB_BUFSIZ);
 		usb_ep_free_request (gadget->ep0, dev->req);
+		dev->req = 0;
 	}
 
-	unregister_netdev (&dev->net);
-	up (&dev->mutex);
+	unregister_netdev (dev->net);
 
 	/* assuming we used keventd, it must quiesce too */
 	flush_scheduled_work ();
-
-	kfree (dev);
 	set_gadget_data (gadget, 0);
 }
 
@@ -1517,22 +1646,24 @@
 {
 	struct eth_dev		*dev;
 	struct net_device	*net;
+	int			status = -ENOMEM;
+#ifdef	DEV_CONFIG_CDC
 	u8			node_id [ETH_ALEN];
 
 	/* just one upstream link at a time */
 	if (ethaddr [0] != 0)
 		return -ENODEV;
+#endif
 
-	dev = kmalloc (sizeof *dev, SLAB_KERNEL);
-	if (!dev)
-		return -ENOMEM;
-	memset (dev, 0, sizeof *dev);
+ 	net = alloc_etherdev (sizeof *dev);
+ 	if (!net)
+		return status;
+	dev = net->priv;
 	spin_lock_init (&dev->lock);
-	init_MUTEX_LOCKED (&dev->mutex);
 	INIT_WORK (&dev->work, eth_work, dev);
 
 	/* network device setup */
-	net = &dev->net;
+	dev->net = net;
 	SET_MODULE_OWNER (net);
 	net->priv = dev;
 	strcpy (net->name, "usb%d");
@@ -1545,6 +1676,7 @@
 	net->dev_addr [0] &= 0xfe;	// clear multicast bit
 	net->dev_addr [0] |= 0x02;	// set local assignment bit (IEEE802)
 
+#ifdef	DEV_CONFIG_CDC
 	/* ... another address for the host, on the other end of the
 	 * link, gets exported through CDC (see CDC spec table 41)
 	 */
@@ -1554,6 +1686,7 @@
 	snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X",
 		node_id [0], node_id [1], node_id [2],
 		node_id [3], node_id [4], node_id [5]);
+#endif
 
 	net->change_mtu = eth_change_mtu;
 	net->get_stats = eth_get_stats;
@@ -1567,36 +1700,38 @@
 	/* preallocate control response and buffer */
 	dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
 	if (!dev->req)
-		goto enomem;
+		goto fail;
 	dev->req->complete = eth_setup_complete;
 	dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
 				&dev->req->dma, GFP_KERNEL);
 	if (!dev->req->buf) {
 		usb_ep_free_request (gadget->ep0, dev->req);
-		goto enomem;
+		goto fail;
 	}
 
 	/* finish hookup to lower layer ... */
 	dev->gadget = gadget;
 	set_gadget_data (gadget, dev);
 	gadget->ep0->driver_data = dev;
-
+	INFO (dev, "%s, " CHIP ", version: " DRIVER_VERSION "\n", driver_desc);
+#ifdef	DEV_CONFIG_CDC
+	INFO (dev, "CDC host enet %s\n", ethaddr);
+#endif
+	
 	/* two kinds of host-initiated state changes:
 	 *  - iff DATA transfer is active, carrier is "on"
 	 *  - tx queueing enabled if open *and* carrier is "on"
 	 */
-	INFO (dev, "%s, host enet %s, version: " DRIVER_VERSION "\n",
-			driver_desc, ethaddr);
-	register_netdev (&dev->net);
-	netif_stop_queue (&dev->net);
-	netif_carrier_off (&dev->net);
-
-	up (&dev->mutex);
-	return 0;
+	netif_stop_queue (dev->net);
+	netif_carrier_off (dev->net);
 
-enomem:
+ 	// SET_NETDEV_DEV (dev->net, &gadget->dev);
+ 	status = register_netdev (dev->net);
+ 	if (status == 0)
+ 		return status;
+fail:
 	eth_unbind (gadget);
-	return -ENOMEM;
+	return status;
 }
 
 /*-------------------------------------------------------------------------*/
diff -Nru a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
--- a/drivers/usb/gadget/net2280.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/usb/gadget/net2280.c	Sat Jul 19 12:54:22 2003
@@ -2496,7 +2496,7 @@
 	device_remove_file (&pdev->dev, &dev_attr_registers);
 	pci_set_drvdata (pdev, 0);
 
-	INFO (dev, "unbind from pci %s\n", pdev->slot_name);
+	INFO (dev, "unbind from pci %s\n", pci_name(pdev));
 
 	kfree (dev);
 	the_controller = 0;
@@ -2518,7 +2518,7 @@
 	 * usb_gadget_driver_{register,unregister}() must change.
 	 */
 	if (the_controller) {
-		WARN (the_controller, "ignoring %s\n", pdev->slot_name);
+		WARN (the_controller, "ignoring %s\n", pci_name(pdev));
 		return -EBUSY;
 	}
 
@@ -2534,7 +2534,7 @@
 	dev->pdev = pdev;
 	dev->gadget.ops = &net2280_ops;
 
-	strcpy (dev->gadget.dev.bus_id, pdev->slot_name);
+	strcpy (dev->gadget.dev.bus_id, pci_name(pdev));
 	strcpy (dev->gadget.dev.name, pdev->dev.name);
 	dev->gadget.dev.parent = &pdev->dev;
 	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
diff -Nru a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
--- a/drivers/usb/gadget/net2280.h	Sat Jul 19 12:54:26 2003
+++ b/drivers/usb/gadget/net2280.h	Sat Jul 19 12:54:26 2003
@@ -654,7 +654,7 @@
 
 #define xprintk(dev,level,fmt,args...) \
 	printk(level "%s %s: " fmt , driver_name , \
-			dev->pdev->slot_name , ## args)
+			pci_name(dev->pdev) , ## args)
 
 #ifdef DEBUG
 #undef DEBUG
diff -Nru a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
--- a/drivers/usb/gadget/zero.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/usb/gadget/zero.c	Sat Jul 19 12:54:24 2003
@@ -92,7 +92,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-#define DRIVER_VERSION		"19 Feb 2003"
+#define DRIVER_VERSION		"Bastille Day 2003"
 
 static const char shortname [] = "zero";
 static const char longname [] = "Gadget Zero";
@@ -160,18 +160,18 @@
 #endif
 
 /*
- * PXA-250 UDC:  widely used in second gen Linux-capable PDAs.
+ * PXA-2xx UDC:  widely used in second gen Linux-capable PDAs.
  *
  * This has fifteen fixed-function full speed endpoints, and it
  * can support all USB transfer types.
  *
- * It only supports three configurations (numbered 1, 2, or 3)
- * with two interfaces each ... there's partial hardware support
- * for set_configuration and set_interface, preventing some more
- * interesting config/interface/endpoint arrangements.
+ * These supports three or four configurations, with fixed numbers.
+ * The hardware interprets SET_INTERFACE, net effect is that you
+ * can't use altsettings or reset the interfaces independently.
+ * So stick to a single interface.
  */
-#ifdef	CONFIG_USB_ZERO_PXA250
-#define CHIP			"pxa250"
+#ifdef	CONFIG_USB_ZERO_PXA2XX
+#define CHIP			"pxa2xx"
 #define DRIVER_VERSION_NUM	0x0103
 #define EP0_MAXPACKET		16
 static const char EP_OUT_NAME [] = "ep12out-bulk";
@@ -291,9 +291,12 @@
 
 static unsigned buflen = 4096;
 static unsigned qlen = 32;
+static unsigned pattern = 0;
 
 module_param (buflen, uint, S_IRUGO|S_IWUSR);
 module_param (qlen, uint, S_IRUGO|S_IWUSR);
+module_param (pattern, uint, S_IRUGO|S_IWUSR);
+
 
 /*
  * Normally the "loopback" configuration is second (index 1) so
@@ -497,8 +500,8 @@
 
 /*
  * config descriptors are also handcrafted.  these must agree with code
- * that sets configurations, and with code managing interface altsettings.
- * other complexity may come from:
+ * that sets configurations, and with code managing interfaces and their
+ * altsettings.  other complexity may come from:
  *
  *  - high speed support, including "other speed config" rules
  *  - multiple configurations
@@ -506,7 +509,7 @@
  *  - embedded class or vendor-specific descriptors
  *
  * this handles high speed, and has a second config that could as easily
- * have been an alternate interface setting.
+ * have been an alternate interface setting (on most hardware).
  *
  * NOTE:  to demonstrate (and test) more USB capabilities, this driver
  * should include an altsetting to test interrupt transfers, including
@@ -608,16 +611,29 @@
 	struct usb_request	*req
 )
 {
-	int i;
+	unsigned	i;
+	u8		*buf = req->buf;
 
-	for (i = 0; i < req->actual; i++) {
-		if (((u8 *)req->buf) [i] != 0) {
-			ERROR (dev, "nonzero OUT byte from host, "
-					"buf [%d] = %d\n",
-					i, ((u8 *)req->buf) [i]);
-			usb_ep_set_halt (ep);
-			return -EINVAL;
+	for (i = 0; i < req->actual; i++, buf++) {
+		switch (pattern) {
+		/* all-zeroes has no synchronization issues */
+		case 0:
+			if (*buf == 0)
+				continue;
+			break;
+		/* mod63 stays in sync with short-terminated transfers,
+		 * or otherwise when host and gadget agree on how large
+		 * each usb transfer request should be.  resync is done
+		 * with set_interface or set_config.
+		 */
+		case 1:
+			if (*buf == (u8)(i % 63))
+				continue;
+			break;
 		}
+		ERROR (dev, "bad OUT byte, buf [%d] = %d\n", i, *buf);
+		usb_ep_set_halt (ep);
+		return -EINVAL;
 	}
 	return 0;
 }
@@ -629,7 +645,18 @@
 	struct usb_request	*req
 )
 {
-	memset (req->buf, 0, req->length);
+	unsigned	i;
+	u8		*buf = req->buf;
+
+	switch (pattern) {
+	case 0:
+		memset (req->buf, 0, req->length);
+		break;
+	case 1:
+		for  (i = 0; i < req->length; i++)
+			*buf++ = (u8) (i % 63);
+		break;
+	}
 }
 
 /* if there is only one request in the queue, there'll always be an
@@ -651,10 +678,13 @@
 		break;
 
 	/* this endpoint is normally active while we're configured */
+	case -ECONNABORTED: 		/* hardware forced ep reset */
 	case -ECONNRESET:		/* request dequeued */
 	case -ESHUTDOWN:		/* disconnect from host */
 		VDEBUG (dev, "%s gone (%d), %d/%d\n", ep->name, status,
 				req->actual, req->length);
+		if (ep == dev->out_ep)
+			check_read_data (dev, ep, req);
 		free_ep_req (ep, req);
 		return;
 
@@ -693,6 +723,9 @@
 	memset (req->buf, 0, req->length);
 	req->complete = source_sink_complete;
 
+	if (strcmp (ep->name, EP_IN_NAME) == 0)
+		reinit_write_data (ep->driver_data, ep, req);
+
 	status = usb_ep_queue (ep, req, gfp_flags);
 	if (status) {
 		struct zero_dev	*dev = ep->driver_data;
@@ -801,6 +834,8 @@
 	 * rely on the hardware driver to clean up on disconnect or
 	 * endpoint disable.
 	 */
+	case -ECONNABORTED: 		/* hardware forced ep reset */
+	case -ECONNRESET:		/* request dequeued */
 	case -ESHUTDOWN:		/* disconnect from host */
 		free_ep_req (ep, req);
 		return;
@@ -905,7 +940,7 @@
  *
  * note that some device controller hardware will constrain what this
  * code can do, perhaps by disallowing more than one configuration or
- * by limiting configuration choices (like the pxa250).
+ * by limiting configuration choices (like the pxa2xx).
  */
 static int
 zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags)
@@ -1046,7 +1081,8 @@
 		break;
 
 	/* until we add altsetting support, or other interfaces,
-	 * only 0/0 are possible.
+	 * only 0/0 are possible.  pxa2xx only supports 0/0 (poorly)
+	 * and already killed pending endpoint I/O.
 	 */
 	case USB_REQ_SET_INTERFACE:
 		if (ctrl->bRequestType != USB_RECIP_INTERFACE)
diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
--- a/drivers/usb/host/ohci-hcd.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/usb/host/ohci-hcd.c	Sat Jul 19 12:54:22 2003
@@ -319,6 +319,7 @@
 	int			epnum = ep & USB_ENDPOINT_NUMBER_MASK;
 	unsigned long		flags;
 	struct ed		*ed;
+	unsigned		limit = 1000;
 
 	/* ASSERT:  any requests/urbs are being unlinked */
 	/* ASSERT:  nobody can be submitting urbs for this any more */
@@ -337,6 +338,8 @@
 		ed->state = ED_IDLE;
 	switch (ed->state) {
 	case ED_UNLINK:		/* wait for hw to finish? */
+		/* major IRQ delivery trouble loses INTR_SF too... */
+		WARN_ON (limit-- == 0);
 		spin_unlock_irqrestore (&ohci->lock, flags);
 		set_current_state (TASK_UNINTERRUPTIBLE);
 		schedule_timeout (1);
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- a/drivers/usb/host/ohci-q.c	Sat Jul 19 12:54:29 2003
+++ b/drivers/usb/host/ohci-q.c	Sat Jul 19 12:54:29 2003
@@ -43,6 +43,16 @@
 	spin_lock (&urb->lock);
 	if (likely (urb->status == -EINPROGRESS))
 		urb->status = 0;
+	/* report short control reads right even though the data TD always
+	 * has TD_R set.  (much simpler, but creates the 1-td limit.)
+	 */
+	if (unlikely (urb->transfer_flags & URB_SHORT_NOT_OK)
+			&& unlikely (usb_pipecontrol (urb->pipe))
+			&& urb->actual_length < urb->transfer_buffer_length
+			&& usb_pipein (urb->pipe)
+			&& urb->status == 0) {
+		urb->status = -EREMOTEIO;
+	}
 	spin_unlock (&urb->lock);
 
 	// what lock protects these?
diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
--- a/drivers/usb/host/uhci-hcd.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/usb/host/uhci-hcd.c	Sat Jul 19 12:54:27 2003
@@ -2007,19 +2007,17 @@
 	unsigned int io_addr = uhci->io_addr;
 	int i;
 
-	if (!uhci->hcd.pdev ||
-	     uhci->hcd.pdev->vendor != PCI_VENDOR_ID_INTEL ||
-	     uhci->hcd.pdev->device != PCI_DEVICE_ID_INTEL_82371AB_2)
+	if (!uhci->hcd.pdev || uhci->hcd.pdev->vendor != PCI_VENDOR_ID_INTEL)
 		return 1;
 
-	/* This is a 82371AB/EB/MB USB controller which has a bug that
-	 * causes false resume indications if any port has an
-	 * over current condition.  To prevent problems, we will not
-	 * allow a global suspend if any ports are OC.
+	/* Some of Intel's USB controllers have a bug that causes false
+	 * resume indications if any port has an over current condition.
+	 * To prevent problems, we will not allow a global suspend if
+	 * any ports are OC.
 	 *
-	 * Some motherboards using the 82371AB/EB/MB (but not the USB portion)
-	 * appear to hardwire the over current inputs active to disable
-	 * the USB ports.
+	 * Some motherboards using Intel's chipsets (but not using all
+	 * the USB ports) appear to hardwire the over current inputs active
+	 * to disable the USB ports.
 	 */
 
 	/* check for over current condition on any port */
diff -Nru a/drivers/usb/image/hpusbscsi.c b/drivers/usb/image/hpusbscsi.c
--- a/drivers/usb/image/hpusbscsi.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/usb/image/hpusbscsi.c	Sat Jul 19 12:54:30 2003
@@ -9,7 +9,7 @@
 #include <linux/smp_lock.h>
 #include <linux/usb.h>
 #include <asm/atomic.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include "../../scsi/scsi.h"
 #include "../../scsi/hosts.h"
 
@@ -109,7 +109,8 @@
 		goto out_unlink_controlurb;
 
 	new->host->hostdata[0] = (unsigned long)new;
-	scsi_add_host(new->host, &intf->dev);
+	scsi_add_host(new->host, &intf->dev); /* XXX handle failure */
+	scsi_scan_host(new->host);
 
 	new->sense_command[0] = REQUEST_SENSE;
 	new->sense_command[4] = HPUSBSCSI_SENSE_LENGTH;
@@ -306,7 +307,10 @@
 	if(unlikely(u->status < 0)) {
                 if (likely(hpusbscsi->state != HP_STATE_FREE))
                         handle_usb_error(hpusbscsi);
-		return;
+		if (u->status == -ECONNRESET || u->status == -ENOENT || u->status == -ESHUTDOWN)
+			return;
+		else
+			goto resub;
 	}
 
 	scsi_state = hpusbscsi->scsi_state_byte;
@@ -348,6 +352,8 @@
 	TRACE_STATE;
 		break;
 	}
+resub:
+	usb_submit_urb(u, GFP_ATOMIC);
 }
 
 static void simple_command_callback(struct urb *u, struct pt_regs *regs)
@@ -427,7 +433,7 @@
 				hpusbscsi->state = HP_STATE_WAIT;
 			} else {
 				issue_request_sense(hpusbscsi);
-			}			
+			}
 		}
 	} else {
 		if (likely(hpusbscsi->scallback != NULL))
diff -Nru a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
--- a/drivers/usb/image/microtek.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/usb/image/microtek.c	Sat Jul 19 12:54:30 2003
@@ -134,7 +134,7 @@
 #include <linux/proc_fs.h>
 
 #include <asm/atomic.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include "../../scsi/scsi.h"
 #include "../../scsi/hosts.h"
 
@@ -817,7 +817,8 @@
 		goto out_free_urb;
 
 	new_desc->host->hostdata[0] = (unsigned long)new_desc;
-	scsi_add_host(new_desc->host, NULL);
+	scsi_add_host(new_desc->host, NULL); /* XXX handle failure */
+	scsi_scan_host(new_desc->host);
 
 	usb_set_intfdata(intf, new_desc);
 	return 0;
diff -Nru a/drivers/usb/image/scanner.c b/drivers/usb/image/scanner.c
--- a/drivers/usb/image/scanner.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/usb/image/scanner.c	Sat Jul 19 12:54:24 2003
@@ -364,6 +364,11 @@
  *      Mustek, Pacific Image Electronics, Plustek, and Visioneer scanners.
  *      Fixed names of some other scanners.
  *
+ * 0.4.14  2003-07-15
+ *    - Fixed race between open and probe (Oliver Neukum).
+ *    - Added vendor/product ids for Avision, Canon, HP, Microtek and Relisys scanners.
+ *    - Clean up irq urb when not enough memory is available.
+ *
  * TODO
  *    - Performance
  *    - Select/poll methods
@@ -1068,6 +1073,9 @@
 /* Ok, now initialize all the relevant values */
 	if (!(scn->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) {
 		err("probe_scanner(%d): Not enough memory for the output buffer.", intf->minor);
+		if (have_intr)
+			usb_unlink_urb(scn->scn_irq);
+		usb_free_urb(scn->scn_irq);
 		kfree(scn);
 		up(&scn_mutex);
 		return -ENOMEM;
@@ -1076,6 +1084,9 @@
 
 	if (!(scn->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) {
 		err("probe_scanner(%d): Not enough memory for the input buffer.", intf->minor);
+		if (have_intr)
+			usb_unlink_urb(scn->scn_irq);
+		usb_free_urb(scn->scn_irq);
 		kfree(scn->obuf);
 		kfree(scn);
 		up(&scn_mutex);
@@ -1117,10 +1128,9 @@
 	info ("USB scanner device (0x%04x/0x%04x) now attached to %s",
 	      dev->descriptor.idVendor, dev->descriptor.idProduct, name);
 
-	up(&scn_mutex);
-
 	usb_set_intfdata(intf, scn);
-
+	up(&scn_mutex);
+	
 	return 0;
 }
 
diff -Nru a/drivers/usb/image/scanner.h b/drivers/usb/image/scanner.h
--- a/drivers/usb/image/scanner.h	Sat Jul 19 12:54:24 2003
+++ b/drivers/usb/image/scanner.h	Sat Jul 19 12:54:24 2003
@@ -43,7 +43,7 @@
 
 // #define DEBUG
 
-#define DRIVER_VERSION "0.4.13"
+#define DRIVER_VERSION "0.4.14"
 #define DRIVER_DESC "USB Scanner Driver"
 
 #include <linux/usb.h>
@@ -103,6 +103,7 @@
 	/* Avision */
 	{ USB_DEVICE(0x0638, 0x0268) }, /* iVina 1200U */
 	{ USB_DEVICE(0x0638, 0x0a10) },	/* iVina FB1600 (=Umax Astra 4500) */
+	{ USB_DEVICE(0x0638, 0x0a20) }, /* iVina FB1800 (=Umax Astra 4700) */
 	/* Benq: see Acer */
 	/* Brother */
 	{ USB_DEVICE(0x04f9, 0x010f) },	/* MFC 5100C */
@@ -115,10 +116,12 @@
 	{ USB_DEVICE(0x04a9, 0x2206) }, /* CanoScan N650U/N656U */
 	{ USB_DEVICE(0x04a9, 0x2207) }, /* CanoScan N1220U */
 	{ USB_DEVICE(0x04a9, 0x2208) }, /* CanoScan D660U */ 
+	{ USB_DEVICE(0x04a9, 0x220a) },	/* CanoScan D2400UF */
 	{ USB_DEVICE(0x04a9, 0x220b) }, /* CanoScan D646U */
 	{ USB_DEVICE(0x04a9, 0x220c) },	/* CanoScan D1250U2 */
 	{ USB_DEVICE(0x04a9, 0x220d) }, /* CanoScan N670U/N676U/LIDE 20 */
 	{ USB_DEVICE(0x04a9, 0x220e) }, /* CanoScan N1240U/LIDE 30 */
+	{ USB_DEVICE(0x04a9, 0x220f) },	/* CanoScan 8000F */
 	{ USB_DEVICE(0x04a9, 0x2213) },	/* LIDE 50 */
 	{ USB_DEVICE(0x04a9, 0x3042) }, /* FS4000US */
 	/* Colorado -- See Primax/Colorado below */
@@ -158,6 +161,7 @@
 	{ USB_DEVICE(0x03f0, 0x0901) }, /* ScanJet 2300C */
 	{ USB_DEVICE(0x03F0, 0x1005) },	/* ScanJet 5400C */
 	{ USB_DEVICE(0x03F0, 0x1105) },	/* ScanJet 5470C */
+	{ USB_DEVICE(0x03f0, 0x1205) }, /* ScanJet 5550C */
 	{ USB_DEVICE(0x03f0, 0x1305) },	/* Scanjet 4570c */
 	{ USB_DEVICE(0x03f0, 0x1411) }, /* PSC 750 */
 	{ USB_DEVICE(0x03f0, 0x2005) },	/* ScanJet 3570c */
@@ -173,6 +177,7 @@
 	/* Memorex */
 	{ USB_DEVICE(0x0461, 0x0346) }, /* 6136u - repackaged Primax ? */
 	/* Microtek */
+	{ USB_DEVICE(0x05da, 0x20c9) }, /* ScanMaker 6700 */
 	{ USB_DEVICE(0x05da, 0x30ce) },	/* ScanMaker 3800 */
 	{ USB_DEVICE(0x05da, 0x30cf) },	/* ScanMaker 4800 */
 	{ USB_DEVICE(0x04a7, 0x0224) },	/* Scanport 3000 (actually Visioneer?)*/
@@ -250,6 +255,7 @@
 	{ USB_DEVICE(0x06dc, 0x0014) }, /* Winscan Pro 2448U */
 	/* Relisis */
 	// { USB_DEVICE(0x0475, 0x0103) },	/* Episode - undetected endpoint */
+	{ USB_DEVICE(0x0475, 0x0210) }, /* Scorpio Ultra 3 */
 	/* Seiko/Epson Corp. */
 	{ USB_DEVICE(0x04b8, 0x0101) },	/* Perfection 636U and 636Photo */
 	{ USB_DEVICE(0x04b8, 0x0102) }, /* GT-2200 */
diff -Nru a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c
--- a/drivers/usb/media/dabusb.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/usb/media/dabusb.c	Sat Jul 19 12:54:25 2003
@@ -721,7 +721,7 @@
 
 
 /* --------------------------------------------------------------------- */
-static int dabusb_probe (struct usb_interface *intf, 
+static int dabusb_probe (struct usb_interface *intf,
 			 const struct usb_device_id *id)
 {
 	struct usb_device *usbdev = interface_to_usbdev(intf);
@@ -738,9 +738,7 @@
 	if (intf->altsetting->desc.bInterfaceNumber != _DABUSB_IF && usbdev->descriptor.idProduct == 0x9999)
 		return -ENODEV;
 
-	retval = usb_register_dev(intf, &dabusb_class);
-	if (retval)
-		return -ENOMEM;
+
 
 	s = &dabusb[intf->minor];
 
@@ -766,8 +764,15 @@
 		}
 	}
 	dbg("bound to interface: %d", ifnum);
-	up (&s->mutex);
 	usb_set_intfdata (intf, s);
+	up (&s->mutex);
+
+	retval = usb_register_dev(intf, &dabusb_class);
+	if (retval) {
+		usb_set_intfdata (intf, NULL);
+		return -ENOMEM;
+	}
+
 	return 0;
 
       reject:
diff -Nru a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
--- a/drivers/usb/misc/usblcd.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/usb/misc/usblcd.c	Sat Jul 19 12:54:21 2003
@@ -1,4 +1,4 @@
-/***************************************************************************** 
+/*****************************************************************************
  *                          USBLCD Kernel Driver                             *
  *        See http://www.usblcd.de for Hardware and Documentation.           *
  *                            Version 1.03                                   *
@@ -18,7 +18,7 @@
 #include <asm/uaccess.h>
 #include <linux/usb.h>
 
-#define DRIVER_VERSION "USBLCD Driver Version 1.03"
+#define DRIVER_VERSION "USBLCD Driver Version 1.04"
 
 #define USBLCD_MINOR		144
 
@@ -257,7 +257,7 @@
 	struct lcd_usb_data *lcd = &lcd_instance;
 	int i;
 	int retval;
-	
+
 	if (dev->descriptor.idProduct != 0x0001  ) {
 		warn(KERN_INFO "USBLCD model not supported.");
 		return -ENODEV;
@@ -274,29 +274,31 @@
 		(i & 0xF000)>>12,(i & 0xF00)>>8,(i & 0xF0)>>4,(i & 0xF),
 		dev->devnum);
 
-	retval = usb_register_dev(intf, &usb_lcd_class);
-	if (retval) {
-		err("Not able to get a minor for this device.");
-		return -ENOMEM;
-	}
+
 
 	lcd->present = 1;
 	lcd->lcd_dev = dev;
 
 	if (!(lcd->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) {
 		err("probe_lcd: Not enough memory for the output buffer");
-		usb_deregister_dev(intf, &usb_lcd_class);
 		return -ENOMEM;
 	}
 	dbg("probe_lcd: obuf address:%p", lcd->obuf);
 
 	if (!(lcd->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) {
 		err("probe_lcd: Not enough memory for the input buffer");
-		usb_deregister_dev(intf, &usb_lcd_class);
 		kfree(lcd->obuf);
 		return -ENOMEM;
 	}
 	dbg("probe_lcd: ibuf address:%p", lcd->ibuf);
+
+	retval = usb_register_dev(intf, &usb_lcd_class);
+	if (retval) {
+		err("Not able to get a minor for this device.");
+		kfree(lcd->obuf);
+		kfree(lcd->ibuf);
+		return -ENOMEM;
+	}
 
 	usb_set_intfdata (intf, lcd);
 	return 0;
diff -Nru a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
--- a/drivers/usb/misc/usbtest.c	Sat Jul 19 12:54:29 2003
+++ b/drivers/usb/misc/usbtest.c	Sat Jul 19 12:54:29 2003
@@ -47,6 +47,7 @@
 	const char		*name;
 	u8			ep_in;		/* bulk/intr source */
 	u8			ep_out;		/* bulk/intr sink */
+	unsigned		autoconf : 1;
 	int			alt;
 };
 
@@ -78,6 +79,61 @@
 
 /*-------------------------------------------------------------------------*/
 
+static int
+get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf)
+{
+	int				tmp;
+	struct usb_host_interface	*alt;
+	struct usb_host_endpoint	*in, *out;
+	struct usb_device		*udev;
+
+	for (tmp = 0; tmp < intf->max_altsetting; tmp++) {
+		unsigned	ep;
+
+		in = out = 0;
+		alt = intf->altsetting + tmp;
+
+		/* take the first altsetting with in-bulk + out-bulk;
+		 * ignore other endpoints and altsetttings.
+		 */
+		for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) {
+			struct usb_host_endpoint	*e;
+
+			e = alt->endpoint + ep;
+			if (e->desc.bmAttributes != USB_ENDPOINT_XFER_BULK)
+				continue;
+			if (e->desc.bEndpointAddress & USB_DIR_IN) {
+				if (!in)
+					in = e;
+			} else {
+				if (!out)
+					out = e;
+			}
+			if (in && out)
+				goto found;
+		}
+	}
+	return -EINVAL;
+
+found:
+	udev = testdev_to_usbdev (dev);
+	if (alt->desc.bAlternateSetting != 0) {
+		tmp = usb_set_interface (udev,
+				alt->desc.bInterfaceNumber,
+				alt->desc.bAlternateSetting);
+		if (tmp < 0)
+			return tmp;
+	}
+
+	dev->in_pipe = usb_rcvbulkpipe (udev,
+			in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+	dev->out_pipe = usb_sndbulkpipe (udev,
+			out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
 /* Support for testing basic non-queued I/O streams.
  *
  * These just package urbs as requests that can be easily canceled.
@@ -1275,14 +1331,26 @@
 			wtest = " intr-out";
 		}
 	} else {
-		if (info->ep_in) {
-			dev->in_pipe = usb_rcvbulkpipe (udev, info->ep_in);
-			rtest = " bulk-in";
+		if (info->autoconf) {
+			int status;
+
+			status = get_endpoints (dev, intf);
+			if (status < 0) {
+				dbg ("couldn't get endpoints, %d\n", status);
+				return status;
+			}
+		} else {
+			if (info->ep_in)
+				dev->in_pipe = usb_rcvbulkpipe (udev,
+							info->ep_in);
+			if (info->ep_out)
+				dev->out_pipe = usb_sndbulkpipe (udev,
+							info->ep_out);
 		}
-		if (info->ep_out) {
-			dev->out_pipe = usb_sndbulkpipe (udev, info->ep_out);
+		if (dev->in_pipe)
+			rtest = " bulk-in";
+		if (dev->out_pipe)
 			wtest = " bulk-out";
-		}
 	}
 
 	usb_set_intfdata (intf, dev);
@@ -1336,11 +1404,6 @@
 };
 
 /* ezusb family device with dedicated usb test firmware,
- * or a peripheral running Linux and 'zero.c' test firmware.
- *
- * FIXME usbtest should read the descriptors, since compatible
- * test firmware might run on hardware (pxa250 for one) that
- * can't configure an ep2in-bulk.
  */
 static struct usbtest_info fw_info = {
 	.name		= "usb test device",
@@ -1349,10 +1412,20 @@
 	.alt		= 0,
 };
 
+/* peripheral running Linux and 'zero.c' test firmware, or
+ * its user-mode cousin. different versions of this use
+ * different hardware with the same vendor/product codes.
+ * host side MUST rely on the endpoint descriptors.
+ */
+static struct usbtest_info gz_info = {
+	.name		= "Linux gadget zero",
+	.autoconf	= 1,
+	.alt		= 0,
+};
+
 static struct usbtest_info um_info = {
-	.name		= "user mode test driver",
-	.ep_in		= 7,
-	.ep_out		= 3,
+	.name		= "Linux user mode test driver",
+	.autoconf	= 1,
 	.alt		= -1,
 };
 
@@ -1418,7 +1491,7 @@
 
 	/* "Gadget Zero" firmware runs under Linux */
 	{ USB_DEVICE (0x0525, 0xa4a0),
-		.driver_info = (unsigned long) &fw_info,
+		.driver_info = (unsigned long) &gz_info,
 		},
 
 	/* so does a user-mode variant */
diff -Nru a/drivers/usb/net/ax8817x.c b/drivers/usb/net/ax8817x.c
--- a/drivers/usb/net/ax8817x.c	Sat Jul 19 12:54:23 2003
+++ b/drivers/usb/net/ax8817x.c	Sat Jul 19 12:54:23 2003
@@ -1208,6 +1208,7 @@
 	net->init = ax8817x_net_init;
 	net->priv = ax_info;
 
+	SET_NETDEV_DEV(net, &intf->dev);
 	ret = register_netdev(net);
 	if (ret < 0) {
 		err("%s: Failed net init (%d)\n", __FUNCTION__, ret);
diff -Nru a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
--- a/drivers/usb/net/catc.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/usb/net/catc.c	Sat Jul 19 12:54:25 2003
@@ -936,6 +936,7 @@
 	printk("%2.2x.\n", netdev->dev_addr[i]);
 	usb_set_intfdata(intf, catc);
 
+	SET_NETDEV_DEV(netdev, &intf->dev);
 	if (register_netdev(netdev) != 0) {
 		usb_set_intfdata(intf, NULL);
 		usb_free_urb(catc->ctrl_urb);
diff -Nru a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
--- a/drivers/usb/net/kaweth.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/usb/net/kaweth.c	Sat Jul 19 12:54:26 2003
@@ -1123,8 +1123,9 @@
 	if (dma_supported (&intf->dev, 0xffffffffffffffffULL))
 		kaweth->net->features |= NETIF_F_HIGHDMA;
 
+	SET_NETDEV_DEV(netdev, &intf->dev);
 	if (register_netdev(netdev) != 0) {
-		kaweth_err("Error calling init_etherdev.");
+		kaweth_err("Error registering netdev.");
 		goto err_intfdata;
 	}
 
diff -Nru a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
--- a/drivers/usb/net/pegasus.c	Sat Jul 19 12:54:30 2003
+++ b/drivers/usb/net/pegasus.c	Sat Jul 19 12:54:30 2003
@@ -1262,7 +1262,6 @@
 	}
 	set_ethernet_addr(pegasus);
 	fill_skb_pool(pegasus);
-	printk("%s: %s\n", net->name, usb_dev_id[dev_index].name);
 	if (pegasus->features & PEGASUS_II) {
 		info("setup Pegasus II specific registers");
 		setup_pegasus_II(pegasus);
@@ -1273,9 +1272,11 @@
 		pegasus->phy = 1;
 	}
 	usb_set_intfdata(intf, pegasus);
+	SET_NETDEV_DEV(net, &intf->dev);
 	res = register_netdev(net);
 	if (res)
 		goto out4;
+	printk("%s: %s\n", net->name, usb_dev_id[dev_index].name);
 	return 0;
 
 out4:
diff -Nru a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
--- a/drivers/usb/net/rtl8150.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/usb/net/rtl8150.c	Sat Jul 19 12:54:25 2003
@@ -830,6 +830,7 @@
 	
 	usb_set_intfdata(intf, dev);
 
+	SET_NETDEV_DEV(netdev, &intf->dev);
 	if (register_netdev(netdev) != 0) {
 		err("couldn't register the device");
 		goto out2;
diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
--- a/drivers/usb/net/usbnet.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/usb/net/usbnet.c	Sat Jul 19 12:54:25 2003
@@ -2602,7 +2602,7 @@
 
 	dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
 	
-	SET_NETDEV_DEV(dev->net, &dev->udev->dev);
+	SET_NETDEV_DEV(dev->net, &udev->dev);
 	status = register_netdev (dev->net);
 	if (status)
 		goto out3;
diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
--- a/drivers/usb/serial/ftdi_sio.c	Sat Jul 19 12:54:26 2003
+++ b/drivers/usb/serial/ftdi_sio.c	Sat Jul 19 12:54:26 2003
@@ -257,6 +257,7 @@
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_DSS20_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID, 0, 0x3ff) },
@@ -321,6 +322,7 @@
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_DSS20_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID, 0x400, 0xffff) },
@@ -396,6 +398,7 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_DSS20_PID) },
 	{ USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) },
 	{ USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID) },
diff -Nru a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
--- a/drivers/usb/serial/ftdi_sio.h	Sat Jul 19 12:54:27 2003
+++ b/drivers/usb/serial/ftdi_sio.h	Sat Jul 19 12:54:27 2003
@@ -105,7 +105,13 @@
 #define SEALEVEL_2803_6_PID	0X2863 	/* SeaLINK+8 (2803) Port 6 */
 #define SEALEVEL_2803_7_PID	0X2873 	/* SeaLINK+8 (2803) Port 7 */
 #define SEALEVEL_2803_8_PID	0X2883 	/* SeaLINK+8 (2803) Port 8 */
+
+/*
+ * DSS-20 Sync Station for Sony Ericsson P800
+ */
  
+#define FTDI_DSS20_PID          0xFC82  
+
 /*
  * Home Electronics (www.home-electro.com) USB gadgets
  */
diff -Nru a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
--- a/drivers/usb/serial/ipaq.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/usb/serial/ipaq.c	Sat Jul 19 12:54:27 2003
@@ -125,10 +125,13 @@
 	{ USB_DEVICE(LINKUP_VENDOR_ID, LINKUP_PRODUCT_ID) },
 	{ USB_DEVICE(MICROSOFT_VENDOR_ID, MICROSOFT_00CE_ID) },
 	{ USB_DEVICE(PORTATEC_VENDOR_ID, PORTATEC_PRODUCT_ID) },
+	{ USB_DEVICE(ROVER_VENDOR_ID, ROVER_P5_ID) },
 	{ USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_WIRELESS_ID) },
 	{ USB_DEVICE(SOCKET_VENDOR_ID, SOCKET_PRODUCT_ID) },
 	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_ID) },
+	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E310_ID) },
 	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E740_ID) },
+	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E335_ID) },
 	{ USB_DEVICE(HTC_VENDOR_ID, HTC_PRODUCT_ID) },
 	{ USB_DEVICE(NEC_VENDOR_ID, NEC_PRODUCT_ID) },
 	{ USB_DEVICE(ASUS_VENDOR_ID, ASUS_A600_PRODUCT_ID) },
diff -Nru a/drivers/usb/serial/ipaq.h b/drivers/usb/serial/ipaq.h
--- a/drivers/usb/serial/ipaq.h	Sat Jul 19 12:54:21 2003
+++ b/drivers/usb/serial/ipaq.h	Sat Jul 19 12:54:21 2003
@@ -61,6 +61,9 @@
 #define PORTATEC_VENDOR_ID	0x0961
 #define PORTATEC_PRODUCT_ID	0x0010
 
+#define ROVER_VENDOR_ID		0x047b
+#define ROVER_P5_ID		0x3000
+
 #define SAGEM_VENDOR_ID		0x5e04
 #define SAGEM_WIRELESS_ID	0xce00
 
@@ -69,7 +72,9 @@
 
 #define TOSHIBA_VENDOR_ID	0x0930
 #define TOSHIBA_PRODUCT_ID	0x0700
+#define TOSHIBA_E310_ID		0x0705
 #define TOSHIBA_E740_ID		0x0706
+#define TOSHIBA_E335_ID		0x0707
 
 #define HTC_VENDOR_ID		0x0bb4
 #define HTC_PRODUCT_ID		0x00ce
diff -Nru a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
--- a/drivers/usb/serial/usb-serial.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/usb/serial/usb-serial.c	Sat Jul 19 12:54:24 2003
@@ -530,7 +530,9 @@
 	/* if disconnect beat us to the punch here, there's nothing to do */
 	if (tty && tty->driver_data) {
 		__serial_close(port, filp);
+		tty->driver_data = NULL;
 	}
+	port->tty = NULL;
 }
 
 static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
--- a/drivers/usb/serial/visor.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/usb/serial/visor.c	Sat Jul 19 12:54:24 2003
@@ -509,18 +509,17 @@
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 
+	/* free up the transfer buffer, as usb_free_urb() does not do this */
+	kfree (urb->transfer_buffer);
+
 	if (port_paranoia_check (port, __FUNCTION__))
 		return;
 	
 	dbg("%s - port %d", __FUNCTION__, port->number);
 	
-	if (urb->status) {
-		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
-		return;
-	}
-
-	/* free up the transfer buffer, as usb_free_urb() does not do this */
-	kfree (urb->transfer_buffer);
+	if (urb->status)
+		dbg("%s - nonzero write bulk status received: %d",
+		    __FUNCTION__, urb->status);
 
 	schedule_work(&port->work);
 }
diff -Nru a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h
--- a/drivers/usb/storage/debug.h	Sat Jul 19 12:54:30 2003
+++ b/drivers/usb/storage/debug.h	Sat Jul 19 12:54:30 2003
@@ -46,7 +46,6 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/blk.h>
 #include <linux/cdrom.h>
 #include "usb.h"
 
diff -Nru a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
--- a/drivers/usb/storage/isd200.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/usb/storage/isd200.c	Sat Jul 19 12:54:25 2003
@@ -280,6 +280,7 @@
 
 	/* maximum number of LUNs supported */
 	unsigned char MaxLUNs;
+	struct scsi_cmnd srb;
 };
 
 
@@ -404,15 +405,15 @@
 			  void* pointer, int value )
 {
 	union ata_cdb ata;
-	struct scsi_cmnd srb;
 	struct scsi_device srb_dev;
 	struct isd200_info *info = (struct isd200_info *)us->extra;
+	struct scsi_cmnd *srb = &info->srb;
 	int status;
 
 	memset(&ata, 0, sizeof(ata));
-	memset(&srb, 0, sizeof(srb));
 	memset(&srb_dev, 0, sizeof(srb_dev));
-	srb.device = &srb_dev;
+	srb->device = &srb_dev;
+	++srb->serial_number;
 
 	ata.generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
 	ata.generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
@@ -425,9 +426,9 @@
 		ata.generic.RegisterSelect =
 		  REG_CYLINDER_LOW | REG_CYLINDER_HIGH |
 		  REG_STATUS | REG_ERROR;
-		srb.sc_data_direction = SCSI_DATA_READ;
-		srb.request_buffer = pointer;
-		srb.request_bufflen = value;
+		srb->sc_data_direction = SCSI_DATA_READ;
+		srb->request_buffer = pointer;
+		srb->request_bufflen = value;
 		break;
 
 	case ACTION_ENUM:
@@ -437,7 +438,7 @@
 					   ACTION_SELECT_5;
 		ata.generic.RegisterSelect = REG_DEVICE_HEAD;
 		ata.write.DeviceHeadByte = value;
-		srb.sc_data_direction = SCSI_DATA_NONE;
+		srb->sc_data_direction = SCSI_DATA_NONE;
 		break;
 
 	case ACTION_RESET:
@@ -446,7 +447,7 @@
 					   ACTION_SELECT_3|ACTION_SELECT_4;
 		ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
 		ata.write.DeviceControlByte = ATA_DC_RESET_CONTROLLER;
-		srb.sc_data_direction = SCSI_DATA_NONE;
+		srb->sc_data_direction = SCSI_DATA_NONE;
 		break;
 
 	case ACTION_REENABLE:
@@ -455,7 +456,7 @@
 					   ACTION_SELECT_3|ACTION_SELECT_4;
 		ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
 		ata.write.DeviceControlByte = ATA_DC_REENABLE_CONTROLLER;
-		srb.sc_data_direction = SCSI_DATA_NONE;
+		srb->sc_data_direction = SCSI_DATA_NONE;
 		break;
 
 	case ACTION_SOFT_RESET:
@@ -464,16 +465,16 @@
 		ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND;
 		ata.write.DeviceHeadByte = info->DeviceHead;
 		ata.write.CommandByte = WIN_SRST;
-		srb.sc_data_direction = SCSI_DATA_NONE;
+		srb->sc_data_direction = SCSI_DATA_NONE;
 		break;
 
 	case ACTION_IDENTIFY:
 		US_DEBUGP("   isd200_action(IDENTIFY)\n");
 		ata.generic.RegisterSelect = REG_COMMAND;
 		ata.write.CommandByte = WIN_IDENTIFY;
-		srb.sc_data_direction = SCSI_DATA_READ;
-		srb.request_buffer = (void *)&info->drive;
-		srb.request_bufflen = sizeof(struct hd_driveid);
+		srb->sc_data_direction = SCSI_DATA_READ;
+		srb->request_buffer = (void *)&info->drive;
+		srb->request_bufflen = sizeof(struct hd_driveid);
 		break;
 
 	default:
@@ -481,9 +482,9 @@
 		break;
 	}
 
-	memcpy(srb.cmnd, &ata, sizeof(ata.generic));
-	srb.cmd_len = sizeof(ata.generic);
-	status = usb_stor_Bulk_transport(&srb, us);
+	memcpy(srb->cmnd, &ata, sizeof(ata.generic));
+	srb->cmd_len = sizeof(ata.generic);
+	status = usb_stor_Bulk_transport(srb, us);
 	if (status == USB_STOR_TRANSPORT_GOOD)
 		status = ISD200_GOOD;
 	else {
@@ -834,7 +835,7 @@
 			   int detect )
 {
 	int status = ISD200_GOOD;
-	unsigned char regs[8];
+	unsigned char *regs = us->iobuf;
 	unsigned long endTime;
 	struct isd200_info *info = (struct isd200_info *)us->extra;
 	int recheckAsMaster = FALSE;
@@ -856,7 +857,7 @@
 			break;
 
 		status = isd200_action( us, ACTION_READ_STATUS, 
-					regs, sizeof(regs) );
+					regs, 8 );
 		if ( status != ISD200_GOOD )
 			break;
 
diff -Nru a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
--- a/drivers/usb/storage/jumpshot.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/usb/storage/jumpshot.c	Sat Jul 19 12:54:21 2003
@@ -86,7 +86,6 @@
 
 static int jumpshot_get_status(struct us_data  *us)
 {
-	unsigned char reply;
 	int rc;
 
 	if (!us)
@@ -94,14 +93,14 @@
 
 	// send the setup
 	rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
-				   0, 0xA0, 0, 7, &reply, 1);
+				   0, 0xA0, 0, 7, us->iobuf, 1);
 
 	if (rc != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
-	if (reply != 0x50) {
+	if (us->iobuf[0] != 0x50) {
 		US_DEBUGP("jumpshot_get_status:  0x%2x\n",
-			  (unsigned short) (reply));
+			  us->iobuf[0]);
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 
@@ -115,7 +114,7 @@
 			      unsigned char *dest, 
 			      int use_sg)
 {
-	unsigned char command[] = { 0, 0, 0, 0, 0, 0xe0, 0x20 };
+	unsigned char *command = us->iobuf;
 	unsigned char *buffer = NULL;
 	unsigned char *ptr;
 	unsigned char  thistime;
@@ -154,7 +153,8 @@
 		command[3] = (sector >>  8) & 0xFF;
 		command[4] = (sector >> 16) & 0xFF;
 
-		command[5] |= (sector >> 24) & 0x0F;
+		command[5] = 0xE0 | ((sector >> 24) & 0x0F);
+		command[6] = 0x20;
 
 		// send the setup + command
 		result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
@@ -199,7 +199,7 @@
 			       unsigned char *src, 
 			       int use_sg)
 {
-	unsigned char command[7] = { 0, 0, 0, 0, 0, 0xE0, 0x30 };
+	unsigned char *command = us->iobuf;
 	unsigned char *buffer = NULL;
 	unsigned char *ptr;
 	unsigned char  thistime;
@@ -240,7 +240,8 @@
 		command[3] = (sector >>  8) & 0xFF;
 		command[4] = (sector >> 16) & 0xFF;
 
-		command[5] |= (sector >> 24) & 0x0F;
+		command[5] = 0xE0 | ((sector >> 24) & 0x0F);
+		command[6] = 0x30;
 
 		// send the setup + command
 		result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
@@ -291,13 +292,19 @@
 static int jumpshot_id_device(struct us_data *us,
 			      struct jumpshot_info *info)
 {
-	unsigned char command[2] = { 0xe0, 0xec };
-	unsigned char reply[512];
+	unsigned char *command = us->iobuf;
+	unsigned char *reply;
 	int 	 rc;
 
 	if (!us || !info)
 		return USB_STOR_TRANSPORT_ERROR;
 
+	command[0] = 0xE0;
+	command[1] = 0xEC;
+	reply = kmalloc(512, GFP_NOIO);
+	if (!reply)
+		return USB_STOR_TRANSPORT_ERROR;
+
 	// send the setup
 	rc = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
 				   0, 0x20, 0, 6, command, 2);
@@ -305,20 +312,27 @@
 	if (rc != USB_STOR_XFER_GOOD) {
 		US_DEBUGP("jumpshot_id_device:  Gah! "
 			  "send_control for read_capacity failed\n");
-		return rc;
+		rc = USB_STOR_TRANSPORT_ERROR;
+		goto leave;
 	}
 
 	// read the reply
 	rc = jumpshot_bulk_read(us, reply, sizeof(reply));
-	if (rc != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
+	if (rc != USB_STOR_XFER_GOOD) {
+		rc = USB_STOR_TRANSPORT_ERROR;
+		goto leave;
+	}
 
 	info->sectors = ((u32)(reply[117]) << 24) |
 			((u32)(reply[116]) << 16) |
 			((u32)(reply[115]) <<  8) |
 			((u32)(reply[114])      );
 
-	return USB_STOR_TRANSPORT_GOOD;
+	rc = USB_STOR_TRANSPORT_GOOD;
+
+ leave:
+	kfree(reply);
+	return rc;
 }
 
 static int jumpshot_handle_mode_sense(struct us_data *us,
diff -Nru a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
--- a/drivers/usb/storage/protocol.c	Sat Jul 19 12:54:21 2003
+++ b/drivers/usb/storage/protocol.c	Sat Jul 19 12:54:21 2003
@@ -130,8 +130,9 @@
 void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us)
 {
 	/* Pad the ATAPI command with zeros 
+	 *
 	 * NOTE: This only works because a Scsi_Cmnd struct field contains
-	 * a unsigned char cmnd[12], so we know we have storage available
+	 * a unsigned char cmnd[16], so we know we have storage available
 	 */
 	for (; srb->cmd_len<12; srb->cmd_len++)
 		srb->cmnd[srb->cmd_len] = 0;
@@ -149,13 +150,10 @@
 
 void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
 {
-	int old_cmnd = 0;
-
-	/* Fix some commands -- this is a form of mode translation
-	 * ATAPI devices only accept 12 byte long commands 
+	/* Pad the ATAPI command with zeros 
 	 *
 	 * NOTE: This only works because a Scsi_Cmnd struct field contains
-	 * a unsigned char cmnd[12], so we know we have storage available
+	 * a unsigned char cmnd[16], so we know we have storage available
 	 */
 
 	/* Pad the ATAPI command with zeros */
@@ -165,60 +163,10 @@
 	/* set command length to 12 bytes */
 	srb->cmd_len = 12;
 
-	/* determine the correct (or minimum) data length for these commands */
-	switch (srb->cmnd[0]) {
-
-		/* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */
-	case MODE_SENSE:
-	case MODE_SELECT:
-		/* save the command so we can tell what it was */
-		old_cmnd = srb->cmnd[0];
-
-		srb->cmnd[11] = 0;
-		srb->cmnd[10] = 0;
-		srb->cmnd[9] = 0;
-		srb->cmnd[8] = srb->cmnd[4];
-		srb->cmnd[7] = 0;
-		srb->cmnd[6] = 0;
-		srb->cmnd[5] = 0;
-		srb->cmnd[4] = 0;
-		srb->cmnd[3] = 0;
-		srb->cmnd[2] = srb->cmnd[2];
-		srb->cmnd[1] = srb->cmnd[1];
-		srb->cmnd[0] = srb->cmnd[0] | 0x40;
-		break;
-
-		/* change READ_6/WRITE_6 to READ_10/WRITE_10, which 
-		 * are ATAPI commands */
-	case WRITE_6:
-	case READ_6:
-		srb->cmnd[11] = 0;
-		srb->cmnd[10] = 0;
-		srb->cmnd[9] = 0;
-		srb->cmnd[8] = srb->cmnd[4];
-		srb->cmnd[7] = 0;
-		srb->cmnd[6] = 0;
-		srb->cmnd[5] = srb->cmnd[3];
-		srb->cmnd[4] = srb->cmnd[2];
-		srb->cmnd[3] = srb->cmnd[1] & 0x1F;
-		srb->cmnd[2] = 0;
-		srb->cmnd[1] = srb->cmnd[1] & 0xE0;
-		srb->cmnd[0] = srb->cmnd[0] | 0x20;
-		break;
-	} /* end switch on cmnd[0] */
-
-	/* convert MODE_SELECT data here */
-	if (old_cmnd == MODE_SELECT)
-		usb_stor_scsiSense6to10(srb);
-
 	/* send the command to the transport layer */
 	usb_stor_invoke_transport(srb, us);
-	if (srb->result == SAM_STAT_GOOD) {
-
-		/* Fix the MODE_SENSE data if we translated the command */
-		if (old_cmnd == MODE_SENSE)
-			usb_stor_scsiSense10to6(srb);
 
+	if (srb->result == SAM_STAT_GOOD) {
 		/* fix the INQUIRY data if necessary */
 		fix_inquiry_data(srb);
 	}
@@ -227,19 +175,23 @@
 
 void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
 {
-	int old_cmnd = 0;
-
 	/* fix some commands -- this is a form of mode translation
 	 * UFI devices only accept 12 byte long commands 
 	 *
 	 * NOTE: This only works because a Scsi_Cmnd struct field contains
-	 * a unsigned char cmnd[12], so we know we have storage available
+	 * a unsigned char cmnd[16], so we know we have storage available
 	 */
 
+	/* Pad the ATAPI command with zeros */
+	for (; srb->cmd_len<12; srb->cmd_len++)
+		srb->cmnd[srb->cmd_len] = 0;
+
 	/* set command length to 12 bytes (this affects the transport layer) */
 	srb->cmd_len = 12;
 
-	/* determine the correct (or minimum) data length for these commands */
+	/* XXX We should be constantly re-evaluating the need for these */
+
+	/* determine the correct data length for these commands */
 	switch (srb->cmnd[0]) {
 
 		/* for INQUIRY, UFI devices only ever return 36 bytes */
@@ -247,33 +199,6 @@
 		srb->cmnd[4] = 36;
 		break;
 
-		/* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */
-	case MODE_SENSE:
-	case MODE_SELECT:
-		/* save the command so we can tell what it was */
-		old_cmnd = srb->cmnd[0];
-
-		srb->cmnd[11] = 0;
-		srb->cmnd[10] = 0;
-		srb->cmnd[9] = 0;
-
-		/* if we're sending data, we send all.	If getting data, 
-		 * get the minimum */
-		if (srb->cmnd[0] == MODE_SELECT)
-			srb->cmnd[8] = srb->cmnd[4];
-		else
-			srb->cmnd[8] = 8;
-
-		srb->cmnd[7] = 0;
-		srb->cmnd[6] = 0;
-		srb->cmnd[5] = 0;
-		srb->cmnd[4] = 0;
-		srb->cmnd[3] = 0;
-		srb->cmnd[2] = srb->cmnd[2];
-		srb->cmnd[1] = srb->cmnd[1];
-		srb->cmnd[0] = srb->cmnd[0] | 0x40;
-		break;
-
 		/* again, for MODE_SENSE_10, we get the minimum (8) */
 	case MODE_SENSE_10:
 		srb->cmnd[7] = 0;
@@ -284,38 +209,12 @@
 	case REQUEST_SENSE:
 		srb->cmnd[4] = 18;
 		break;
-
-		/* change READ_6/WRITE_6 to READ_10/WRITE_10, which 
-		 * are UFI commands */
-	case WRITE_6:
-	case READ_6:
-		srb->cmnd[11] = 0;
-		srb->cmnd[10] = 0;
-		srb->cmnd[9] = 0;
-		srb->cmnd[8] = srb->cmnd[4];
-		srb->cmnd[7] = 0;
-		srb->cmnd[6] = 0;
-		srb->cmnd[5] = srb->cmnd[3];
-		srb->cmnd[4] = srb->cmnd[2];
-		srb->cmnd[3] = srb->cmnd[1] & 0x1F;
-		srb->cmnd[2] = 0;
-		srb->cmnd[1] = srb->cmnd[1] & 0xE0;
-		srb->cmnd[0] = srb->cmnd[0] | 0x20;
-		break;
 	} /* end switch on cmnd[0] */
 
-	/* convert MODE_SELECT data here */
-	if (old_cmnd == MODE_SELECT)
-		usb_stor_scsiSense6to10(srb);
-
 	/* send the command to the transport layer */
 	usb_stor_invoke_transport(srb, us);
-	if (srb->result == SAM_STAT_GOOD) {
-
-		/* Fix the MODE_SENSE data if we translated the command */
-		if (old_cmnd == MODE_SENSE)
-			usb_stor_scsiSense10to6(srb);
 
+	if (srb->result == SAM_STAT_GOOD) {
 		/* Fix the data for an INQUIRY, if necessary */
 		fix_inquiry_data(srb);
 	}
@@ -323,68 +222,10 @@
 
 void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
 {
-	int old_cmnd = 0;
-
-	/* This code supports devices which do not support {READ|WRITE}_6
-	 * Apparently, neither Windows or MacOS will use these commands,
-	 * so some devices do not support them
-	 */
-	if (us->flags & US_FL_MODE_XLATE) {
-		US_DEBUGP("Invoking Mode Translation\n");
-		/* save the old command for later */
-		old_cmnd = srb->cmnd[0];
-
-		switch (srb->cmnd[0]) {
-		/* change READ_6/WRITE_6 to READ_10/WRITE_10 */
-		case WRITE_6:
-		case READ_6:
-			srb->cmd_len = 12;
-			srb->cmnd[11] = 0;
-			srb->cmnd[10] = 0;
-			srb->cmnd[9] = 0;
-			srb->cmnd[8] = srb->cmnd[4];
-			srb->cmnd[7] = 0;
-			srb->cmnd[6] = 0;
-			srb->cmnd[5] = srb->cmnd[3];
-			srb->cmnd[4] = srb->cmnd[2];
-			srb->cmnd[3] = srb->cmnd[1] & 0x1F;
-			srb->cmnd[2] = 0;
-			srb->cmnd[1] = srb->cmnd[1] & 0xE0;
-			srb->cmnd[0] = srb->cmnd[0] | 0x20;
-			break;
-
-		/* convert MODE_SELECT data here */
-		case MODE_SENSE:
-		case MODE_SELECT:
-			srb->cmd_len = 12;
-			srb->cmnd[11] = 0;
-			srb->cmnd[10] = 0;
-			srb->cmnd[9] = 0;
-			srb->cmnd[8] = srb->cmnd[4];
-			srb->cmnd[7] = 0;
-			srb->cmnd[6] = 0;
-			srb->cmnd[5] = 0;
-			srb->cmnd[4] = 0;
-			srb->cmnd[3] = 0;
-			srb->cmnd[2] = srb->cmnd[2];
-			srb->cmnd[1] = srb->cmnd[1];
-			srb->cmnd[0] = srb->cmnd[0] | 0x40;
-			break;
-		} /* switch (srb->cmnd[0]) */
-	} /* if (us->flags & US_FL_MODE_XLATE) */
-
-	/* convert MODE_SELECT data here */
-	if ((us->flags & US_FL_MODE_XLATE) && (old_cmnd == MODE_SELECT))
-		usb_stor_scsiSense6to10(srb);
-
 	/* send the command to the transport layer */
 	usb_stor_invoke_transport(srb, us);
-	if (srb->result == SAM_STAT_GOOD) {
-
-		/* Fix the MODE_SENSE data if we translated the command */
-		if ((us->flags & US_FL_MODE_XLATE) && (old_cmnd == MODE_SENSE))
-			usb_stor_scsiSense10to6(srb);
 
+	if (srb->result == SAM_STAT_GOOD) {
 		/* Fix the INQUIRY data if necessary */
 		fix_inquiry_data(srb);
 
diff -Nru a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h
--- a/drivers/usb/storage/protocol.h	Sat Jul 19 12:54:24 2003
+++ b/drivers/usb/storage/protocol.h	Sat Jul 19 12:54:24 2003
@@ -41,7 +41,7 @@
 #ifndef _PROTOCOL_H_
 #define _PROTOCOL_H_
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include "scsi.h"
 #include "usb.h"
 
diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
--- a/drivers/usb/storage/scsiglue.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/usb/storage/scsiglue.c	Sat Jul 19 12:54:25 2003
@@ -263,7 +263,6 @@
 
 #define DO_FLAG(a)  	if (f & US_FL_##a)  pos += sprintf(pos, " " #a)
 		DO_FLAG(SINGLE_LUN);
-		DO_FLAG(MODE_XLATE);
 		DO_FLAG(SCM_MULT_TARG);
 		DO_FLAG(FIX_INQUIRY);
 		DO_FLAG(FIX_CAPACITY);
@@ -345,500 +344,4 @@
 	[7]	= 0x0a,			    /* additional length */
 	[12]	= 0x24			    /* Invalid Field in CDB */
 };
-
-#define USB_STOR_SCSI_SENSE_HDRSZ 4
-#define USB_STOR_SCSI_SENSE_10_HDRSZ 8
-
-struct usb_stor_scsi_sense_hdr
-{
-  __u8* dataLength;
-  __u8* mediumType;
-  __u8* devSpecParms;
-  __u8* blkDescLength;
-};
-
-typedef struct usb_stor_scsi_sense_hdr Usb_Stor_Scsi_Sense_Hdr;
-
-union usb_stor_scsi_sense_hdr_u
-{
-  Usb_Stor_Scsi_Sense_Hdr hdr;
-  __u8* array[USB_STOR_SCSI_SENSE_HDRSZ];
-};
-
-typedef union usb_stor_scsi_sense_hdr_u Usb_Stor_Scsi_Sense_Hdr_u;
-
-struct usb_stor_scsi_sense_hdr_10
-{
-  __u8* dataLengthMSB;
-  __u8* dataLengthLSB;
-  __u8* mediumType;
-  __u8* devSpecParms;
-  __u8* reserved1;
-  __u8* reserved2;
-  __u8* blkDescLengthMSB;
-  __u8* blkDescLengthLSB;
-};
-
-typedef struct usb_stor_scsi_sense_hdr_10 Usb_Stor_Scsi_Sense_Hdr_10;
-
-union usb_stor_scsi_sense_hdr_10_u
-{
-  Usb_Stor_Scsi_Sense_Hdr_10 hdr;
-  __u8* array[USB_STOR_SCSI_SENSE_10_HDRSZ];
-};
-
-typedef union usb_stor_scsi_sense_hdr_10_u Usb_Stor_Scsi_Sense_Hdr_10_u;
-
-void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* , Usb_Stor_Scsi_Sense_Hdr_u*,
-				    Usb_Stor_Scsi_Sense_Hdr_10_u*, int* );
-
-int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 )
-{
-  __u8 *buffer=0;
-  int outputBufferSize = 0;
-  int length=0;
-  struct scatterlist *sg = 0;
-  int i=0, j=0, element=0;
-  Usb_Stor_Scsi_Sense_Hdr_u the6Locations;
-  Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations;
-  int sb=0,si=0,db=0,di=0;
-  int sgLength=0;
-
-  US_DEBUGP("-- converting 10 byte sense data to 6 byte\n");
-  the10->cmnd[0] = the10->cmnd[0] & 0xBF;
-
-  /* Determine buffer locations */
-  usb_stor_scsiSenseParseBuffer( the10, &the6Locations, &the10Locations,
-				 &length );
-
-  /* Work out minimum buffer to output */
-  outputBufferSize = *the10Locations.hdr.dataLengthLSB;
-  outputBufferSize += USB_STOR_SCSI_SENSE_HDRSZ;
-
-  /* Check to see if we need to trucate the output */
-  if ( outputBufferSize > length )
-    {
-      printk( KERN_WARNING USB_STORAGE 
-	      "Had to truncate MODE_SENSE_10 buffer into MODE_SENSE.\n" );
-      printk( KERN_WARNING USB_STORAGE
-	      "outputBufferSize is %d and length is %d.\n",
-	      outputBufferSize, length );
-    }
-  outputBufferSize = length;
-
-  /* Data length */
-  if ( *the10Locations.hdr.dataLengthMSB != 0 ) /* MSB must be zero */
-    {
-      printk( KERN_WARNING USB_STORAGE 
-	      "Command will be truncated to fit in SENSE6 buffer.\n" );
-      *the6Locations.hdr.dataLength = 0xff;
-    }
-  else
-    {
-      *the6Locations.hdr.dataLength = *the10Locations.hdr.dataLengthLSB;
-    }
-
-  /* Medium type and DevSpecific parms */
-  *the6Locations.hdr.mediumType = *the10Locations.hdr.mediumType;
-  *the6Locations.hdr.devSpecParms = *the10Locations.hdr.devSpecParms;
-
-  /* Block descriptor length */
-  if ( *the10Locations.hdr.blkDescLengthMSB != 0 ) /* MSB must be zero */
-    {
-      printk( KERN_WARNING USB_STORAGE 
-	      "Command will be truncated to fit in SENSE6 buffer.\n" );
-      *the6Locations.hdr.blkDescLength = 0xff;
-    }
-  else
-    {
-      *the6Locations.hdr.blkDescLength = *the10Locations.hdr.blkDescLengthLSB;
-    }
-
-  if ( the10->use_sg == 0 )
-    {
-      buffer = the10->request_buffer;
-      /* Copy the rest of the data */
-      memmove( &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]),
-	       &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]),
-	       outputBufferSize - USB_STOR_SCSI_SENSE_HDRSZ );
-      /* initialise last bytes left in buffer due to smaller header */
-      memset( &(buffer[outputBufferSize
-	    -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ)]),
-	      0,
-	      USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ );
-    }
-  else
-    {
-      sg = (struct scatterlist *) the10->request_buffer;
-      /* scan through this scatterlist and figure out starting positions */
-      for ( i=0; i < the10->use_sg; i++)
-	{
-	  sgLength = sg[i].length;
-	  for ( j=0; j<sgLength; j++ )
-	    {
-	      /* get to end of header */
-	      if ( element == USB_STOR_SCSI_SENSE_HDRSZ )
-		{
-		  db=i;
-		  di=j;
-		}
-	      if ( element == USB_STOR_SCSI_SENSE_10_HDRSZ )
-		{
-		  sb=i;
-		  si=j;
-		  /* we've found both sets now, exit loops */
-		  j=sgLength;
-		  i=the10->use_sg;
-		}
-	      element++;
-	    }
-	}
-
-      /* Now we know where to start the copy from */
-      element = USB_STOR_SCSI_SENSE_HDRSZ;
-      while ( element < outputBufferSize
-	      -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) )
-	{
-	  /* check limits */
-	  if ( sb >= the10->use_sg ||
-	       si >= sg[sb].length ||
-	       db >= the10->use_sg ||
-	       di >= sg[db].length )
-	    {
-	      printk( KERN_ERR USB_STORAGE
-		      "Buffer overrun averted, this shouldn't happen!\n" );
-	      break;
-	    }
-
-	  /* copy one byte */
-	  {
-		char *src = sg_address(sg[sb]) + si;
-		char *dst = sg_address(sg[db]) + di;
-
-		 *dst = *src;
-	  }
-
-	  /* get next destination */
-	  if ( sg[db].length-1 == di )
-	    {
-	      db++;
-	      di=0;
-	    }
-	  else
-	    {
-	      di++;
-	    }
-
-	  /* get next source */
-	  if ( sg[sb].length-1 == si )
-	    {
-	      sb++;
-	      si=0;
-	    }
-	  else
-	    {
-	      si++;
-	    }
-
-	  element++;
-	}
-      /* zero the remaining bytes */
-      while ( element < outputBufferSize )
-	{
-	  /* check limits */
-	  if ( db >= the10->use_sg ||
-	       di >= sg[db].length )
-	    {
-	      printk( KERN_ERR USB_STORAGE
-		      "Buffer overrun averted, this shouldn't happen!\n" );
-	      break;
-	    }
-
-	  *(char*)(sg_address(sg[db])) = 0;
-
-	  /* get next destination */
-	  if ( sg[db].length-1 == di )
-	    {
-	      db++;
-	      di=0;
-	    }
-	  else
-	    {
-	      di++;
-	    }
-	  element++;
-	}
-    }
-
-  /* All done any everything was fine */
-  return 0;
-}
-
-int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 )
-{
-  /* will be used to store part of buffer */  
-  __u8 tempBuffer[USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ],
-    *buffer=0;
-  int outputBufferSize = 0;
-  int length=0;
-  struct scatterlist *sg = 0;
-  int i=0, j=0, element=0;
-  Usb_Stor_Scsi_Sense_Hdr_u the6Locations;
-  Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations;
-  int sb=0,si=0,db=0,di=0;
-  int lsb=0,lsi=0,ldb=0,ldi=0;
-
-  US_DEBUGP("-- converting 6 byte sense data to 10 byte\n");
-  the6->cmnd[0] = the6->cmnd[0] | 0x40;
-
-  /* Determine buffer locations */
-  usb_stor_scsiSenseParseBuffer( the6, &the6Locations, &the10Locations,
-				 &length );
-
-  /* Work out minimum buffer to output */
-  outputBufferSize = *the6Locations.hdr.dataLength;
-  outputBufferSize += USB_STOR_SCSI_SENSE_10_HDRSZ;
-
-  /* Check to see if we need to trucate the output */
-  if ( outputBufferSize > length )
-    {
-      printk( KERN_WARNING USB_STORAGE 
-	      "Had to truncate MODE_SENSE into MODE_SENSE_10 buffer.\n" );
-      printk( KERN_WARNING USB_STORAGE
-	      "outputBufferSize is %d and length is %d.\n",
-	      outputBufferSize, length );
-    }
-  outputBufferSize = length;
-
-  /* Block descriptor length - save these before overwriting */
-  tempBuffer[2] = *the10Locations.hdr.blkDescLengthMSB;
-  tempBuffer[3] = *the10Locations.hdr.blkDescLengthLSB;
-  *the10Locations.hdr.blkDescLengthLSB = *the6Locations.hdr.blkDescLength;
-  *the10Locations.hdr.blkDescLengthMSB = 0;
-
-  /* reserved - save these before overwriting */
-  tempBuffer[0] = *the10Locations.hdr.reserved1;
-  tempBuffer[1] = *the10Locations.hdr.reserved2;
-  *the10Locations.hdr.reserved1 = *the10Locations.hdr.reserved2 = 0;
-
-  /* Medium type and DevSpecific parms */
-  *the10Locations.hdr.devSpecParms = *the6Locations.hdr.devSpecParms;
-  *the10Locations.hdr.mediumType = *the6Locations.hdr.mediumType;
-
-  /* Data length */
-  *the10Locations.hdr.dataLengthLSB = *the6Locations.hdr.dataLength;
-  *the10Locations.hdr.dataLengthMSB = 0;
-
-  if ( !the6->use_sg )
-    {
-      buffer = the6->request_buffer;
-      /* Copy the rest of the data */
-      memmove( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]),
-	      &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]),
-	      outputBufferSize-USB_STOR_SCSI_SENSE_10_HDRSZ );
-      /* Put the first four bytes (after header) in place */
-      memcpy( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]),
-	      tempBuffer,
-	      USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ );
-    }
-  else
-    {
-      sg = (struct scatterlist *) the6->request_buffer;
-      /* scan through this scatterlist and figure out ending positions */
-      for ( i=0; i < the6->use_sg; i++)
-	{
-	  for ( j=0; j<sg[i].length; j++ )
-	    {
-	      /* get to end of header */
-	      if ( element == USB_STOR_SCSI_SENSE_HDRSZ )
-		{
-		  ldb=i;
-		  ldi=j;
-		}
-	      if ( element == USB_STOR_SCSI_SENSE_10_HDRSZ )
-		{
-		  lsb=i;
-		  lsi=j;
-		  /* we've found both sets now, exit loops */
-		  j=sg[i].length;
-		  i=the6->use_sg;
-		  break;
-		}
-	      element++;
-	    }
-	}
-      /* scan through this scatterlist and figure out starting positions */
-      element = length-1;
-      /* destination is the last element */
-      db=the6->use_sg-1;
-      di=sg[db].length-1;
-      for ( i=the6->use_sg-1; i >= 0; i--)
-	{
-	  for ( j=sg[i].length-1; j>=0; j-- )
-	    {
-	      /* get to end of header and find source for copy */
-	      if ( element == length - 1
-		   - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) )
-		{
-		  sb=i;
-		  si=j;
-		  /* we've found both sets now, exit loops */
-		  j=-1;
-		  i=-1;
-		}
-	      element--;
-	    }
-	}
-      /* Now we know where to start the copy from */
-      element = length-1
-	- (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ);
-      while ( element >= USB_STOR_SCSI_SENSE_10_HDRSZ )
-	{
-	  /* check limits */
-	  if ( ( sb <= lsb && si < lsi ) ||
-	       ( db <= ldb && di < ldi ) )
-	    {
-	      printk( KERN_ERR USB_STORAGE
-		      "Buffer overrun averted, this shouldn't happen!\n" );
-	      break;
-	    }
-
-	  /* copy one byte */
-	  {
-		char *src = sg_address(sg[sb]) + si;
-		char *dst = sg_address(sg[db]) + di;
-
-		 *dst = *src;
-	  }
-
-	  /* get next destination */
-	  if ( di == 0 )
-	    {
-	      db--;
-	      di=sg[db].length-1;
-	    }
-	  else
-	    {
-	      di--;
-	    }
-
-	  /* get next source */
-	  if ( si == 0 )
-	    {
-	      sb--;
-	      si=sg[sb].length-1;
-	    }
-	  else
-	    {
-	      si--;
-	    }
-
-	  element--;
-	}
-      /* copy the remaining four bytes */
-      while ( element >= USB_STOR_SCSI_SENSE_HDRSZ )
-	{
-	  /* check limits */
-	  if ( db <= ldb && di < ldi )
-	    {
-	      printk( KERN_ERR USB_STORAGE
-		      "Buffer overrun averted, this shouldn't happen!\n" );
-	      break;
-	    }
-
-	 {
-		 char *dst = sg_address(sg[db]) + di;
-
-		 *dst = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ];
-	 }
-
-
-	  /* get next destination */
-	  if ( di == 0 )
-	    {
-	      db--;
-	      di=sg[db].length-1;
-	    }
-	  else
-	    {
-	      di--;
-	    }
-	  element--;
-	}
-    }
-
-  /* All done and everything was fine */
-  return 0;
-}
-
-void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* srb, Usb_Stor_Scsi_Sense_Hdr_u* the6,
-			       Usb_Stor_Scsi_Sense_Hdr_10_u* the10,
-			       int* length_p )
-
-{
-  int i = 0, j=0, element=0;
-  struct scatterlist *sg = 0;
-  int length = 0;
-  __u8* buffer=0;
-
-  /* are we scatter-gathering? */
-  if ( srb->use_sg != 0 )
-    {
-      /* loop over all the scatter gather structures and 
-       * get pointer to the data members in the headers
-       * (also work out the length while we're here)
-       */
-      sg = (struct scatterlist *) srb->request_buffer;
-      for (i = 0; i < srb->use_sg; i++)
-	{
-	  length += sg[i].length;
-	  /* We only do the inner loop for the headers */
-	  if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
-	    {
-	      /* scan through this scatterlist */
-	      for ( j=0; j<sg[i].length; j++ )
-		{
-		  if ( element < USB_STOR_SCSI_SENSE_HDRSZ )
-		    {
-		      /* fill in the pointers for both header types */
-		      the6->array[element] = sg_address(sg[i]) + j;
-		      the10->array[element] = sg_address(sg[i]) + j;
-
-		    }
-		  else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ )
-		    {
-		      /* only the longer headers still cares now */
-		      the10->array[element] = sg_address(sg[i]) + j;
-		       
-		    }
-		  /* increase element counter */
-		  element++;
-		}
-	    }
-	}
-    }
-  else
-    {
-      length = srb->request_bufflen;
-      buffer = srb->request_buffer;
-      if ( length < USB_STOR_SCSI_SENSE_10_HDRSZ )
-	printk( KERN_ERR USB_STORAGE
-		"Buffer length smaller than header!!" );
-      for( i=0; i<USB_STOR_SCSI_SENSE_10_HDRSZ; i++ )
-	{
-	  if ( i < USB_STOR_SCSI_SENSE_HDRSZ )
-	    {
-	      the6->array[i] = &(buffer[i]);
-	      the10->array[i] = &(buffer[i]);
-	    }
-	  else
-	    {
-	      the10->array[i] = &(buffer[i]);
-	    }
-	}
-    }
-
-  /* Set value of length passed in */
-  *length_p = length;
-}
 
diff -Nru a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h
--- a/drivers/usb/storage/scsiglue.h	Sat Jul 19 12:54:25 2003
+++ b/drivers/usb/storage/scsiglue.h	Sat Jul 19 12:54:25 2003
@@ -41,7 +41,7 @@
 #ifndef _SCSIGLUE_H_
 #define _SCSIGLUE_H_
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include "scsi.h"
 #include "hosts.h"
 
diff -Nru a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
--- a/drivers/usb/storage/sddr09.c	Sat Jul 19 12:54:27 2003
+++ b/drivers/usb/storage/sddr09.c	Sat Jul 19 12:54:27 2003
@@ -261,12 +261,13 @@
  */
 static int
 sddr09_test_unit_ready(struct us_data *us) {
-	unsigned char command[6] = {
-		0, LUNBITS, 0, 0, 0, 0
-	};
+	unsigned char *command = us->iobuf;
 	int result;
 
-	result = sddr09_send_scsi_command(us, command, sizeof(command));
+	memset(command, 0, 6);
+	command[1] = LUNBITS;
+
+	result = sddr09_send_scsi_command(us, command, 6);
 
 	US_DEBUGP("sddr09_test_unit_ready returns %d\n", result);
 
@@ -281,12 +282,15 @@
  */
 static int
 sddr09_request_sense(struct us_data *us, unsigned char *sensebuf, int buflen) {
-	unsigned char command[12] = {
-		0x03, LUNBITS, 0, 0, buflen, 0, 0, 0, 0, 0, 0, 0
-	};
+	unsigned char *command = us->iobuf;
 	int result;
 
-	result = sddr09_send_scsi_command(us, command, sizeof(command));
+	memset(command, 0, 12);
+	command[0] = 0x03;
+	command[1] = LUNBITS;
+	command[4] = buflen;
+
+	result = sddr09_send_scsi_command(us, command, 12);
 	if (result != USB_STOR_TRANSPORT_GOOD) {
 		US_DEBUGP("request sense failed\n");
 		return result;
@@ -331,20 +335,23 @@
 	     int nr_of_pages, int bulklen, unsigned char *buf,
 	     int use_sg) {
 
-	unsigned char command[12] = {
-		0xe8, LUNBITS | x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-	};
+	unsigned char *command = us->iobuf;
 	int result;
 
+	command[0] = 0xE8;
+	command[1] = LUNBITS | x;
 	command[2] = MSB_of(fromaddress>>16);
 	command[3] = LSB_of(fromaddress>>16); 
 	command[4] = MSB_of(fromaddress & 0xFFFF);
 	command[5] = LSB_of(fromaddress & 0xFFFF); 
-
+	command[6] = 0;
+	command[7] = 0;
+	command[8] = 0;
+	command[9] = 0;
 	command[10] = MSB_of(nr_of_pages);
 	command[11] = LSB_of(nr_of_pages);
 
-	result = sddr09_send_scsi_command(us, command, sizeof(command));
+	result = sddr09_send_scsi_command(us, command, 12);
 
 	if (result != USB_STOR_TRANSPORT_GOOD) {
 		US_DEBUGP("Result for send_control in sddr09_read2%d %d\n",
@@ -458,17 +465,18 @@
  */
 static int
 sddr09_erase(struct us_data *us, unsigned long Eaddress) {
-	unsigned char command[12] = {
-		0xea, LUNBITS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-	};
+	unsigned char *command = us->iobuf;
 	int result;
 
+	memset(command, 0, 12);
+	command[0] = 0xEA;
+	command[1] = LUNBITS;
 	command[6] = MSB_of(Eaddress>>16);
 	command[7] = LSB_of(Eaddress>>16);
 	command[8] = MSB_of(Eaddress & 0xFFFF);
 	command[9] = LSB_of(Eaddress & 0xFFFF);
 
-	result = sddr09_send_scsi_command(us, command, sizeof(command));
+	result = sddr09_send_scsi_command(us, command, 12);
 
 	if (result != USB_STOR_TRANSPORT_GOOD)
 		US_DEBUGP("Result for send_control in sddr09_erase %d\n",
@@ -493,11 +501,12 @@
 	      unsigned long Waddress, unsigned long Eaddress,
 	      int nr_of_pages, int bulklen, unsigned char *buf, int use_sg) {
 
-	unsigned char command[12] = {
-		0xe9, LUNBITS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-	};
+	unsigned char *command = us->iobuf;
 	int result;
 
+	command[0] = 0xE9;
+	command[1] = LUNBITS;
+
 	command[2] = MSB_of(Waddress>>16);
 	command[3] = LSB_of(Waddress>>16);
 	command[4] = MSB_of(Waddress & 0xFFFF);
@@ -511,7 +520,7 @@
 	command[10] = MSB_of(nr_of_pages);
 	command[11] = LSB_of(nr_of_pages);
 
-	result = sddr09_send_scsi_command(us, command, sizeof(command));
+	result = sddr09_send_scsi_command(us, command, 12);
 
 	if (result != USB_STOR_TRANSPORT_GOOD) {
 		US_DEBUGP("Result for send_control in sddr09_writeX %d\n",
@@ -554,15 +563,15 @@
  */
 static int
 sddr09_read_sg_test_only(struct us_data *us) {
-	unsigned char command[15] = {
-		0xe7, LUNBITS, 0
-	};
+	unsigned char *command = us->iobuf;
 	int result, bulklen, nsg, ct;
 	unsigned char *buf;
 	unsigned long address;
 
 	nsg = bulklen = 0;
-
+	command[0] = 0xE7;
+	command[1] = LUNBITS;
+	command[2] = 0;
 	address = 040000; ct = 1;
 	nsg++;
 	bulklen += (ct << 9);
@@ -628,20 +637,22 @@
 static int
 sddr09_read_status(struct us_data *us, unsigned char *status) {
 
-	unsigned char command[12] = {
-		0xec, LUNBITS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-	};
-	unsigned char data[64];
+	unsigned char *command = us->iobuf;
+	unsigned char *data = us->iobuf;
 	int result;
 
 	US_DEBUGP("Reading status...\n");
 
-	result = sddr09_send_scsi_command(us, command, sizeof(command));
+	memset(command, 0, 12);
+	command[0] = 0xEC;
+	command[1] = LUNBITS;
+
+	result = sddr09_send_scsi_command(us, command, 12);
 	if (result != USB_STOR_TRANSPORT_GOOD)
 		return result;
 
 	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
-				       data, sizeof(data), NULL);
+				       data, 64, NULL);
 	*status = data[0];
 	return (result == USB_STOR_XFER_GOOD ?
 			USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
@@ -953,13 +964,15 @@
  */
 static int
 sddr09_read_deviceID(struct us_data *us, unsigned char *deviceID) {
-	unsigned char command[12] = {
-		0xed, LUNBITS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-	};
-	unsigned char content[64];
+	unsigned char *command = us->iobuf;
+	unsigned char *content = us->iobuf;
 	int result, i;
 
-	result = sddr09_send_scsi_command(us, command, sizeof(command));
+	memset(command, 0, 12);
+	command[0] = 0xED;
+	command[1] = LUNBITS;
+
+	result = sddr09_send_scsi_command(us, command, 12);
 	if (result != USB_STOR_TRANSPORT_GOOD)
 		return result;
 
@@ -1006,11 +1019,13 @@
 static int
 sddr09_reset(struct us_data *us) {
 
-	unsigned char command[12] = {
-		0xeb, LUNBITS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-	};
+	unsigned char *command = us->iobuf;
+
+	memset(command, 0, 12);
+	command[0] = 0xEB;
+	command[1] = LUNBITS;
 
-	return sddr09_send_scsi_command(us, command, sizeof(command));
+	return sddr09_send_scsi_command(us, command, 12);
 }
 #endif
 
@@ -1313,7 +1328,7 @@
 int
 sddr09_init(struct us_data *us) {
 	int result;
-	unsigned char data[18];
+	unsigned char *data = us->iobuf;
 
 	result = sddr09_send_command(us, 0x01, USB_DIR_IN, data, 2);
 	if (result != USB_STOR_TRANSPORT_GOOD) {
@@ -1333,10 +1348,10 @@
 	US_DEBUGP("SDDR09init: %02X %02X\n", data[0], data[1]);
 	// get 07 00
 
-	result = sddr09_request_sense(us, data, sizeof(data));
+	result = sddr09_request_sense(us, data, 18);
 	if (result == USB_STOR_TRANSPORT_GOOD && data[2] != 0) {
 		int j;
-		for (j=0; j<sizeof(data); j++)
+		for (j=0; j<18; j++)
 			printk(" %02X", data[j]);
 		printk("\n");
 		// get 70 00 00 00 00 00 00 * 00 00 00 00 00 00
diff -Nru a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
--- a/drivers/usb/storage/sddr55.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/usb/storage/sddr55.c	Sat Jul 19 12:54:24 2003
@@ -91,13 +91,14 @@
 static int sddr55_status(struct us_data *us)
 {
 	int result;
-	unsigned char command[8] = {
-		0, 0, 0, 0, 0, 0xb0, 0, 0x80
-	};
-	unsigned char status[8];
+	unsigned char *command = us->iobuf;
+	unsigned char *status = us->iobuf;
 	struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
 
 	/* send command */
+	memset(command, 0, 8);
+	command[5] = 0xB0;
+	command[7] = 0x80;
 	result = sddr55_bulk_transport(us,
 		SCSI_DATA_WRITE, command, 8);
 
@@ -158,10 +159,8 @@
 		int use_sg) {
 
 	int result = USB_STOR_TRANSPORT_GOOD;
-	unsigned char command[8] = {
-		0, 0, 0, 0, 0, 0xb0, 0, 0x85
-	};
-	unsigned char status[8];
+	unsigned char *command = us->iobuf;
+	unsigned char *status = us->iobuf;
 	struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
 
 	unsigned int pba;
@@ -205,11 +204,15 @@
 
 			address = (pba << info->blockshift) + page;
 
+			command[0] = 0;
 			command[1] = LSB_of(address>>16);
 			command[2] = LSB_of(address>>8);
 			command[3] = LSB_of(address);
 
+			command[4] = 0;
+			command[5] = 0xB0;
 			command[6] = LSB_of(pages << (1 - info->smallpageshift));
+			command[7] = 0x85;
 
 			/* send command */
 			result = sddr55_bulk_transport(us,
@@ -274,10 +277,8 @@
 		int use_sg) {
 
 	int result = USB_STOR_TRANSPORT_GOOD;
-	unsigned char command[8] = {
-		0, 0, 0, 0, 0, 0xb0, 0, 0x86
-	};
-	unsigned char status[8];
+	unsigned char *command = us->iobuf;
+	unsigned char *status = us->iobuf;
 	struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
 
 	unsigned int pba;
@@ -380,6 +381,8 @@
 		command[6] = MSB_of(lba % 1000);
 
 		command[4] |= LSB_of(pages >> info->smallpageshift);
+		command[5] = 0xB0;
+		command[7] = 0x86;
 
 		/* send command */
 		result = sddr55_bulk_transport(us,
@@ -473,11 +476,12 @@
 		unsigned char *deviceID) {
 
 	int result;
-	unsigned char command[8] = {
-		0, 0, 0, 0, 0, 0xb0, 0, 0x84
-	};
-	unsigned char content[64];
+	unsigned char *command = us->iobuf;
+	unsigned char *content = us->iobuf;
 
+	memset(command, 0, 8);
+	command[5] = 0xB0;
+	command[7] = 0x84;
 	result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8);
 
 	US_DEBUGP("Result of send_control for device ID is %d\n",
@@ -598,7 +602,7 @@
 	struct sddr55_card_info *info = (struct sddr55_card_info *)(us->extra);
 	int numblocks;
 	unsigned char *buffer;
-	unsigned char command[8] = { 0, 0, 0, 0, 0, 0xb0, 0, 0x8a};	
+	unsigned char *command = us->iobuf;
 	int i;
 	unsigned short lba;
 	unsigned short max_lba;
@@ -614,7 +618,10 @@
 	if (!buffer)
 		return -1;
 
+	memset(command, 0, 8);
+	command[5] = 0xB0;
 	command[6] = numblocks * 2 / 256;
+	command[7] = 0x8A;
 
 	result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8);
 
diff -Nru a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
--- a/drivers/usb/storage/transport.h	Sat Jul 19 12:54:24 2003
+++ b/drivers/usb/storage/transport.h	Sat Jul 19 12:54:24 2003
@@ -42,7 +42,7 @@
 #define _TRANSPORT_H_
 
 #include <linux/config.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include "usb.h"
 #include "scsi.h"
 
diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
--- a/drivers/usb/storage/unusual_devs.h	Sat Jul 19 12:54:26 2003
+++ b/drivers/usb/storage/unusual_devs.h	Sat Jul 19 12:54:26 2003
@@ -119,7 +119,7 @@
 UNUSUAL_DEV(  0x04cb, 0x0100, 0x0000, 0x2210,
 		"Fujifilm",
 		"FinePix 1400Zoom",
-		US_SC_8070, US_PR_CBI, NULL, US_FL_FIX_INQUIRY),
+		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
 
 /* Reported by Peter Wächtler <pwaechtler@loewe-komp.de>
  * The device needs the flags only.
@@ -236,7 +236,7 @@
 UNUSUAL_DEV(  0x054c, 0x0010, 0x0106, 0x0450, 
 		"Sony",
 		"DSC-S30/S70/S75/505V/F505/F707/F717/P8", 
-		US_SC_SCSI, US_PR_CB, NULL,
+		US_SC_SCSI, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN | US_FL_MODE_XLATE ),
 
 /* Reported by wim@geeks.nl */
@@ -555,7 +555,7 @@
 UNUSUAL_DEV(  0x08ca, 0x2011, 0x0000, 0x9999,
 		"AIPTEK",
 		"PocketCAM 3Mega",
-		US_SC_SCSI, US_PR_BULK, NULL,
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_MODE_XLATE ),
 
 /* aeb */
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c	Sat Jul 19 12:54:24 2003
+++ b/drivers/usb/storage/usb.c	Sat Jul 19 12:54:24 2003
@@ -958,6 +958,8 @@
 		goto BadDevice;
 	}
 
+	scsi_scan_host(us->host);
+
 	printk(KERN_DEBUG 
 	       "WARNING: USB Mass Storage data integrity not assured\n");
 	printk(KERN_DEBUG 
diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
--- a/drivers/usb/storage/usb.h	Sat Jul 19 12:54:26 2003
+++ b/drivers/usb/storage/usb.h	Sat Jul 19 12:54:26 2003
@@ -45,7 +45,7 @@
 #define _USB_H_
 
 #include <linux/usb.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/smp_lock.h>
 #include <linux/completion.h>
 #include <linux/version.h>
@@ -69,11 +69,10 @@
 
 /* Flag definitions: these entries are static */
 #define US_FL_SINGLE_LUN      0x00000001 /* allow access to only LUN 0	    */
-#define US_FL_MODE_XLATE      0x00000002 /* translate _6 to _10 commands for
-						    Win/MacOS compatibility */
+#define US_FL_MODE_XLATE      0          /* [no longer used]                */
 #define US_FL_IGNORE_SER      0		 /* [no longer used]		    */
 #define US_FL_SCM_MULT_TARG   0x00000020 /* supports multiple targets	    */
-#define US_FL_FIX_INQUIRY     0x00000040 /* INQUIRY response needs fixing   */
+#define US_FL_FIX_INQUIRY     0x00000040 /* INQUIRY response needs faking   */
 #define US_FL_FIX_CAPACITY    0x00000080 /* READ CAPACITY response too big  */
 
 /* Dynamic flag definitions: used in set_bit() etc. */
diff -Nru a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
--- a/drivers/usb/usb-skeleton.c	Sat Jul 19 12:54:25 2003
+++ b/drivers/usb/usb-skeleton.c	Sat Jul 19 12:54:25 2003
@@ -507,7 +507,7 @@
 	struct usb_endpoint_descriptor *endpoint;
 	size_t buffer_size;
 	int i;
-	int retval;
+	int retval = -ENOMEM;
 
 	/* See if the device offered us matches what we can accept */
 	if ((udev->descriptor.idVendor != USB_SKEL_VENDOR_ID) ||
@@ -515,18 +515,11 @@
 		return -ENODEV;
 	}
 
-	retval = usb_register_dev (interface, &skel_class);
-	if (retval) {
-		/* something prevented us from registering this driver */
-		err ("Not able to get a minor for this device.");
-		goto exit;
-	}
-
 	/* allocate memory for our device state and initialize it */
 	dev = kmalloc (sizeof(struct usb_skel), GFP_KERNEL);
 	if (dev == NULL) {
 		err ("Out of memory");
-		goto exit_minor;
+		goto error;
 	}
 	memset (dev, 0x00, sizeof (*dev));
 
@@ -603,24 +596,24 @@
 	/* allow device read, write and ioctl */
 	dev->present = 1;
 
+	/* we can register the device now, as it is ready */
+	usb_set_intfdata (interface, dev);
+	retval = usb_register_dev (interface, &skel_class);
+	if (retval) {
+		/* something prevented us from registering this driver */
+		err ("Not able to get a minor for this device.");
+		usb_set_intfdata (interface, NULL);
+		goto error;
+	}
+
+
 	/* let the user know what node this device is now attached to */
 	info ("USB Skeleton device now attached to USBSkel-%d", dev->minor);
-
-	goto exit;
+	return 0;
 
 error:
 	skel_delete (dev);
-	dev = NULL;
-
-exit_minor:
-	usb_deregister_dev (interface, &skel_class);
-
-exit:
-	if (dev) {
-		usb_set_intfdata (interface, dev);
-		return 0;
-	}
-	return -ENODEV;
+	return retval;
 }
 
 
diff -Nru a/drivers/video/Makefile b/drivers/video/Makefile
--- a/drivers/video/Makefile	Sat Jul 19 12:54:23 2003
+++ b/drivers/video/Makefile	Sat Jul 19 12:54:23 2003
@@ -69,7 +69,7 @@
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o 
 obj-$(CONFIG_FB_HIT)              += hitfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_E1355)            += epson1355fb.o
-obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
+obj-$(CONFIG_FB_PVR2)             += pvr2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_VOODOO1)          += sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 
 obj-$(CONFIG_FB_FFB)               += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o
diff -Nru a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
--- a/drivers/video/pvr2fb.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/video/pvr2fb.c	Sat Jul 19 12:54:22 2003
@@ -4,7 +4,7 @@
  * Dreamcast.
  *
  * Copyright (c) 2001 M. R. Brown <mrbrown@0xd6.org>
- * Copyright (c) 2001 Paul Mundt  <lethal@chaoticdreams.org>
+ * Copyright (c) 2001, 2002, 2003 Paul Mundt <lethal@linux-sh.org>
  *
  * This file is part of the LinuxDC project (linuxdc.sourceforge.net).
  *
@@ -12,14 +12,15 @@
 
 /*
  * This driver is mostly based on the excellent amifb and vfb sources.  It uses
- * an odd scheme for converting hardware values to/from framebuffer values, here are
- * some hacked-up formulas:
+ * an odd scheme for converting hardware values to/from framebuffer values,
+ * here are some hacked-up formulas:
  *
- *  The Dreamcast has screen offsets from each side of its four borders and the start
- *  offsets of the display window.  I used these values to calculate 'pseudo' values
- *  (think of them as placeholders) for the fb video mode, so that when it came time
- *  to convert these values back into their hardware values, I could just add mode-
- *  specific offsets to get the correct mode settings:
+ *  The Dreamcast has screen offsets from each side of its four borders and
+ *  the start offsets of the display window.  I used these values to calculate
+ *  'pseudo' values (think of them as placeholders) for the fb video mode, so
+ *  that when it came time to convert these values back into their hardware
+ *  values, I could just add mode- specific offsets to get the correct mode
+ *  settings:
  *
  *      left_margin = diwstart_h - borderstart_h;
  *      right_margin = borderstop_h - (diwstart_h + xres);
@@ -29,9 +30,9 @@
  *      hsync_len = borderstart_h + (hsync_total - borderstop_h);
  *      vsync_len = borderstart_v + (vsync_total - borderstop_v);
  *
- *  Then, when it's time to convert back to hardware settings, the only constants
- *  are the borderstart_* offsets, all other values are derived from the fb video
- *  mode:
+ *  Then, when it's time to convert back to hardware settings, the only
+ *  constants are the borderstart_* offsets, all other values are derived from
+ *  the fb video mode:
  *  
  *      // PAL
  *      borderstart_h = 116;
@@ -57,7 +58,6 @@
 #include <linux/interrupt.h>
 #include <linux/fb.h>
 #include <linux/init.h>
-#include <linux/console.h>
 
 #ifdef CONFIG_SH_DREAMCAST
 #include <asm/io.h>
@@ -66,14 +66,9 @@
 #endif
 
 #ifdef CONFIG_MTRR
-  #include <asm/mtrr.h>
+#include <asm/mtrr.h>
 #endif
 
-#include <video/fbcon.h>
-#include <video/fbcon-cfb16.h>
-#include <video/fbcon-cfb24.h>
-#include <video/fbcon-cfb32.h>
-
 #ifdef CONFIG_FB_PVR2_DEBUG
 #  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
 #else
@@ -124,16 +119,6 @@
  */
 
 static struct pvr2fb_par {
-
-	int xres;
-	int yres;
-	int vxres;
-	int vyres;
-	int xoffset;
-	int yoffset;
-	u_short bpp;
-
-	u_long pixclock;
 	u_short hsync_total;	/* Clocks/line */
 	u_short vsync_total;	/* Lines/field */
 	u_short borderstart_h;
@@ -144,53 +129,49 @@
 	u_short diwstart_v;	/* Vertical offset of the display field, for
 				   interlaced modes, this is the long field */
 	u_long disp_start;	/* Address of image within VRAM */
-
-	u_long next_line;	/* Modulo for next line */
-
 	u_char is_interlaced;	/* Is the display interlaced? */
 	u_char is_doublescan;	/* Are scanlines output twice? (doublescan) */
 	u_char is_lowres;	/* Is horizontal pixel-doubling enabled? */
+} *currentpar;
 
-	u_long bordercolor;	/* RGB888 format border color */
-
-	u_long vmode;
-	
-} currentpar;
-
-static int currbpp;
-static struct display disp;
-static struct fb_info fb_info;
+static struct fb_info *fb_info;
 static int pvr2fb_inverse = 0;
 
-static struct { u_short red, green, blue, alpha; } palette[256];
-static union {
-#ifdef FBCON_HAS_CFB16
-	u16 cfb16[16];
-#endif
-#ifdef FBCON_HAS_CFB24
-	u32 cfb24[16];
-#endif
-#ifdef FBCON_HAS_CFB32
-	u32 cfb32[16];
-#endif
-} fbcon_cmap;
+static struct fb_fix_screeninfo pvr2_fix __initdata = {
+	.id =		"NEC PowerVR2",
+	.type = 	FB_TYPE_PACKED_PIXELS,
+	.visual = 	FB_VISUAL_TRUECOLOR,
+	.ypanstep =	1,
+	.ywrapstep =	1,
+	.accel = 	FB_ACCEL_NONE,
+};
 
-static char pvr2fb_name[16] = "NEC PowerVR2";
+static struct fb_var_screeninfo pvr2_var __initdata = {
+	.xres =		640,
+	.yres =		480,
+	.xres_virtual =	640,
+	.yres_virtual = 480,
+	.bits_per_pixel	=16,
+	.red =		{ 11, 5, 0 },
+	.green =	{  5, 6, 0 },
+	.blue =		{  0, 5, 0 },
+	.activate =	FB_ACTIVATE_NOW,
+	.height =	-1,
+	.width =	-1,
+	.vmode =	FB_VMODE_NONINTERLACED,
+};
 
 #define VIDEOMEMSIZE (8*1024*1024)
 static u_long videomemory = 0xa5000000, videomemorysize = VIDEOMEMSIZE;
 static int cable_type = -1;
 static int video_output = -1;
 
-#ifdef CONFIG_MTRR
-static int enable_mtrr = 1;
-static int mtrr_handle;
-#endif
+static int nopan = 0;
+static int nowrap = 1;
 
 /*
  * We do all updating, blanking, etc. during the vertical retrace period
  */
-
 static u_short do_vmode_full = 0;	/* Change the video mode */
 static u_short do_vmode_pan = 0;	/* Update the video mode */
 static short do_blank = 0;		/* (Un)Blank the screen */
@@ -201,50 +182,15 @@
 
 int pvr2fb_setup(char*);
 
-static int pvr2fb_get_fix(struct fb_fix_screeninfo *fix, int con,
-                            struct fb_info *info);
-static int pvr2fb_get_var(struct fb_var_screeninfo *var, int con,
-                            struct fb_info *info);
-static int pvr2fb_set_var(struct fb_var_screeninfo *var, int con,
-                            struct fb_info *info);
-static int pvr2fb_pan_display(struct fb_var_screeninfo *var, int con,
-                                struct fb_info *info);
-static int pvr2fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-                             struct fb_info *info);
-static int pvr2fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-                             struct fb_info *info);
 static int pvr2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                             u_int transp, struct fb_info *info);
 static int pvr2fb_blank(int blank, struct fb_info *info);
-
-	/*
-	 * Interface to the low level console driver
-	 */
-
-static int pvr2fbcon_switch(int con, struct fb_info *info);
-static int pvr2fbcon_updatevar(int con, struct fb_info *info);
-
-	/*
-	 * Internal/hardware-specific routines
-	 */
-
 static u_long get_line_length(int xres_virtual, int bpp);
 static void set_color_bitfields(struct fb_var_screeninfo *var);
-static int pvr2_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-                            u_int *transp, struct fb_info *info);
-
-static int pvr2_encode_fix(struct fb_fix_screeninfo *fix,
-                             struct pvr2fb_par *par);
-static int pvr2_decode_var(struct fb_var_screeninfo *var,
-                          struct pvr2fb_par *par);
-static int pvr2_encode_var(struct fb_var_screeninfo *var,
-                          struct pvr2fb_par *par);
-static void pvr2_get_par(struct pvr2fb_par *par);
-static void pvr2_set_var(struct fb_var_screeninfo *var);
-static void pvr2_pan_var(struct fb_var_screeninfo *var);
-static int pvr2_update_par(void);
-static void pvr2_update_display(void);
-static void pvr2_init_display(void);
+static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
+static int pvr2fb_set_par(struct fb_info *info);
+static void pvr2_update_display(struct fb_info *info);
+static void pvr2_init_display(struct fb_info *info);
 static void pvr2_do_blank(void);
 static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id, struct pt_regs *fp);
 static int pvr2_init_cable(void);
@@ -252,19 +198,18 @@
                             int val, int size);
 
 static struct fb_ops pvr2fb_ops = {
-	.owner =	THIS_MODULE,
-	.fb_get_fix =	pvr2fb_get_fix,
-	.fb_get_var =	pvr2fb_get_var,
-	.fb_set_var =	pvr2fb_set_var,
-	.fb_get_cmap =	pvr2fb_get_cmap,
-	.fb_set_cmap =	pvr2fb_set_cmap,
-	.fb_setcolreg =	pvr2fb_setcolreg,
-	.fb_pan_display = pvr2fb_pan_display,
-	.fb_blank =	pvr2fb_blank,
+	.owner 		= THIS_MODULE,
+	.fb_setcolreg 	= pvr2fb_setcolreg,
+	.fb_blank 	= pvr2fb_blank,
+	.fb_check_var 	= pvr2fb_check_var,
+	.fb_set_par 	= pvr2fb_set_par,
+	.fb_fillrect 	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_cursor	= soft_cursor,
 };
 
 static struct fb_videomode pvr2_modedb[] __initdata = {
-
     /*
      * Broadcast video modes (PAL and NTSC).  I'm unfamiliar with
      * PAL-M and PAL-N, but from what I've read both modes parallel PAL and
@@ -275,21 +220,16 @@
 	/* 640x480 @ 60Hz interlaced (NTSC) */
 	"ntsc_640x480i", 60, 640, 480, TV_CLK, 38, 33, 0, 18, 146, 26,
 	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
-    },
-
-    {
+    }, {
 	/* 640x240 @ 60Hz (NTSC) */
 	/* XXX: Broken! Don't use... */
 	"ntsc_640x240", 60, 640, 240, TV_CLK, 38, 33, 0, 0, 146, 22,
 	FB_SYNC_BROADCAST, FB_VMODE_YWRAP
-    },
-
-    {
+    }, {
 	/* 640x480 @ 60hz (VGA) */
 	"vga_640x480", 60, 640, 480, VGA_CLK, 38, 33, 0, 18, 146, 26,
 	0, FB_VMODE_YWRAP
-    },
-
+    }, 
 };
 
 #define NUM_TOTAL_MODES  ARRAY_SIZE(pvr2_modedb)
@@ -301,222 +241,10 @@
 static int defmode = DEFMODE_NTSC;
 static char *mode_option __initdata = NULL;
 
-/* Get the fixed part of the display */
-
-static int pvr2fb_get_fix(struct fb_fix_screeninfo *fix, int con,
-                            struct fb_info *info)
-{
-	struct pvr2fb_par par;
-
-	if (con == -1)
-		pvr2_get_par(&par);
-	else {
-		int err;
-
-		if ((err = pvr2_decode_var(&fb_display[con].var, &par)))
-			return err;
-	}
-	return pvr2_encode_fix(fix, &par);
-}
-
-/* Get the user-defined part of the display */
-
-static int pvr2fb_get_var(struct fb_var_screeninfo *var, int con,
-                            struct fb_info *info)
-{
-	int err = 0;
-
-	if (con == -1) {
-		struct pvr2fb_par par;
-
-		pvr2_get_par(&par);
-		err = pvr2_encode_var(var, &par);
-	} else
-		*var = fb_display[con].var;
-	
-	return err;
-}
-
-/* Set the user-defined part of the display */
-
-static int pvr2fb_set_var(struct fb_var_screeninfo *var, int con,
-                            struct fb_info *info)
-{
-	int err, activate = var->activate;
-	int oldxres, oldyres, oldvxres, oldvyres, oldbpp;
-	struct pvr2fb_par par;
-
-	struct display *display;
-	if (con >= 0)
-		display = &fb_display[con];
-	else
-		display = &disp;        /* used during initialization */
-
-	/*
-	 * FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
-	 * as FB_VMODE_SMOOTH_XPAN is only used internally
-	 */
-
-	if (var->vmode & FB_VMODE_CONUPDATE) {
-		var->vmode |= FB_VMODE_YWRAP;
-		var->xoffset = display->var.xoffset;
-		var->yoffset = display->var.yoffset;
-	}
-	if ((err = pvr2_decode_var(var, &par)))
-		return err;
-	pvr2_encode_var(var, &par);
-
-	/* Do memory check and bitfield set here?? */
-
-	if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-		oldxres = display->var.xres;
-		oldyres = display->var.yres;
-		oldvxres = display->var.xres_virtual;
-		oldvyres = display->var.yres_virtual;
-		oldbpp = display->var.bits_per_pixel;
-		display->var = *var;
-		if (oldxres != var->xres || oldyres != var->yres ||
-		    oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
-		    oldbpp != var->bits_per_pixel) {
-			struct fb_fix_screeninfo fix;
-
-			pvr2_encode_fix(&fix, &par);
-			display->scrollmode = SCROLL_YREDRAW;
-			display->visual = fix.visual;
-			display->type = fix.type;
-			display->type_aux = fix.type_aux;
-			display->ypanstep = fix.ypanstep;
-			display->ywrapstep = fix.ywrapstep;
-			display->line_length = fix.line_length;
-			display->can_soft_blank = 1;
-			display->inverse = pvr2fb_inverse;
-			switch (var->bits_per_pixel) {
-#ifdef FBCON_HAS_CFB16
-			    case 16:
-				display->dispsw = &fbcon_cfb16;
-				display->dispsw_data = fbcon_cmap.cfb16;
-				break;
-#endif
-#ifdef FBCON_HAS_CFB24
-			    case 24:
-				display->dispsw = &fbcon_cfb24;
-				display->dispsw_data = fbcon_cmap.cfb24;
-				break;
-#endif
-#ifdef FBCON_HAS_CFB32
-			    case 32:
-				display->dispsw = &fbcon_cfb32;
-				display->dispsw_data = fbcon_cmap.cfb32;
-				break;
-#endif
-			    default:
-				display->dispsw = &fbcon_dummy;
-				break;
-			}
-			if (fb_info.changevar)
-				(*fb_info.changevar)(con);
-		}
-		if (oldbpp != var->bits_per_pixel) {
-			if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
-				return err;
-			do_install_cmap(con, info);
-		}
-		if (con == info->currcon)
-			pvr2_set_var(&display->var);
-	}
-
-	return 0;
-}
-
-/*
- * Pan or wrap the display.
- * This call looks only at xoffset, yoffset and the FB_VMODE_YRAP flag
- */
-
-static int pvr2fb_pan_display(struct fb_var_screeninfo *var, int con,
-                                struct fb_info *info)
-{
-	if (var->vmode & FB_VMODE_YWRAP) {
-		if (var->yoffset<0 || var->yoffset >=
-		    fb_display[con].var.yres_virtual || var->xoffset)
-			return -EINVAL;
-	 } else {
-		if (var->xoffset+fb_display[con].var.xres >
-		    fb_display[con].var.xres_virtual ||
-		    var->yoffset+fb_display[con].var.yres >
-		    fb_display[con].var.yres_virtual)
-		    return -EINVAL;
-	}
-	if (con == info->currcon)
-		pvr2_pan_var(var);
-	fb_display[con].var.xoffset = var->xoffset;
-	fb_display[con].var.yoffset = var->yoffset;
-	if (var->vmode & FB_VMODE_YWRAP)
-		fb_display[con].var.vmode |= FB_VMODE_YWRAP;
-	else
-		fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
-			
-	return 0;
-}
-
-/* Get the colormap */
-
-static int pvr2fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-                             struct fb_info *info)
-{
-	if (con == info->currcon) /* current console? */
-		return fb_get_cmap(cmap, kspc, pvr2_getcolreg, info);
-	else if (fb_display[con].cmap.len) /* non default colormap? */
-		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-	else
-		fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-		             cmap, kspc ? 0 : 2);
-	return 0;
-}
-
-/* Set the colormap */
-
-static int pvr2fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-	                     struct fb_info *info)
-{
-	int err;
-
-	if (!fb_display[con].cmap.len) {        /* no colormap allocated? */
-		if ((err = fb_alloc_cmap(&fb_display[con].cmap,
-		                         1<<fb_display[con].var.bits_per_pixel,
-					 0)))
-			 return err;
-	}
-	if (con == info->currcon)                     /* current console? */
-		return fb_set_cmap(cmap, kspc, info);
-	else
-		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
-
-	return 0;
-}
-
-static int pvr2fbcon_switch(int con, struct fb_info *info)
-{
-	/* Do we have to save the colormap? */
-	if (fb_display[info->currcon].cmap.len)
-		fb_get_cmap(&fb_display[info->currcon].cmap, 1, pvr2_getcolreg, info);
-
-	info->currcon = con;
-	pvr2_set_var(&fb_display[con].var);
-	/* Install new colormap */
-	do_install_cmap(con, info);
-	return 0;
-}
-
-static int pvr2fbcon_updatevar(int con, struct fb_info *info)
-{
-	pvr2_pan_var(&fb_display[con].var);
-	return 0;
-}
-
 static int pvr2fb_blank(int blank, struct fb_info *info)
 {
 	do_blank = blank ? blank : -1;
+	return 0;
 }
 
 static inline u_long get_line_length(int xres_virtual, int bpp)
@@ -548,52 +276,29 @@
 	}
 }
 
-static int pvr2_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-                            u_int *transp, struct fb_info *info)
-{
-	if (regno > 255)
-	    return 1;
-	
-	*red = palette[regno].red;
-	*green = palette[regno].green;
-	*blue = palette[regno].blue;
-	*transp = 0;
-	return 0;
-}
-	
 static int pvr2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                             u_int transp, struct fb_info *info)
 {
 	if (regno > 255)
 		return 1;
 
-	palette[regno].red = red;
-	palette[regno].green = green;
-	palette[regno].blue = blue;
-
 	if (regno < 16) {
-		switch (currbpp) {
-#ifdef FBCON_HAS_CFB16
+		switch (info->var.bits_per_pixel) {
 		    case 16: /* RGB 565 */
-			fbcon_cmap.cfb16[regno] = (red & 0xf800) |
-			                          ((green & 0xfc00) >> 5) |
+			((u16*)(info->pseudo_palette))[regno] = (red & 0xf800) |
+						((green & 0xfc00) >> 5) |
 						  ((blue & 0xf800) >> 11);
 			break;
-#endif
-#ifdef FBCON_HAS_CFB24
 		    case 24: /* RGB 888 */
 			red >>= 8; green >>= 8; blue >>= 8;
-			fbcon_cmap.cfb24[regno] = (red << 16) | (green << 8) | blue;
+			((u32*)(info->pseudo_palette))[regno] = (red << 16) | (green << 8) | blue;
 			break;
-#endif
-#ifdef FBCON_HAS_CFB32
 		    case 32: /* ARGB 8888 */
 			red >>= 8; green >>= 8; blue >>= 8;
-			fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | blue;
+			((u32*)(info->pseudo_palette))[regno] = (transp << 24) |(red << 16) | (green << 8) | blue;
 			break;
-#endif
 		    default:
-			DPRINTK("Invalid bit depth %d?!?\n", currbpp);
+			DPRINTK("Invalid bit depth %d?!?\n", info->var.bits_per_pixel);
 			return 1;
 		}
 	}
@@ -601,85 +306,33 @@
 	return 0;
 }
 
-
-static int pvr2_encode_fix(struct fb_fix_screeninfo *fix,
-                             struct pvr2fb_par *par)
-{
-	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-	strcpy(fix->id, pvr2fb_name);
-	fix->smem_start = videomemory;
-	fix->smem_len = videomemorysize;
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->type_aux = 0;
-	fix->visual = FB_VISUAL_TRUECOLOR;
-
-	if (par->vmode & FB_VMODE_YWRAP) {
-		fix->ywrapstep = 1;
-		fix->xpanstep = fix->ypanstep = 0;
-	} else {
-		fix->ywrapstep = 0;
-		fix->xpanstep = 1;
-		fix->ypanstep = 1;
-	}
-	fix->line_length = par->next_line;
-
-	return 0;
-}
-
-/*
- * Create a hardware video mode using the framebuffer values.  If a value needs
- * to be clipped or constrained it's done here.  This routine needs a bit more
- * work to make sure we're doing the right tests at the right time.
- */
-static int pvr2_decode_var(struct fb_var_screeninfo *var,
-                             struct pvr2fb_par *par)
+static int pvr2fb_set_par(struct fb_info *info)
 {
+	struct pvr2fb_par *par = (struct pvr2fb_par *)info->par;
+	struct fb_var_screeninfo *var = &info->var;
 	u_long line_length;
 	u_short vtotal;
 
-	if (var->pixclock != TV_CLK && var->pixclock != VGA_CLK) {
-		DPRINTK("Invalid pixclock value %d\n", var->pixclock);
-		return -EINVAL;
-	}
-	par->pixclock = var->pixclock;
-	
-	if ((par->xres = var->xres) < 320)
-		par->xres = 320;
-	if ((par->yres = var->yres) < 240)
-		par->yres = 240;
-	if ((par->vxres = var->xres_virtual) < par->xres)
-		par->vxres = par->xres;
-	if ((par->vyres = var->yres_virtual) < par->yres)
-		par->vyres = par->yres;
-
-	if ((par->bpp = var->bits_per_pixel) <= 16)
-		par->bpp = 16;
-	else if ((par->bpp = var->bits_per_pixel) <= 24)
-		par->bpp = 24;
-	else if ((par->bpp = var->bits_per_pixel) <= 32)
-		par->bpp = 32;
-
-	currbpp = par->bpp;
-
 	/*
 	 * XXX: It's possible that a user could use a VGA box, change the cable
-	 * type in hardware (i.e. switch from VGA<->composite), then change modes
-	 * (i.e. switching to another VT).  If that happens we should automagically
-	 * change the output format to cope, but currently I don't have a VGA box
-	 * to make sure this works properly.
+	 * type in hardware (i.e. switch from VGA<->composite), then change
+	 * modes (i.e. switching to another VT).  If that happens we should
+	 * automagically change the output format to cope, but currently I
+	 * don't have a VGA box to make sure this works properly.
 	 */
 	cable_type = pvr2_init_cable();
 	if (cable_type == CT_VGA && video_output != VO_VGA)
 		video_output = VO_VGA;
 
-	par->vmode = var->vmode & FB_VMODE_MASK;
-	if (par->vmode & FB_VMODE_INTERLACED && video_output != VO_VGA)
+	var->vmode &= FB_VMODE_MASK;
+	if (var->vmode & FB_VMODE_INTERLACED && video_output != VO_VGA)
 		par->is_interlaced = 1;
 	/* 
 	 * XXX: Need to be more creative with this (i.e. allow doublecan for
 	 * PAL/NTSC output).
 	 */
-	par->is_doublescan = (par->yres < 480 && video_output == VO_VGA);
+	if (var->vmode & FB_VMODE_DOUBLE && video_output == VO_VGA)
+		par->is_doublescan = 1;
 	
 	par->hsync_total = var->left_margin + var->xres + var->right_margin +
 	                   var->hsync_len;
@@ -691,22 +344,12 @@
 		if (par->is_interlaced)
 			vtotal /= 2;
 		if (vtotal > (PAL_VTOTAL + NTSC_VTOTAL)/2) {
-			/* PAL video output */
-			/* XXX: Should be using a range here ... ? */
-			if (par->hsync_total != PAL_HTOTAL) {
-				DPRINTK("invalid hsync total for PAL\n");
-				return -EINVAL;
-			}
 			/* XXX: Check for start values here... */
 			/* XXX: Check hardware for PAL-compatibility */
 			par->borderstart_h = 116;
 			par->borderstart_v = 44;
 		} else {
 			/* NTSC video output */
-			if (par->hsync_total != NTSC_HTOTAL) {
-				DPRINTK("invalid hsync total for NTSC\n");
-				return -EINVAL;
-			}
 			par->borderstart_h = 126;
 			par->borderstart_v = 18;
 		}
@@ -714,155 +357,123 @@
 		/* VGA mode */
 		/* XXX: What else needs to be checked? */
 		/* 
-		 * XXX: We have a little freedom in VGA modes, what ranges should
-		 * be here (i.e. hsync/vsync totals, etc.)?
+		 * XXX: We have a little freedom in VGA modes, what ranges
+		 * should be here (i.e. hsync/vsync totals, etc.)?
 		 */
 		par->borderstart_h = 126;
 		par->borderstart_v = 40;
 	}
 
 	/* Calculate the remainding offsets */
-	par->borderstop_h = par->borderstart_h + par->hsync_total -
-	                    var->hsync_len;
-	par->borderstop_v = par->borderstart_v + par->vsync_total -
-	                    var->vsync_len;
 	par->diwstart_h = par->borderstart_h + var->left_margin;
 	par->diwstart_v = par->borderstart_v + var->upper_margin;
+	par->borderstop_h = par->diwstart_h + var->xres + 
+			    var->right_margin;    
+	par->borderstop_v = par->diwstart_v + var->yres +
+			    var->lower_margin;
+
 	if (!par->is_interlaced)
 		par->borderstop_v /= 2;
-
-	if (par->xres < 640)
+	if (info->var.xres < 640)
 		par->is_lowres = 1;
 
-	/* XXX: Needs testing. */
-	if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
-		par->xoffset = var->xoffset;
-		par->yoffset = var->yoffset;
-		if (par->vmode & FB_VMODE_YWRAP) {
-			if (par->xoffset || par->yoffset < 0 || par->yoffset >=
-			    par->vyres)
-				par->xoffset = par->yoffset = 0;
-		} else {
-			if (par->xoffset < 0 || par->xoffset > par->vxres-par->xres ||
-			    par->yoffset < 0 || par->yoffset > par->vyres-par->yres)
-				par->xoffset = par->yoffset = 0;
-		}
-	} else
-		par->xoffset = par->yoffset = 0;
-
-	/* Check memory sizes */
 	line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
-	if (line_length * var->yres_virtual > videomemorysize)
-		return -ENOMEM;
-	par->disp_start = videomemory + (get_line_length(par->vxres, par->bpp) *
-	                  par->yoffset) * get_line_length(par->xoffset, par->bpp);
-	par->next_line = line_length;
-	
+	par->disp_start = videomemory + (line_length * var->yoffset) * line_length;
+	info->fix.line_length = line_length;
 	return 0;
 }
 
-static int pvr2_encode_var(struct fb_var_screeninfo *var,
-                             struct pvr2fb_par *par)
+static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-	memset(var, 0, sizeof(struct fb_var_screeninfo));
+	u_short vtotal, hsync_total;
+	u_long line_length;
 
-	var->xres = par->xres;
-	var->yres = par->yres;
-	var->xres_virtual = par->vxres;
-	var->yres_virtual = par->vyres;
-	var->xoffset = par->xoffset;
-	var->yoffset = par->yoffset;
+	if (var->pixclock != TV_CLK || var->pixclock != VGA_CLK) {
+		DPRINTK("Invalid pixclock value %d\n", var->pixclock);
+		return -EINVAL;
+	}
 
-	var->bits_per_pixel = par->bpp;
-	set_color_bitfields(var);
+	if (var->xres < 320)
+		var->xres = 320;
+	if (var->yres < 240)
+		var->yres = 240;
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+
+	if (var->bits_per_pixel <= 16)
+		var->bits_per_pixel = 16;
+	else if (var->bits_per_pixel <= 24)
+		var->bits_per_pixel = 24;
+	else if (var->bits_per_pixel <= 32)
+		var->bits_per_pixel = 32;
 
-	var->activate = FB_ACTIVATE_NOW;
-	var->height = -1;
-	var->width = -1;
+	set_color_bitfields(var);
 
-	var->pixclock = par->pixclock;
+	if (var->vmode & FB_VMODE_YWRAP) {
+		if (var->xoffset || var->yoffset < 0 || 
+		    var->yoffset >= var->yres_virtual) {
+			var->xoffset = var->yoffset = 0;
+		} else {
+			if (var->xoffset > var->xres_virtual - var->xres ||
+		    	    var->yoffset > var->yres_virtual - var->yres || 
+			    var->xoffset < 0 || var->yoffset < 0)
+				var->xoffset = var->yoffset = 0;
+		}
+	} else {
+		var->xoffset = var->yoffset = 0;
+	}
 
-	if (par->is_doublescan)
+	/* 
+	 * XXX: Need to be more creative with this (i.e. allow doublecan for
+	 * PAL/NTSC output).
+	 */
+	if (var->yres < 480 && video_output == VO_VGA)
 		var->vmode = FB_VMODE_DOUBLE;
 
-	if (par->is_interlaced)
-		var->vmode |= FB_VMODE_INTERLACED;
-	else
-		var->vmode |= FB_VMODE_NONINTERLACED;
-
-	var->right_margin = par->borderstop_h - (par->diwstart_h + par->xres);
-	var->left_margin = par->diwstart_h - par->borderstart_h;
-	var->hsync_len = par->borderstart_h + (par->hsync_total - par->borderstop_h);
-	var->upper_margin = par->diwstart_v - par->borderstart_v;
-	var->lower_margin = par->borderstop_v - (par->diwstart_v + par->yres);
-	var->vsync_len = par->borderstart_v + (par->vsync_total - par->borderstop_v);
 	if (video_output != VO_VGA)
-		var->sync = FB_SYNC_BROADCAST;
-
-	if (par->vmode & FB_VMODE_YWRAP)
-		var->vmode |= FB_VMODE_YWRAP;
-	
-	return 0;
-}
-
-static void pvr2_get_par(struct pvr2fb_par *par)
-{
-	*par = currentpar;
-}
-
-/* Setup the new videomode in hardware */
-
-static void pvr2_set_var(struct fb_var_screeninfo *var)
-{
-	do_vmode_pan = 0;
-	do_vmode_full = 0;
-	pvr2_decode_var(var, &currentpar);
-
-	do_vmode_full = 1;
-}
-
-/* 
- * Pan or wrap the display
- * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag in `var'.
- */
-static void pvr2_pan_var(struct fb_var_screeninfo *var)
-{
-	struct pvr2fb_par *par = &currentpar;
+		var->sync = FB_SYNC_BROADCAST | FB_VMODE_INTERLACED;
 
-	par->xoffset = var->xoffset;
-	par->yoffset = var->yoffset;
-	if (var->vmode & FB_VMODE_YWRAP)
-		par->vmode |= FB_VMODE_YWRAP;
-	else
-		par->vmode &= ~FB_VMODE_YWRAP;
-
-	do_vmode_pan = 0;
-	pvr2_update_par();
-	do_vmode_pan = 1;
-}
-
-static int pvr2_update_par(void)
-{
-	struct pvr2fb_par *par = &currentpar;
-	u_long move;
-
-	move = get_line_length(par->xoffset, par->bpp);
-	if (par->yoffset) {
-		par->disp_start += (par->next_line * par->yoffset) + move;
-	} else
-		par->disp_start += move;
+	hsync_total = var->left_margin + var->xres + var->right_margin +
+		      var->hsync_len;
+	vtotal = var->upper_margin + var->yres + var->lower_margin +
+		 var->vsync_len;
 
+	if (var->sync & FB_SYNC_BROADCAST) {
+		if (var->vmode & FB_VMODE_INTERLACED)
+			vtotal /= 2;
+		if (vtotal > (PAL_VTOTAL + NTSC_VTOTAL)/2) {
+			/* PAL video output */
+			/* XXX: Should be using a range here ... ? */
+			if (hsync_total != PAL_HTOTAL) {
+				DPRINTK("invalid hsync total for PAL\n");
+				return -EINVAL;
+			}
+		} else {
+			/* NTSC video output */
+			if (hsync_total != NTSC_HTOTAL) {
+				DPRINTK("invalid hsync total for NTSC\n");
+				return -EINVAL;
+			}
+		}
+	}
+	/* Check memory sizes */
+	line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
+	if (line_length * var->yres_virtual > videomemorysize)
+		return -ENOMEM;
 	return 0;
 }
 
-static void pvr2_update_display(void)
+static void pvr2_update_display(struct fb_info *info)
 {
-	struct pvr2fb_par *par = &currentpar;
+	struct pvr2fb_par *par = (struct pvr2fb_par *) info->par;
+	struct fb_var_screeninfo *var = &info->var;
 
 	/* Update the start address of the display image */
 	ctrl_outl(par->disp_start, DISP_DIWADDRL);
 	ctrl_outl(par->disp_start +
-		  get_line_length(par->xoffset + par->xres, par->bpp),
+		  get_line_length(var->xoffset+var->xres, var->bits_per_pixel),
 	          DISP_DIWADDRS);
 }
 
@@ -872,11 +483,12 @@
  * registers are still undocumented.
  */
 
-static void pvr2_init_display(void)
+static void pvr2_init_display(struct fb_info *info)
 {
-	struct pvr2fb_par *par = &currentpar;
+	struct pvr2fb_par *par = (struct pvr2fb_par *) info->par;
+	struct fb_var_screeninfo *var = &info->var;
 	u_short diw_height, diw_width, diw_modulo = 1;
-	u_short bytesperpixel = par->bpp / 8;
+	u_short bytesperpixel = var->bits_per_pixel >> 3;
 
 	/* hsync and vsync totals */
 	ctrl_outl((par->vsync_total << 16) | par->hsync_total, DISP_SYNCSIZE);
@@ -885,16 +497,16 @@
 	/* since we're "panning" within vram, we need to offset things based
 	 * on the offset from the virtual x start to our real gfx. */
 	if (video_output != VO_VGA && par->is_interlaced)
-		diw_modulo += par->next_line / 4;
-	diw_height = (par->is_interlaced ? par->yres / 2 : par->yres);
-	diw_width = get_line_length(par->xres, par->bpp) / 4;
+		diw_modulo += info->fix.line_length / 4;
+	diw_height = (par->is_interlaced ? var->yres / 2 : var->yres);
+	diw_width = get_line_length(var->xres, var->bits_per_pixel) / 4;
 	ctrl_outl((diw_modulo << 20) | (--diw_height << 10) | --diw_width,
 	          DISP_DIWSIZE);
 
 	/* display address, long and short fields */
 	ctrl_outl(par->disp_start, DISP_DIWADDRL);
 	ctrl_outl(par->disp_start +
-	          get_line_length(par->xoffset + par->xres, par->bpp),
+	          get_line_length(var->xoffset+var->xres, var->bits_per_pixel),
 	          DISP_DIWADDRS);
 
 	/* border horizontal, border vertical, border color */
@@ -919,7 +531,6 @@
 	/* video enable, color sync, interlace, 
 	 * hsync and vsync polarity (currently unused) */
 	ctrl_outl(0x100 | ((par->is_interlaced /*|4*/) << 4), DISP_SYNCCONF);
-
 }
 
 /* Simulate blanking by making the border cover the entire screen */
@@ -941,23 +552,20 @@
 
 static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id, struct pt_regs *fp)
 {
-	if (do_vmode_pan || do_vmode_full)
-		pvr2_update_display();
+	struct fb_info *info = dev_id;
 
+	if (do_vmode_pan || do_vmode_full)
+		pvr2_update_display(info);
 	if (do_vmode_full)
-		pvr2_init_display();
-
+		pvr2_init_display(info);
 	if (do_vmode_pan)
 		do_vmode_pan = 0;
-
+	if (do_vmode_full)
+		do_vmode_full = 0;
 	if (do_blank) {
 		pvr2_do_blank();
 		do_blank = 0;
 	}
-
-	if (do_vmode_full) {
-		do_vmode_full = 0;
-	}
 	return IRQ_HANDLED;
 }
 
@@ -991,94 +599,120 @@
 
 int __init pvr2fb_init(void)
 {
-	struct fb_var_screeninfo var;
 	u_long modememused;
+	int err = -EINVAL;
 
-	if (!MACH_DREAMCAST)
+	if (!mach_is_dreamcast())
 		return -ENXIO;
 
+	fb_info = kmalloc(sizeof(struct fb_info) + sizeof(struct pvr2fb_par) +
+			  sizeof(u32) * 16, GFP_KERNEL);
+	
+	if (!fb_info) {
+		printk(KERN_ERR "Failed to allocate memory for fb_info\n");
+		return -ENOMEM;
+	}
+
+	memset(fb_info, 0, sizeof(fb_info) + sizeof(struct pvr2fb_par) + sizeof(u32) * 16);
+
+	currentpar = (struct pvr2fb_par *)(fb_info + 1);
+
 	/* Make a guess at the monitor based on the attached cable */
 	if (pvr2_init_cable() == CT_VGA) {
-		fb_info.monspecs.hfmin = 30000;
-		fb_info.monspecs.hfmax = 70000;
-		fb_info.monspecs.vfmin = 60;
-		fb_info.monspecs.vfmax = 60;
-	}
-	else { /* Not VGA, using a TV (taken from acornfb) */
-		fb_info.monspecs.hfmin = 15469;
-		fb_info.monspecs.hfmax = 15781;
-		fb_info.monspecs.vfmin = 49;
-		fb_info.monspecs.vfmax = 51;
+		fb_info->monspecs.hfmin = 30000;
+		fb_info->monspecs.hfmax = 70000;
+		fb_info->monspecs.vfmin = 60;
+		fb_info->monspecs.vfmax = 60;
+	} else {
+		/* Not VGA, using a TV (taken from acornfb) */
+		fb_info->monspecs.hfmin = 15469;
+		fb_info->monspecs.hfmax = 15781;
+		fb_info->monspecs.vfmin = 49;
+		fb_info->monspecs.vfmax = 51;
 	}
 
-	/* XXX: This needs to pull default video output via BIOS or other means */
+	/*
+	 * XXX: This needs to pull default video output via BIOS or other means
+	 */
 	if (video_output < 0) {
-		if (cable_type == CT_VGA)
+		if (cable_type == CT_VGA) {
 			video_output = VO_VGA;
-		else
+		} else {
 			video_output = VO_NTSC;
+		}
 	}
 	
-	strcpy(fb_info.modename, pvr2fb_name);
-	fb_info.changevar = NULL;
-	fb_info.fbops = &pvr2fb_ops;
-	fb_info.screen_base = (char *) videomemory;
-	fb_info.disp = &disp;
-	fb_info.currcon = -1;
-	fb_info.switch_con = &pvr2fbcon_switch;
-	fb_info.updatevar = &pvr2fbcon_updatevar;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
-	memset(&var, 0, sizeof(var));
+	pvr2_fix.smem_start = videomemory;
+	pvr2_fix.smem_len = videomemorysize;
+
+	fb_info->screen_base = ioremap_nocache(pvr2_fix.smem_start,
+					       pvr2_fix.smem_len);
+	
+	if (!fb_info->screen_base) {
+		printk("Failed to remap MMIO space\n");
+		err = -ENXIO;
+		goto out_err;
+	}
+
+	memset_io((unsigned long)fb_info->screen_base, 0, pvr2_fix.smem_len);
+
+	pvr2_fix.ypanstep	= nopan  ? 0 : 1;
+	pvr2_fix.ywrapstep	= nowrap ? 0 : 1;
+
+	fb_info->fbops		= &pvr2fb_ops;
+	fb_info->fix		= pvr2_fix;
+	fb_info->par		= currentpar;
+	fb_info->pseudo_palette	= (void *)(fb_info->par + 1);
+	fb_info->flags		= FBINFO_FLAG_DEFAULT;
 
 	if (video_output == VO_VGA)
 		defmode = DEFMODE_VGA;
 
-	if (!fb_find_mode(&var, &fb_info, mode_option, pvr2_modedb,
-	                  NUM_TOTAL_MODES, &pvr2_modedb[defmode], 16)) {
-		return -EINVAL;
-	}
+	if (!mode_option)
+		mode_option = "640x480@60";
 
-	if (request_irq(HW_EVENT_VSYNC, pvr2fb_interrupt, 0,
-	                "pvr2 VBL handler", &currentpar)) {
-		DPRINTK("couldn't register VBL int\n");
-		return -EBUSY;
-	}
+	if (!fb_find_mode(&fb_info->var, fb_info, mode_option, pvr2_modedb,
+	                  NUM_TOTAL_MODES, &pvr2_modedb[defmode], 16))
+		fb_info->var = pvr2_var;
 
-#ifdef CONFIG_MTRR
-	if (enable_mtrr) {
-		mtrr_handle = mtrr_add(videomemory, videomemorysize, MTRR_TYPE_WRCOMB, 1);
-		printk("pvr2fb: MTRR turned on\n");
+	if (request_irq(HW_EVENT_VSYNC, pvr2fb_interrupt, 0,
+	                "pvr2 VBL handler", fb_info)) {
+		err = -EBUSY;
+		goto out_err;
 	}
-#endif
 
-	pvr2fb_set_var(&var, -1, &fb_info);
+	if (register_framebuffer(fb_info) < 0)
+		goto reg_failed;
 
-	if (register_framebuffer(&fb_info) < 0)
-		return -EINVAL;
+	modememused = get_line_length(fb_info->var.xres_virtual,
+				      fb_info->var.bits_per_pixel);
+	modememused *= fb_info->var.yres_virtual;
 
-	modememused = get_line_length(var.xres_virtual, var.bits_per_pixel);
-	modememused *= var.yres_virtual;
 	printk("fb%d: %s frame buffer device, using %ldk/%ldk of video memory\n",
-	       fb_info.node, fb_info.modename, modememused>>10,
+	       fb_info->node, fb_info->fix.id, modememused>>10,
 	       videomemorysize>>10);
 	printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n", 
-	       fb_info.node, var.xres, var.yres, var.bits_per_pixel, 
-	       get_line_length(var.xres, var.bits_per_pixel),
+	       fb_info->node, fb_info->var.xres, fb_info->var.yres,
+	       fb_info->var.bits_per_pixel, 
+	       get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel),
 	       (char *)pvr2_get_param(cables, NULL, cable_type, 3),
 	       (char *)pvr2_get_param(outputs, NULL, video_output, 3));
 
 	return 0;
+
+reg_failed:
+	free_irq(HW_EVENT_VSYNC, 0);
+out_err:
+	kfree(fb_info);
+
+	return err;
 }
 
 static void __exit pvr2fb_exit(void)
 {
-#ifdef CONFIG_MTRR
-	if (enable_mtrr) {
-		mtrr_del(mtrr_handle, videomemory, videomemorysize);
-		printk("pvr2fb: MTRR turned off\n");
-	}
-#endif
-	unregister_framebuffer(&fb_info);
+	unregister_framebuffer(fb_info);
+	free_irq(HW_EVENT_VSYNC, 0);
+	kfree(fb_info);
 }
 
 static int __init pvr2_get_param(const struct pvr2_params *p, const char *s,
@@ -1102,7 +736,6 @@
  * Parse command arguments.  Supported arguments are:
  *    inverse                             Use inverse color maps
  *    nomtrr                              Disable MTRR usage
- *    font:<fontname>                     Specify console font
  *    cable:composite|rgb|vga             Override the video cable type
  *    output:NTSC|PAL|VGA                 Override the video output format
  *
@@ -1117,8 +750,6 @@
 	char cable_arg[80];
 	char output_arg[80];
 
-	fb_info.fontname[0] = '\0';
-
 	if (!options || !*options)
 		return 0;
 
@@ -1128,23 +759,21 @@
 		if (!strcmp(this_opt, "inverse")) {
 			pvr2fb_inverse = 1;
 			fb_invert_cmaps();
-		} else if (!strncmp(this_opt, "font:", 5))
-			strcpy(fb_info.fontname, this_opt + 5);
-		else if (!strncmp(this_opt, "cable:", 6))
+		} else if (!strncmp(this_opt, "cable:", 6)) {
 			strcpy(cable_arg, this_opt + 6);
-		else if (!strncmp(this_opt, "output:", 7))
+		} else if (!strncmp(this_opt, "output:", 7)) {
 			strcpy(output_arg, this_opt + 7);
-#ifdef CONFIG_MTRR
-		else if (!strncmp(this_opt, "nomtrr", 6))
-			enable_mtrr = 0;
-#endif
-		else
+		} else if (!strncmp(this_opt, "nopan", 5)) {
+			nopan = 1;
+		} else if (!strncmp(this_opt, "nowrap", 6)) {
+			nowrap = 1;
+		} else {
 			mode_option = this_opt;
+		}
 	}
 
 	if (*cable_arg)
 		cable_type = pvr2_get_param(cables, cable_arg, 0, 3);
-
 	if (*output_arg)
 		video_output = pvr2_get_param(outputs, output_arg, 0, 3);
 
diff -Nru a/drivers/video/vesafb.c b/drivers/video/vesafb.c
--- a/drivers/video/vesafb.c	Sat Jul 19 12:54:22 2003
+++ b/drivers/video/vesafb.c	Sat Jul 19 12:54:22 2003
@@ -51,7 +51,7 @@
 static u32 pseudo_palette[17];
 
 static int             inverse   = 0;
-static int             mtrr      = 0;
+static int             mtrr      = 1;
 
 static int             pmi_setpal = 0;	/* pmi for palette changes ??? */
 static int             ypan       = 0;  /* 0..nothing, 1..ypan, 2..ywrap */
@@ -208,6 +208,8 @@
 			pmi_setpal=1;
 		else if (! strcmp(this_opt, "mtrr"))
 			mtrr=1;
+		else if (! strcmp(this_opt, "nomtrr"))
+			mtrr=0;
 	}
 	return 0;
 }
@@ -230,6 +232,12 @@
 	vesafb_fix.smem_len = screen_info.lfb_size * 65536;
 	vesafb_fix.visual   = (vesafb_defined.bits_per_pixel == 8) ?
 		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+
+	/* limit framebuffer size to 16 MB.  Otherwise we'll eat tons of
+	 * kernel address space for nothing if the gfx card has alot of
+	 * memory (>= 128 MB isn't uncommon these days ...) */
+	if (vesafb_fix.smem_len > 16 * 1024 * 1024)
+		vesafb_fix.smem_len = 16 * 1024 * 1024;
 
 #ifndef __i386__
 	screen_info.vesapm_seg = 0;
diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
--- a/fs/binfmt_elf.c	Sat Jul 19 12:54:25 2003
+++ b/fs/binfmt_elf.c	Sat Jul 19 12:54:25 2003
@@ -1158,7 +1158,7 @@
 	t->num_notes++;
 	sz += notesize(&t->notes[0]);
 
-	if ((t->prstatus.pr_fpvalid = elf_core_copy_task_fpregs(p, &t->fpu))) {
+	if ((t->prstatus.pr_fpvalid = elf_core_copy_task_fpregs(p, NULL, &t->fpu))) {
 		fill_note(&t->notes[1], "CORE", NT_PRFPREG, sizeof(t->fpu), &(t->fpu));
 		t->num_notes++;
 		sz += notesize(&t->notes[1]);
@@ -1286,7 +1286,7 @@
 	fill_note(notes +2, "CORE", NT_TASKSTRUCT, sizeof(*current), current);
   
   	/* Try to dump the FPU. */
-	if ((prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, fpu)))
+	if ((prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, regs, fpu)))
 		fill_note(notes +3, "CORE", NT_PRFPREG, sizeof(*fpu), fpu);
 	else
 		--numnote;
diff -Nru a/fs/bio.c b/fs/bio.c
--- a/fs/bio.c	Sat Jul 19 12:54:25 2003
+++ b/fs/bio.c	Sat Jul 19 12:54:25 2003
@@ -18,7 +18,7 @@
 #include <linux/mm.h>
 #include <linux/swap.h>
 #include <linux/bio.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES
--- a/fs/cifs/CHANGES	Sat Jul 19 12:54:27 2003
+++ b/fs/cifs/CHANGES	Sat Jul 19 12:54:27 2003
@@ -1,3 +1,12 @@
+Version 0.83
+------------
+Fix oops when mounting to long server names caused by inverted parms to kmalloc.
+Fix MultiuserMount (/proc/fs/cifs configuration setting) so that when enabled
+we will choose a cifs user session (smb uid) that better matches the local
+uid if a) the mount uid does not match the current uid and b) we have another
+session to the same server (ip address) for a different mount which
+matches the current local uid.
+
 Version 0.82
 ------------
 Add support for mknod of block or character devices.  Fix oplock
diff -Nru a/fs/cifs/TODO b/fs/cifs/TODO
--- a/fs/cifs/TODO	Sat Jul 19 12:54:29 2003
+++ b/fs/cifs/TODO	Sat Jul 19 12:54:29 2003
@@ -17,9 +17,12 @@
 
 d) Kerberos/SPNEGO session setup support - (started)
 
-e) NTLMv2 authentication and MD5-HMAC signing SMB PDUs - (mostly implemented)
-	signing necessary for some Windows 2003 servers in domain 
-	mode.
+e) NTLMv2 authentication (mostly implemented)
+
+f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup 
+used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
+	and raw NTLMSSP already. This is important when enabling
+	extended security and mounting to Windows 2003 Servers
 
 f) Directory entry caching relies on a 1 second timer, rather than 
 using FindNotify or equivalent.  - (started)
@@ -43,11 +46,9 @@
 
 m) finish support for IPv6
 
-n) send oplock break response when sent (oplock currently disabled in
-/proc/fs/cifs)
-
-o) reduces the oplock breaks coming from windows).  Piggyback identical
-file opens on top of each other by incrementing reference count rather
+o) Better optimize open (and pathbased setfilesize) to reduce the
+oplock breaks coming from windows srv.  Piggyback identical file
+opens on top of each other by incrementing reference count rather
 than resending (helps reduce server resource utilization and avoid
 spurious oplock breaks).
 
diff -Nru a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
--- a/fs/cifs/cifsfs.c	Sat Jul 19 12:54:25 2003
+++ b/fs/cifs/cifsfs.c	Sat Jul 19 12:54:25 2003
@@ -230,7 +230,7 @@
 	if (cifs_sb) {
 		if (cifs_sb->tcon) {
 			seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
-			if (cifs_sb->tcon->ses->userName)
+			if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->userName))
 				seq_printf(s, ",username=%s",
 					   cifs_sb->tcon->ses->userName);
 			if(cifs_sb->tcon->ses->domainName)
diff -Nru a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
--- a/fs/cifs/cifsglob.h	Sat Jul 19 12:54:23 2003
+++ b/fs/cifs/cifsglob.h	Sat Jul 19 12:54:23 2003
@@ -155,7 +155,8 @@
 	char *serverOS;		/* name of operating system underlying the server */
 	char *serverNOS;	/* name of network operating system that the server is running */
 	char *serverDomain;	/* security realm of server */
-	int Suid;		/* needed for user level security */
+	int Suid;		/* remote smb uid  */
+	uid_t linux_uid;        /* local Linux uid */
 	int capabilities;
 	char serverName[SERVER_NAME_LEN_WITH_NULL * 2];	/* BB make bigger for tcp names - will ipv6 and sctp addresses fit here?? */
 	char userName[MAX_USERNAME_SIZE + 1];
diff -Nru a/fs/cifs/connect.c b/fs/cifs/connect.c
--- a/fs/cifs/connect.c	Sat Jul 19 12:54:28 2003
+++ b/fs/cifs/connect.c	Sat Jul 19 12:54:28 2003
@@ -405,7 +405,7 @@
 				return 1;	/* needs_arg; */
 			}
 			if ((temp_len = strnlen(value, 300)) < 300) {
-				vol->UNC = kmalloc(GFP_KERNEL, temp_len);
+				vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
 				strcpy(vol->UNC,value);
 				if (strncmp(vol->UNC, "//", 2) == 0) {
 					vol->UNC[0] = '\\';
@@ -482,7 +482,7 @@
 			return 1;
 		}
 		if ((temp_len = strnlen(devname, 300)) < 300) {
-			vol->UNC = kmalloc(GFP_KERNEL, temp_len);
+			vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
 			strcpy(vol->UNC,devname);
 			if (strncmp(vol->UNC, "//", 2) == 0) {
 				vol->UNC[0] = '\\';
@@ -860,7 +860,7 @@
 		FreeXid(xid);
 		return -EINVAL;
 	}
-	/* BB add support to use the multiuser_mount flag BB */
+
 	existingCifsSes =
 	    find_tcp_session(sin_server.sin_addr.s_addr,
 			     volume_info.username, &srvTcp);
@@ -926,6 +926,7 @@
 			if (volume_info.domainname)
 				strncpy(pSesInfo->domainName,
 					volume_info.domainname,MAX_USERNAME_SIZE);
+			pSesInfo->linux_uid = volume_info.linux_uid;
 
 			rc = setup_session(xid,pSesInfo, cifs_sb->local_nls);
 			if(!rc)
diff -Nru a/fs/cifs/misc.c b/fs/cifs/misc.c
--- a/fs/cifs/misc.c	Sat Jul 19 12:54:29 2003
+++ b/fs/cifs/misc.c	Sat Jul 19 12:54:29 2003
@@ -190,6 +190,8 @@
 {
 	int i;
 	__u32 tmp;
+	struct list_head* temp_item;
+	struct cifsSesInfo * ses;
 	char *temp = (char *) buffer;
 
 	for (i = 0; i < MAX_CIFS_HDR_SIZE; i++) {
@@ -225,7 +227,52 @@
 			if (treeCon->ses->capabilities & CAP_STATUS32) {
 				buffer->Flags2 |= SMBFLG2_ERR_STATUS;
 			}
+
 			buffer->Uid = treeCon->ses->Suid;	/* always in LE format */
+			if(multiuser_mount != 0) {
+		/* For the multiuser case, there are few obvious technically  */
+		/* possible mechanisms to match the local linux user (uid)    */
+		/* to a valid remote smb user (smb_uid):		      */
+		/* 	1) Query Winbind (or other local pam/nss daemon       */
+		/* 	  for userid/password/logon_domain or credential      */
+		/*      2) Query Winbind for uid to sid to username mapping   */
+		/* 	   and see if we have a matching password for existing*/
+		/*         session for that user perhas getting password by   */
+		/*         adding a new pam_cifs module that stores passwords */
+		/*         so that the cifs vfs can get at that for all logged*/
+		/*	   on users					      */
+		/*	3) (Which is the mechanism we have chosen)	      */
+		/*	   Search through sessions to the same server for a   */
+		/*	   a match on the uid that was passed in on mount     */
+		/*         with the current processes uid (or euid?) and use  */
+		/* 	   that smb uid.   If no existing smb session for     */
+		/* 	   that uid found, use the default smb session ie     */
+		/*         the smb session for the volume mounted which is    */
+		/* 	   the same as would be used if the multiuser mount   */
+		/* 	   flag were disabled.  */
+
+		/*  BB Add support for establishing new tCon and SMB Session  */
+		/*      with userid/password pairs found on the smb session   */ 
+		/*	for other target tcp/ip addresses 		BB    */
+				if(current->uid != treeCon->ses->linux_uid) {
+					cFYI(1,("Multiuser mode and UID did not match tcon uid "));
+					read_lock(&GlobalSMBSeslock);
+					list_for_each(temp_item, &GlobalSMBSessionList) {
+						ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
+						if(ses->linux_uid == current->uid) {
+							if(ses->server == treeCon->ses->server) {
+								cFYI(1,("found matching uid substitute right smb_uid"));  
+								buffer->Uid = ses->Suid;
+								break;
+							} else {
+								/* BB eventually call setup_session here */
+								cFYI(1,("local UID found but smb sess with this server does not exist"));  
+							}
+						}
+					}
+					read_unlock(&GlobalSMBSeslock);
+				}
+			}
 		}
 		if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
 			buffer->Flags2 |= SMBFLG2_DFS;
diff -Nru a/fs/cifs/transport.c b/fs/cifs/transport.c
--- a/fs/cifs/transport.c	Sat Jul 19 12:54:24 2003
+++ b/fs/cifs/transport.c	Sat Jul 19 12:54:24 2003
@@ -45,6 +45,11 @@
 		cERROR(1, ("Null session passed in to AllocMidQEntry "));
 		return NULL;
 	}
+	if (ses->server == NULL) {
+		cERROR(1, ("Null TCP session in AllocMidQEntry"));
+		return NULL;
+	}
+	
 	temp = (struct mid_q_entry *) kmem_cache_alloc(cifs_mid_cachep,
 						       SLAB_KERNEL);
 	if (temp == NULL)
@@ -65,7 +70,6 @@
 		/* Should we wake up tcp thread first? BB  */
 		timeout = wait_event_interruptible_timeout(ses->server->response_q,
 			(ses->server->tcpStatus == CifsGood), timeout);
-        cFYI(1,("timeout (after reconnection wait) %d",timeout));
 	}
 
 	if (ses->server->tcpStatus == CifsGood) {
diff -Nru a/fs/compat_ioctl.c b/fs/compat_ioctl.c
--- a/fs/compat_ioctl.c	Sat Jul 19 12:54:29 2003
+++ b/fs/compat_ioctl.c	Sat Jul 19 12:54:29 2003
@@ -52,7 +52,7 @@
 #include <linux/raw.h>
 #include <linux/smb_fs.h>
 #include <linux/blkpg.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/elevator.h>
 #include <linux/rtc.h>
 #include <linux/pci.h>
diff -Nru a/fs/devfs/base.c b/fs/devfs/base.c
--- a/fs/devfs/base.c	Sat Jul 19 12:54:23 2003
+++ b/fs/devfs/base.c	Sat Jul 19 12:54:23 2003
@@ -676,6 +676,7 @@
 #include <linux/smp.h>
 #include <linux/version.h>
 #include <linux/rwsem.h>
+#include <linux/sched.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -1325,8 +1326,20 @@
 
 static int is_devfsd_or_child (struct fs_info *fs_info)
 {
-    if (current == fs_info->devfsd_task) return (TRUE);
-    if (current->pgrp == fs_info->devfsd_pgrp) return (TRUE);
+    struct task_struct *p = current;
+
+    if (p == fs_info->devfsd_task) return (TRUE);
+    if (p->pgrp == fs_info->devfsd_pgrp) return (TRUE);
+    read_lock(&tasklist_lock);
+    for ( ; p != &init_task; p = p->real_parent)
+    {
+	if (p == fs_info->devfsd_task)
+	{
+	    read_unlock (&tasklist_lock);
+	    return (TRUE);
+	}
+    }
+    read_unlock (&tasklist_lock);
     return (FALSE);
 }   /*  End Function is_devfsd_or_child  */
 
@@ -1432,12 +1445,6 @@
 	va_list args;
 	int error, n;
 
-	if (!S_ISBLK(mode)) {
-		printk(KERN_WARNING "%s: invalide mode (%u) for %s\n",
-				__FUNCTION__, mode, buf);
-		return -EINVAL;
-	}
-
 	va_start(args, fmt);
 	n = vsnprintf(buf, 64, fmt, args);
 	if (n >= 64 || !buf[0]) {
@@ -1445,6 +1452,12 @@
 				__FUNCTION__);
 		return -EINVAL;
 	}
+	
+	if (!S_ISBLK(mode)) {
+		printk(KERN_WARNING "%s: invalide mode (%u) for %s\n",
+				__FUNCTION__, mode, buf);
+		return -EINVAL;
+	}
 
 	de = _devfs_prepare_leaf(&dir, buf, mode);
 	if (!de) {
@@ -1478,17 +1491,17 @@
 	va_list args;
 	int error, n;
 
-	if (!S_ISCHR(mode)) {
-		printk(KERN_WARNING "%s: invalide mode (%u) for %s\n",
-				__FUNCTION__, mode, buf);
-		return -EINVAL;
-	}
-
 	va_start(args, fmt);
 	n = vsnprintf(buf, 64, fmt, args);
 	if (n >= 64 || !buf[0]) {
 		printk(KERN_WARNING "%s: invalid format string\n",
 				__FUNCTION__);
+		return -EINVAL;
+	}
+
+	if (!S_ISCHR(mode)) {
+		printk(KERN_WARNING "%s: invalide mode (%u) for %s\n",
+				__FUNCTION__, mode, buf);
 		return -EINVAL;
 	}
 
diff -Nru a/fs/ext3/acl.c b/fs/ext3/acl.c
--- a/fs/ext3/acl.c	Sat Jul 19 12:54:24 2003
+++ b/fs/ext3/acl.c	Sat Jul 19 12:54:24 2003
@@ -425,7 +425,7 @@
 	if (!error) {
 		handle_t *handle;
 
-		handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
+		handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS);
 		if (IS_ERR(handle)) {
 			error = PTR_ERR(handle);
 			ext3_std_error(inode->i_sb, error);
@@ -531,7 +531,7 @@
 	} else
 		acl = NULL;
 
-	handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
+	handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS);
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 	error = ext3_set_acl(handle, inode, type, acl);
diff -Nru a/fs/ext3/xattr.c b/fs/ext3/xattr.c
--- a/fs/ext3/xattr.c	Sat Jul 19 12:54:25 2003
+++ b/fs/ext3/xattr.c	Sat Jul 19 12:54:25 2003
@@ -875,7 +875,7 @@
 	handle_t *handle;
 	int error, error2;
 
-	handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
+	handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS);
 	if (IS_ERR(handle))
 		error = PTR_ERR(handle);
 	else
@@ -1050,12 +1050,10 @@
 			ext3_error(inode->i_sb, "ext3_xattr_cache_find",
 				"inode %ld: block %ld read error",
 				inode->i_ino, (unsigned long) ce->e_block);
-		} else {
+		} else if (ext3_journal_get_write_access_credits(
+				handle, bh, credits) == 0) {
 			/* ext3_journal_get_write_access() requires an unlocked
 			 * bh, which complicates things here. */
-			if (ext3_journal_get_write_access_credits(handle, bh,
-								  credits) != 0)
-				return NULL;
 			lock_buffer(bh);
 			if (le32_to_cpu(HDR(bh)->h_refcount) >
 				   EXT3_XATTR_REFCOUNT_MAX) {
@@ -1070,6 +1068,7 @@
 			}
 			unlock_buffer(bh);
 			journal_release_buffer(handle, bh, *credits);
+			*credits = 0;
 			brelse(bh);
 		}
 		ce = mb_cache_entry_find_next(ce, 0, inode->i_sb->s_bdev, hash);
diff -Nru a/fs/intermezzo/sysctl.c b/fs/intermezzo/sysctl.c
--- a/fs/intermezzo/sysctl.c	Sat Jul 19 12:54:23 2003
+++ b/fs/intermezzo/sysctl.c	Sat Jul 19 12:54:23 2003
@@ -36,7 +36,6 @@
 #include <asm/segment.h>
 #include <asm/uaccess.h>
 #include <linux/utsname.h>
-#include <linux/blk.h>
 
 #include "intermezzo_fs.h"
 #include "intermezzo_psdev.h"
diff -Nru a/fs/intermezzo/vfs.c b/fs/intermezzo/vfs.c
--- a/fs/intermezzo/vfs.c	Sat Jul 19 12:54:24 2003
+++ b/fs/intermezzo/vfs.c	Sat Jul 19 12:54:24 2003
@@ -66,7 +66,7 @@
 #include <linux/file.h>
 #include <linux/fs.h>
 #include <linux/namei.h>
-#include <linux/blk.h>
+#include <linux/genhd.h>
 
 #include "intermezzo_fs.h"
 #include "intermezzo_psdev.h"
diff -Nru a/fs/jbd/transaction.c b/fs/jbd/transaction.c
--- a/fs/jbd/transaction.c	Sat Jul 19 12:54:24 2003
+++ b/fs/jbd/transaction.c	Sat Jul 19 12:54:24 2003
@@ -742,7 +742,7 @@
 	/* We do not want to get caught playing with fields which the
 	 * log thread also manipulates.  Make sure that the buffer
 	 * completes any outstanding IO before proceeding. */
-	rc = do_get_write_access(handle, jh, 0, NULL);
+	rc = do_get_write_access(handle, jh, 0, credits);
 	journal_put_journal_head(jh);
 	return rc;
 }
@@ -1088,6 +1088,7 @@
 	transaction_t *transaction = handle->h_transaction;
 	journal_t *journal = transaction->t_journal;
 	struct journal_head *jh = bh2jh(bh);
+	int console_loglevel_saved = console_loglevel;
 
 	jbd_debug(5, "journal_head %p\n", jh);
 	JBUFFER_TRACE(jh, "entry");
@@ -1106,16 +1107,6 @@
 	if (jh->b_transaction == handle->h_transaction &&
 					jh->b_jlist == BJ_Metadata) {
 		JBUFFER_TRACE(jh, "fastpath");
-		console_verbose();
-		if (jh->b_transaction != journal->j_running_transaction) {
-			printk("jh->b_transaction=%p\n", jh->b_transaction);
-			printk("journal->j_running_transaction=%p\n",
-				journal->j_running_transaction);
-			printk("handle->h_transaction=%p\n",
-				handle->h_transaction);
-			printk("journal->j_committing_transaction=%p\n",
-				journal->j_committing_transaction);
-		}
 		J_ASSERT_JH(jh, jh->b_transaction ==
 					journal->j_running_transaction);
 		goto out_unlock_bh;
@@ -1156,6 +1147,7 @@
 	jbd_unlock_bh_state(bh);
 out:
 	JBUFFER_TRACE(jh, "exit");
+	console_loglevel = console_loglevel_saved;
 	return 0;
 }
 
@@ -1327,9 +1319,6 @@
 	transaction_t *transaction = handle->h_transaction;
 	journal_t *journal = transaction->t_journal;
 	int old_handle_count, err;
-
-	if (!handle)
-		return 0;
 
 	J_ASSERT(transaction->t_updates > 0);
 	J_ASSERT(journal_current_handle() == handle);
diff -Nru a/fs/jffs2/Makefile b/fs/jffs2/Makefile
--- a/fs/jffs2/Makefile	Sat Jul 19 12:54:23 2003
+++ b/fs/jffs2/Makefile	Sat Jul 19 12:54:23 2003
@@ -13,6 +13,7 @@
 
 LINUX_OBJS-24	:= super-v24.o crc32.o
 LINUX_OBJS-25	:= super.o
+LINUX_OBJS-26	:= super.o
 
 NAND_OBJS-$(CONFIG_JFFS2_FS_NAND)	:= wbuf.o
 
diff -Nru a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
--- a/fs/lockd/clntlock.c	Sat Jul 19 12:54:29 2003
+++ b/fs/lockd/clntlock.c	Sat Jul 19 12:54:29 2003
@@ -187,8 +187,9 @@
 	} else {
 		nlmclnt_prepare_reclaim(host, newstate);
 		nlm_get_host(host);
-		MOD_INC_USE_COUNT;
-		kernel_thread(reclaimer, host, CLONE_KERNEL);
+		__module_get(THIS_MODULE);
+		if (kernel_thread(reclaimer, host, CLONE_KERNEL))
+			module_put(THIS_MODULE);
 	}
 }
 
@@ -244,7 +245,5 @@
 	nlm_release_host(host);
 	lockd_down();
 	unlock_kernel();
-	MOD_DEC_USE_COUNT;
-
-	return 0;
+	module_put_and_exit(0);
 }
diff -Nru a/fs/lockd/svc.c b/fs/lockd/svc.c
--- a/fs/lockd/svc.c	Sat Jul 19 12:54:25 2003
+++ b/fs/lockd/svc.c	Sat Jul 19 12:54:25 2003
@@ -88,7 +88,11 @@
 	unsigned long grace_period_expire;
 
 	/* Lock module and set up kernel thread */
-	MOD_INC_USE_COUNT;
+	/* lockd_up is waiting for us to startup, so will
+	 * be holding a reference to this module, so it
+	 * is safe to just claim another reference
+	 */
+	__module_get(THIS_MODULE);
 	lock_kernel();
 
 	/*
@@ -183,7 +187,7 @@
 
 	/* Release module */
 	unlock_kernel();
-	MOD_DEC_USE_COUNT;
+	module_put_and_exit(0);
 }
 
 /*
diff -Nru a/fs/namespace.c b/fs/namespace.c
--- a/fs/namespace.c	Sat Jul 19 12:54:26 2003
+++ b/fs/namespace.c	Sat Jul 19 12:54:26 2003
@@ -1158,3 +1158,13 @@
 	init_rootfs();
 	init_mount_tree();
 }
+
+void __put_namespace(struct namespace *namespace)
+{
+	down_write(&namespace->sem);
+	spin_lock(&vfsmount_lock);
+	umount_tree(namespace->root);
+	spin_unlock(&vfsmount_lock);
+	up_write(&namespace->sem);
+	kfree(namespace);
+}
diff -Nru a/fs/nfs/inode.c b/fs/nfs/inode.c
--- a/fs/nfs/inode.c	Sat Jul 19 12:54:26 2003
+++ b/fs/nfs/inode.c	Sat Jul 19 12:54:26 2003
@@ -151,15 +151,16 @@
 nfs_put_super(struct super_block *sb)
 {
 	struct nfs_server *server = NFS_SB(sb);
-	struct rpc_clnt	*rpc;
 
 #ifdef CONFIG_NFS_V4
 	if (server->idmap != NULL)
 		nfs_idmap_delete(server);
 #endif /* CONFIG_NFS_V4 */
 
-	if ((rpc = server->client) != NULL)
-		rpc_shutdown_client(rpc);
+	if (server->client != NULL)
+		rpc_shutdown_client(server->client);
+	if (server->client_sys != NULL)
+		rpc_shutdown_client(server->client_sys);
 
 	if (!(server->flags & NFS_MOUNT_NONLM))
 		lockd_down();	/* release rpc.lockd */
@@ -226,27 +227,57 @@
 /*
  * Obtain the root inode of the file system.
  */
-static struct inode *
-nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh)
+static int
+nfs_get_root(struct inode **rooti, rpc_authflavor_t authflavor, struct super_block *sb, struct nfs_fh *rootfh)
 {
 	struct nfs_server	*server = NFS_SB(sb);
-	struct nfs_fattr	fattr;
-	struct inode		*inode;
+	struct nfs_fattr	fattr = { };
 	int			error;
 
-	if ((error = server->rpc_ops->getroot(server, rootfh, &fattr)) < 0) {
+	error = server->rpc_ops->getroot(server, rootfh, &fattr);
+	if (error == -EACCES && authflavor > RPC_AUTH_MAXFLAVOR) {
+		/*
+		 * Some authentication types (gss/krb5, most notably)
+		 * are such that root won't be able to present a
+		 * credential for GETATTR (ie, getroot()).
+		 *
+		 * We still want the mount to succeed.
+		 * 
+		 * So we fake the attr values and mark the inode as such.
+		 * On the first succesful traversal, we fix everything.
+		 * The auth type test isn't quite correct, but whatever.
+		 */
+		dfprintk(VFS, "NFS: faking root inode\n");
+
+		fattr.fileid = 1;
+		fattr.nlink = 2;	/* minimum for a dir */
+		fattr.type = NFDIR;
+		fattr.mode = S_IFDIR|S_IRUGO|S_IXUGO;
+		fattr.size = 4096;
+		fattr.du.nfs3.used = 1;
+		fattr.valid = NFS_ATTR_FATTR|NFS_ATTR_FATTR_V3;
+	} else if (error < 0) {
 		printk(KERN_NOTICE "nfs_get_root: getattr error = %d\n", -error);
-		return NULL;
+		*rooti = NULL;	/* superfluous ... but safe */
+		return error;
 	}
 
-	inode = __nfs_fhget(sb, rootfh, &fattr);
-	return inode;
+	*rooti = __nfs_fhget(sb, rootfh, &fattr);
+	if (error == -EACCES && authflavor > RPC_AUTH_MAXFLAVOR) {
+		if (*rooti) {
+			NFS_FLAGS(*rooti) |= NFS_INO_FAKE_ROOT;
+			NFS_CACHEINV((*rooti));
+			error = 0;
+		}
+	}
+	return error;
 }
 
 /*
  * Do NFS version-independent mount processing, and sanity checking
  */
-int nfs_sb_init(struct super_block *sb)
+static int
+nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
 {
 	struct nfs_server	*server;
 	struct inode		*root_inode = NULL;
@@ -267,8 +298,7 @@
 	sb->s_op         = &nfs_sops;
 
 	/* Did getting the root inode fail? */
-	root_inode = nfs_get_root(sb, &server->fh);
-	if (!root_inode)
+	if (nfs_get_root(&root_inode, authflavor, sb, &server->fh) < 0)
 		goto out_no_root;
 	sb->s_root = d_alloc_root(root_inode);
 	if (!sb->s_root)
@@ -346,19 +376,66 @@
 }
 
 /*
+ * Create an RPC client handle.
+ */
+static struct rpc_clnt *
+nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
+{
+	struct rpc_timeout	timeparms;
+	struct rpc_xprt		*xprt = NULL;
+	struct rpc_clnt		*clnt = NULL;
+	int			tcp   = (data->flags & NFS_MOUNT_TCP);
+
+	/* Initialize timeout values */
+	timeparms.to_initval = data->timeo * HZ / 10;
+	timeparms.to_retries = data->retrans;
+	timeparms.to_maxval  = tcp ? RPC_MAX_TCP_TIMEOUT : RPC_MAX_UDP_TIMEOUT;
+	timeparms.to_exponential = 1;
+
+	if (!timeparms.to_initval)
+		timeparms.to_initval = (tcp ? 600 : 11) * HZ / 10;
+	if (!timeparms.to_retries)
+		timeparms.to_retries = 5;
+
+	/* create transport and client */
+	xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP,
+				 &server->addr, &timeparms);
+	if (xprt == NULL) {
+		printk(KERN_WARNING "NFS: cannot create RPC transport.\n");
+		goto out_fail;
+	}
+	clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
+				 server->rpc_ops->version, data->pseudoflavor);
+	if (clnt == NULL) {
+		printk(KERN_WARNING "NFS: cannot create RPC client.\n");
+		goto out_fail;
+	}
+
+	clnt->cl_intr     = (server->flags & NFS_MOUNT_INTR) ? 1 : 0;
+	clnt->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0;
+	clnt->cl_droppriv = (server->flags & NFS_MOUNT_BROKEN_SUID) ? 1 : 0;
+	clnt->cl_chatty   = 1;
+
+	return clnt;
+
+out_fail:
+	if (xprt)
+		xprt_destroy(xprt);
+	return NULL;
+}
+
+/*
  * The way this works is that the mount process passes a structure
  * in the data argument which contains the server's IP address
  * and the root file handle obtained from the server's mount
  * daemon. We stash these away in the private superblock fields.
  */
-int nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
+static int
+nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
 {
 	struct nfs_server	*server;
-	struct rpc_xprt		*xprt = NULL;
-	struct rpc_clnt		*clnt = NULL;
-	struct rpc_timeout	timeparms;
-	int			tcp, err = -EIO;
-	u32			authflavor;
+	int			err = -EIO;
+	rpc_authflavor_t	authflavor;
 
 	server           = NFS_SB(sb);
 	sb->s_blocksize_bits = 0;
@@ -400,46 +477,20 @@
 		server->rpc_ops = &nfs_v2_clientops;
 	}
 
-	/* Which protocol do we use? */
-	tcp   = (data->flags & NFS_MOUNT_TCP);
-
-	/* Initialize timeout values */
-	timeparms.to_initval = data->timeo * HZ / 10;
-	timeparms.to_retries = data->retrans;
-	timeparms.to_maxval  = tcp? RPC_MAX_TCP_TIMEOUT : RPC_MAX_UDP_TIMEOUT;
-	timeparms.to_exponential = 1;
-
-	if (!timeparms.to_initval)
-		timeparms.to_initval = (tcp ? 600 : 11) * HZ / 10;
-	if (!timeparms.to_retries)
-		timeparms.to_retries = 5;
-
-	/* Now create transport and client */
-	xprt = xprt_create_proto(tcp? IPPROTO_TCP : IPPROTO_UDP,
-						&server->addr, &timeparms);
-	if (xprt == NULL) {
-		printk(KERN_WARNING "NFS: cannot create RPC transport.\n");
+	/* Fill in pseudoflavor for mount version < 5 */
+	if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
+		data->pseudoflavor = RPC_AUTH_UNIX;
+	authflavor = data->pseudoflavor;	/* save for sb_init() */
+	/* XXX maybe we want to add a server->pseudoflavor field */
+
+	/* Create RPC client handles */
+	server->client = nfs_create_client(server, data);
+	if (server->client == NULL)
 		goto out_fail;
-	}
-
-	if (data->flags & NFS_MOUNT_SECFLAVOUR)
-		authflavor = data->pseudoflavor;
-	else
-		authflavor = RPC_AUTH_UNIX;
-
-	clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
-				 server->rpc_ops->version, authflavor);
-	if (clnt == NULL) {
-		printk(KERN_WARNING "NFS: cannot create RPC client.\n");
-		xprt_destroy(xprt);
-		goto out_fail;
-	}
-
-	clnt->cl_intr     = (server->flags & NFS_MOUNT_INTR) ? 1 : 0;
-	clnt->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0;
-	clnt->cl_droppriv = (server->flags & NFS_MOUNT_BROKEN_SUID) ? 1 : 0;
-	clnt->cl_chatty   = 1;
-	server->client    = clnt;
+	data->pseudoflavor = RPC_AUTH_UNIX;	/* RFC 2623, sec 2.3.2 */
+	server->client_sys = nfs_create_client(server, data);
+	if (server->client_sys == NULL)
+		goto out_shutdown;
 
 	/* Fire up rpciod if not yet running */
 	if (rpciod_up() != 0) {
@@ -447,7 +498,7 @@
 		goto out_shutdown;
 	}
 
-	err = nfs_sb_init(sb);
+	err = nfs_sb_init(sb, authflavor);
 	if (err != 0)
 		goto out_noinit;
 
@@ -466,7 +517,10 @@
 out_noinit:
 	rpciod_down();
 out_shutdown:
-	rpc_shutdown_client(server->client);
+	if (server->client)
+		rpc_shutdown_client(server->client);
+	if (server->client_sys)
+		rpc_shutdown_client(server->client_sys);
 out_fail:
 	if (server->hostname)
 		kfree(server->hostname);
@@ -904,6 +958,11 @@
  		goto out_nowait;
 	if (NFS_STALE(inode) && inode != inode->i_sb->s_root->d_inode)
  		goto out_nowait;
+	if (NFS_FAKE_ROOT(inode)) {
+		dfprintk(VFS, "NFS: not revalidating fake root\n");
+		status = 0;
+		goto out_nowait;
+	}
 
 	while (NFS_REVALIDATING(inode)) {
 		status = nfs_wait_on_inode(inode, NFS_INO_REVALIDATING);
@@ -1007,6 +1066,13 @@
 			inode->i_sb->s_id, inode->i_ino,
 			atomic_read(&inode->i_count), fattr->valid);
 
+	/* First successful call after mount, fill real data. */
+	if (NFS_FAKE_ROOT(inode)) {
+		dfprintk(VFS, "NFS: updating fake root\n");
+		nfsi->fileid = fattr->fileid;
+		NFS_FLAGS(inode) &= ~NFS_INO_FAKE_ROOT;
+	}
+
 	if (nfsi->fileid != fattr->fileid) {
 		printk(KERN_ERR "nfs_refresh_inode: inode number mismatch\n"
 		       "expected (%s/0x%Lx), got (%s/0x%Lx)\n",
@@ -1229,6 +1295,8 @@
 			root->size = NFS2_FHSIZE;
 			memcpy(root->data, data->old_root.data, NFS2_FHSIZE);
 		}
+		if (data->version < 5)
+			data->flags &= ~NFS_MOUNT_SECFLAVOUR;
 	}
 
 	if (root->size > sizeof(root->data)) {
@@ -1373,7 +1441,7 @@
 	if ((server->idmap = nfs_idmap_new(server)) == NULL)
 		printk(KERN_WARNING "NFS: couldn't start IDmap\n");
 
-	err = nfs_sb_init(sb);
+	err = nfs_sb_init(sb, authflavour);
 	if (err == 0)
 		return 0;
 	rpciod_down();
diff -Nru a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
--- a/fs/nfs/nfs3proc.c	Sat Jul 19 12:54:25 2003
+++ b/fs/nfs/nfs3proc.c	Sat Jul 19 12:54:25 2003
@@ -681,7 +681,7 @@
 
 	dprintk("NFS call  fsinfo\n");
 	info->fattr->valid = 0;
-	status = rpc_call(server->client, NFS3PROC_FSINFO, fhandle, info, 0);
+	status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0);
 	dprintk("NFS reply fsinfo: %d\n", status);
 	return status;
 }
diff -Nru a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
--- a/fs/nfs/nfs3xdr.c	Sat Jul 19 12:54:30 2003
+++ b/fs/nfs/nfs3xdr.c	Sat Jul 19 12:54:30 2003
@@ -124,8 +124,6 @@
 
 /*
  * Encode/decode time.
- * Since the VFS doesn't care for fractional times, we ignore the
- * nanosecond field.
  */
 static inline u32 *
 xdr_encode_time3(u32 *p, struct timespec *timep)
diff -Nru a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
--- a/fs/nfsd/nfssvc.c	Sat Jul 19 12:54:25 2003
+++ b/fs/nfsd/nfssvc.c	Sat Jul 19 12:54:25 2003
@@ -116,9 +116,12 @@
 	nrservs -= (nfsd_serv->sv_nrthreads-1);
 	while (nrservs > 0) {
 		nrservs--;
+		__module_get(THIS_MODULE);
 		error = svc_create_thread(nfsd, nfsd_serv);
-		if (error < 0)
+		if (error < 0) {
+			module_put(THIS_MODULE);
 			break;
+		}
 	}
 	victim = nfsd_list.next;
 	while (nrservs < 0 && victim != &nfsd_list) {
@@ -175,7 +178,6 @@
 	sigset_t shutdown_mask, allowed_mask;
 
 	/* Lock module and set up kernel thread */
-	MOD_INC_USE_COUNT;
 	lock_kernel();
 	daemonize("nfsd");
 	current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
@@ -281,7 +283,7 @@
 	svc_exit_thread(rqstp);
 
 	/* Release module */
-	MOD_DEC_USE_COUNT;
+	module_put_and_exit(0);
 }
 
 int
diff -Nru a/fs/partitions/check.c b/fs/partitions/check.c
--- a/fs/partitions/check.c	Sat Jul 19 12:54:28 2003
+++ b/fs/partitions/check.c	Sat Jul 19 12:54:28 2003
@@ -16,7 +16,6 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/blk.h>
 #include <linux/kmod.h>
 #include <linux/ctype.h>
 #include <linux/devfs_fs_kernel.h>
@@ -348,6 +347,9 @@
 		return;
 	}
 
+	/* always add handle for the whole disk */
+	devfs_add_partitioned(disk);
+
 	/* No such device (e.g., media were just removed) */
 	if (!get_capacity(disk))
 		return;
@@ -356,7 +358,6 @@
 	if (blkdev_get(bdev, FMODE_READ, 0, BDEV_RAW) < 0)
 		return;
 	state = check_partition(disk, bdev);
-	devfs_add_partitioned(disk);
 	if (state) {
 		for (j = 1; j < state->limit; j++) {
 			sector_t size = state->parts[j].size;
diff -Nru a/fs/partitions/efi.h b/fs/partitions/efi.h
--- a/fs/partitions/efi.h	Sat Jul 19 12:54:26 2003
+++ b/fs/partitions/efi.h	Sat Jul 19 12:54:26 2003
@@ -32,7 +32,6 @@
 #include <linux/kernel.h>
 #include <linux/major.h>
 #include <linux/string.h>
-#include <linux/blk.h>
 #include <linux/efi.h>
 
 #define MSDOS_MBR_SIGNATURE 0xaa55
diff -Nru a/fs/partitions/nec98.c b/fs/partitions/nec98.c
--- a/fs/partitions/nec98.c	Sat Jul 19 12:54:22 2003
+++ b/fs/partitions/nec98.c	Sat Jul 19 12:54:22 2003
@@ -8,7 +8,6 @@
 #include <linux/fs.h>
 #include <linux/genhd.h>
 #include <linux/kernel.h>
-#include <linux/blk.h>
 #include <linux/hdreg.h>
 
 #include "check.h"
diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
--- a/fs/proc/proc_misc.c	Sat Jul 19 12:54:23 2003
+++ b/fs/proc/proc_misc.c	Sat Jul 19 12:54:23 2003
@@ -388,10 +388,8 @@
 		system += kstat_cpu(i).cpustat.system;
 		idle += kstat_cpu(i).cpustat.idle;
 		iowait += kstat_cpu(i).cpustat.iowait;
-#if !defined(CONFIG_ARCH_S390)
 		for (j = 0 ; j < NR_IRQS ; j++)
 			sum += kstat_cpu(i).irqs[j];
-#endif
 	}
 
 	len = sprintf(page, "cpu  %u %u %u %u %u\n",
@@ -412,7 +410,7 @@
 	}
 	len += sprintf(page + len, "intr %u", sum);
 
-#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC64) && !defined(CONFIG_ALPHA)
+#if !defined(CONFIG_PPC64) && !defined(CONFIG_ALPHA)
 	for (i = 0 ; i < NR_IRQS ; i++)
 		len += sprintf(page + len, " %u", kstat_irqs(i));
 #endif
@@ -440,7 +438,6 @@
 	return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
-#if !defined(CONFIG_ARCH_S390)
 extern int show_interrupts(struct seq_file *p, void *v);
 static int interrupts_open(struct inode *inode, struct file *file)
 {
@@ -466,7 +463,6 @@
 	.llseek		= seq_lseek,
 	.release	= single_release,
 };
-#endif
 
 static int filesystems_read_proc(char *page, char **start, off_t off,
 				 int count, int *eof, void *data)
@@ -536,7 +532,8 @@
 		buf++; p++; count--; read++;
 	}
 	pnt = (char *)prof_buffer + p - sizeof(unsigned int);
-	copy_to_user(buf,(void *)pnt,count);
+	if (copy_to_user(buf,(void *)pnt,count))
+		return -EFAULT;
 	read += count;
 	*ppos += read;
 	return read;
@@ -645,9 +642,7 @@
 		entry->proc_fops = &proc_kmsg_operations;
 	create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
 	create_seq_entry("partitions", 0, &proc_partitions_operations);
-#if !defined(CONFIG_ARCH_S390)
 	create_seq_entry("interrupts", 0, &proc_interrupts_operations);
-#endif
 	create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
 	create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
 	create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
diff -Nru a/fs/umsdos/ioctl.c b/fs/umsdos/ioctl.c
--- a/fs/umsdos/ioctl.c	Sat Jul 19 12:54:22 2003
+++ b/fs/umsdos/ioctl.c	Sat Jul 19 12:54:22 2003
@@ -4,6 +4,10 @@
  *  Written 1993 by Jacques Gelinas
  *
  *  Extended MS-DOS ioctl directory handling functions
+ *
+ *  Changes:
+ *  11/07/2003      Daniele Bellucci <bellucda@tiscali.it>
+ *                  - audit copy_to_user/put_user in umsdos_ioctl_fill.
  */
 
 #include <asm/uaccess.h>
@@ -36,11 +40,12 @@
 	struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *) buf;
 
 	if (d->count == 0) {
-		copy_to_user (d->ent->d_name, name, name_len);
-		put_user ('\0', d->ent->d_name + name_len);
-		put_user (name_len, &d->ent->d_reclen);
-		put_user (ino, &d->ent->d_ino);
-		put_user (offset, &d->ent->d_off);
+		if (copy_to_user (d->ent->d_name, name, name_len) ||
+		    put_user ('\0', d->ent->d_name + name_len) ||
+		    put_user (name_len, &d->ent->d_reclen) ||
+		    put_user (ino, &d->ent->d_ino) ||
+		    put_user (offset, &d->ent->d_off))
+			return -EFAULT;
 		d->count = 1;
 		ret = 0;
 	}
diff -Nru a/fs/vfat/namei.c b/fs/vfat/namei.c
--- a/fs/vfat/namei.c	Sat Jul 19 12:54:26 2003
+++ b/fs/vfat/namei.c	Sat Jul 19 12:54:26 2003
@@ -375,7 +375,7 @@
 }
 
 static inline int to_shortname_char(struct nls_table *nls,
-				    char *buf, int buf_size, wchar_t *src,
+				    unsigned char *buf, int buf_size, wchar_t *src,
 				    struct shortname_info *info)
 {
 	int len;
diff -Nru a/include/acpi/acconfig.h b/include/acpi/acconfig.h
--- a/include/acpi/acconfig.h	Sat Jul 19 12:54:26 2003
+++ b/include/acpi/acconfig.h	Sat Jul 19 12:54:26 2003
@@ -64,7 +64,7 @@
 
 /* Version string */
 
-#define ACPI_CA_VERSION                 0x20030619
+#define ACPI_CA_VERSION                 0x20030714
 
 /* Maximum objects in the various object caches */
 
diff -Nru a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h
--- a/include/acpi/platform/acenv.h	Sat Jul 19 12:54:23 2003
+++ b/include/acpi/platform/acenv.h	Sat Jul 19 12:54:23 2003
@@ -134,6 +134,9 @@
 #elif defined(__FreeBSD__)
 #include "acfreebsd.h"
 
+#elif defined(__NetBSD__)
+#include "acnetbsd.h"
+
 #elif defined(MODESTO)
 #include "acmodesto.h"
 
@@ -187,13 +190,14 @@
 #define DEBUGGER_SINGLE_THREADED    0
 #define DEBUGGER_MULTI_THREADED     1
 
+#ifndef DEBUGGER_THREADING
 #ifdef ACPI_APPLICATION
 #define DEBUGGER_THREADING          DEBUGGER_SINGLE_THREADED
 
 #else
 #define DEBUGGER_THREADING          DEBUGGER_MULTI_THREADED
 #endif
-
+#endif /* !DEBUGGER_THREADING */
 
 /******************************************************************************
  *
diff -Nru a/include/asm-generic/local.h b/include/asm-generic/local.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-generic/local.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,118 @@
+#ifndef _ASM_GENERIC_LOCAL_H
+#define _ASM_GENERIC_LOCAL_H
+
+#include <linux/config.h>
+#include <linux/percpu.h>
+#include <asm/types.h>
+#include <asm/hardirq.h>
+
+/* An unsigned long type for operations which are atomic for a single
+ * CPU.  Usually used in combination with per-cpu variables. */
+
+#if BITS_PER_LONG == 32 && !defined(CONFIG_SPARC32)
+/* Implement in terms of atomics. */
+
+/* Don't use typedef: don't want them to be mixed with atomic_t's. */
+typedef struct
+{
+	atomic_t a;
+} local_t;
+
+#define LOCAL_INIT(i)	{ ATOMIC_INIT(i) }
+
+#define local_read(l)	((unsigned long)atomic_read(&(l)->a))
+#define local_set(l,i)	atomic_set((&(l)->a),(i))
+#define local_inc(l)	atomic_inc(&(l)->a)
+#define local_dec(l)	atomic_dec(&(l)->a)
+#define local_add(i,l)	atomic_add((i),(&(l)->a))
+#define local_sub(i,l)	atomic_sub((i),(&(l)->a))
+
+/* Non-atomic variants, ie. preemption disabled and won't be touched
+ * in interrupt, etc.  Some archs can optimize this case well. */
+#define __local_inc(l)		local_set((l), local_read(l) + 1)
+#define __local_dec(l)		local_set((l), local_read(l) - 1)
+#define __local_add(i,l)	local_set((l), local_read(l) + (i))
+#define __local_sub(i,l)	local_set((l), local_read(l) - (i))
+
+#else /* ... can't use atomics. */
+/* Implement in terms of three variables.
+   Another option would be to use local_irq_save/restore. */
+
+typedef struct
+{
+	/* 0 = in hardirq, 1 = in softirq, 2 = usermode. */
+	unsigned long v[3];
+} local_t;
+
+#define _LOCAL_VAR(l)	((l)->v[!in_interrupt() + !in_irq()])
+
+#define LOCAL_INIT(i)	{ { (i), 0, 0 } }
+
+static inline unsigned long local_read(local_t *l)
+{
+	return l->v[0] + l->v[1] + l->v[2];
+}
+
+static inline void local_set(local_t *l, unsigned long v)
+{
+	l->v[0] = v;
+	l->v[1] = l->v[2] = 0;
+}
+
+static inline void local_inc(local_t *l)
+{
+	preempt_disable();
+	_LOCAL_VAR(l)++;
+	preempt_enable();
+}
+
+static inline void local_dec(local_t *l)
+{
+	preempt_disable();
+	_LOCAL_VAR(l)--;
+	preempt_enable();
+}
+
+static inline void local_add(unsigned long v, local_t *l)
+{
+	preempt_disable();
+	_LOCAL_VAR(l) += v;
+	preempt_enable();
+}
+
+static inline void local_sub(unsigned long v, local_t *l)
+{
+	preempt_disable();
+	_LOCAL_VAR(l) -= v;
+	preempt_enable();
+}
+
+/* Non-atomic variants, ie. preemption disabled and won't be touched
+ * in interrupt, etc.  Some archs can optimize this case well. */
+#define __local_inc(l)		((l)->v[0]++)
+#define __local_dec(l)		((l)->v[0]--)
+#define __local_add(i,l)	((l)->v[0] += (i))
+#define __local_sub(i,l)	((l)->v[0] -= (i))
+
+#endif /* Non-atomic implementation */
+
+/* Use these for per-cpu local_t variables: on some archs they are
+ * much more efficient than these naive implementations.  Note they take
+ * a variable (eg. mystruct.foo), not an address.
+ */
+#define cpu_local_read(v)	local_read(&__get_cpu_var(v))
+#define cpu_local_set(v, i)	local_set(&__get_cpu_var(v), (i))
+#define cpu_local_inc(v)	local_inc(&__get_cpu_var(v))
+#define cpu_local_dec(v)	local_dec(&__get_cpu_var(v))
+#define cpu_local_add(i, v)	local_add((i), &__get_cpu_var(v))
+#define cpu_local_sub(i, v)	local_sub((i), &__get_cpu_var(v))
+
+/* Non-atomic increments, ie. preemption disabled and won't be touched
+ * in interrupt, etc.  Some archs can optimize this case well.
+ */
+#define __cpu_local_inc(v)	__local_inc(&__get_cpu_var(v))
+#define __cpu_local_dec(v)	__local_dec(&__get_cpu_var(v))
+#define __cpu_local_add(i, v)	__local_add((i), &__get_cpu_var(v))
+#define __cpu_local_sub(i, v)	__local_sub((i), &__get_cpu_var(v))
+
+#endif /* _ASM_GENERIC_LOCAL_H */
diff -Nru a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
--- a/include/asm-generic/percpu.h	Sat Jul 19 12:54:23 2003
+++ b/include/asm-generic/percpu.h	Sat Jul 19 12:54:23 2003
@@ -9,33 +9,34 @@
 
 /* Separate out the type, so (int[3], foo) works. */
 #define DEFINE_PER_CPU(type, name) \
-    __attribute__((__section__(".data.percpu"))) __typeof__(type) name##__per_cpu
+    __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name
 
 /* var is in discarded region: offset to particular copy we want */
-#define per_cpu(var, cpu) (*RELOC_HIDE(&var##__per_cpu, __per_cpu_offset[cpu]))
+#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
 #define __get_cpu_var(var) per_cpu(var, smp_processor_id())
 
-static inline void percpu_modcopy(void *pcpudst, const void *src,
-				  unsigned long size)
-{
-	unsigned int i;
-	for (i = 0; i < NR_CPUS; i++)
-		if (cpu_possible(i))
-			memcpy(pcpudst + __per_cpu_offset[i], src, size);
-}
+/* A macro to avoid #include hell... */
+#define percpu_modcopy(pcpudst, src, size)			\
+do {								\
+	unsigned int __i;					\
+	for (__i = 0; __i < NR_CPUS; __i++)			\
+		if (cpu_possible(__i))				\
+			memcpy((pcpudst)+__per_cpu_offset[__i],	\
+			       (src), (size));			\
+} while (0)
 #else /* ! SMP */
 
 #define DEFINE_PER_CPU(type, name) \
-    __typeof__(type) name##__per_cpu
+    __typeof__(type) per_cpu__##name
 
-#define per_cpu(var, cpu)			((void)cpu, var##__per_cpu)
-#define __get_cpu_var(var)			var##__per_cpu
+#define per_cpu(var, cpu)			((void)cpu, per_cpu__##var)
+#define __get_cpu_var(var)			per_cpu__##var
 
 #endif	/* SMP */
 
-#define DECLARE_PER_CPU(type, name) extern __typeof__(type) name##__per_cpu
+#define DECLARE_PER_CPU(type, name) extern __typeof__(type) per_cpu__##name
 
-#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(var##__per_cpu)
-#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(var##__per_cpu)
+#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var)
+#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var)
 
 #endif /* _ASM_GENERIC_PERCPU_H_ */
diff -Nru a/include/asm-generic/sections.h b/include/asm-generic/sections.h
--- a/include/asm-generic/sections.h	Sat Jul 19 12:54:21 2003
+++ b/include/asm-generic/sections.h	Sat Jul 19 12:54:21 2003
@@ -3,9 +3,10 @@
 
 /* References to section boundaries */
 
-extern char _text, _etext;
-extern char _data, _edata;
-extern char __bss_start;
-extern char __init_begin, __init_end;
+extern char _text[], _stext[], _etext[];
+extern char _data[], _sdata[], _edata[];
+extern char __bss_start[];
+extern char __init_begin[], __init_end[];
+extern char _sinittext[], _einittext[];
 
 #endif /* _ASM_GENERIC_SECTIONS_H_ */
diff -Nru a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h
--- a/include/asm-i386/hw_irq.h	Sat Jul 19 12:54:30 2003
+++ b/include/asm-i386/hw_irq.h	Sat Jul 19 12:54:30 2003
@@ -16,6 +16,7 @@
 #include <linux/profile.h>
 #include <asm/atomic.h>
 #include <asm/irq.h>
+#include <asm/sections.h>
 
 /*
  * Various low-level irq details needed by irq.c, process.c,
@@ -63,8 +64,6 @@
 extern atomic_t irq_err_count;
 extern atomic_t irq_mis_count;
 
-extern char _stext, _etext;
-
 #define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
 
 /*
@@ -95,7 +94,7 @@
 	if (!((1<<smp_processor_id()) & prof_cpu_mask))
 		return;
 
-	eip -= (unsigned long) &_stext;
+	eip -= (unsigned long)_stext;
 	eip >>= prof_shift;
 	/*
 	 * Don't ignore out-of-bounds EIP values silently,
@@ -107,7 +106,7 @@
 	atomic_inc((atomic_t *)&prof_buffer[eip]);
 }
  
-#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP)
+#if defined(CONFIG_X86_IO_APIC)
 static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i)
 {
 	if (IO_APIC_IRQ(i))
diff -Nru a/include/asm-i386/local.h b/include/asm-i386/local.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-i386/local.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,70 @@
+#ifndef _ARCH_I386_LOCAL_H
+#define _ARCH_I386_LOCAL_H
+
+#include <linux/percpu.h>
+
+typedef struct
+{
+	volatile unsigned long counter;
+} local_t;
+
+#define LOCAL_INIT(i)	{ (i) }
+
+#define local_read(v)	((v)->counter)
+#define local_set(v,i)	(((v)->counter) = (i))
+
+static __inline__ void local_inc(local_t *v)
+{
+	__asm__ __volatile__(
+		"incl %0"
+		:"=m" (v->counter)
+		:"m" (v->counter));
+}
+
+static __inline__ void local_dec(local_t *v)
+{
+	__asm__ __volatile__(
+		"decl %0"
+		:"=m" (v->counter)
+		:"m" (v->counter));
+}
+
+static __inline__ void local_add(unsigned long i, local_t *v)
+{
+	__asm__ __volatile__(
+		"addl %1,%0"
+		:"=m" (v->counter)
+		:"ir" (i), "m" (v->counter));
+}
+
+static __inline__ void local_sub(unsigned long i, local_t *v)
+{
+	__asm__ __volatile__(
+		"subl %1,%0"
+		:"=m" (v->counter)
+		:"ir" (i), "m" (v->counter));
+}
+
+/* On x86, these are no better than the atomic variants. */
+#define __local_inc(l)		local_inc(l)
+#define __local_dec(l)		local_dec(l)
+#define __local_add(i,l)	local_add((i),(l))
+#define __local_sub(i,l)	local_sub((i),(l))
+
+/* Use these for per-cpu local_t variables: on some archs they are
+ * much more efficient than these naive implementations.  Note they take
+ * a variable, not an address.
+ */
+#define cpu_local_read(v)	local_read(&__get_cpu_var(v))
+#define cpu_local_set(v, i)	local_set(&__get_cpu_var(v), (i))
+#define cpu_local_inc(v)	local_inc(&__get_cpu_var(v))
+#define cpu_local_dec(v)	local_dec(&__get_cpu_var(v))
+#define cpu_local_add(i, v)	local_add((i), &__get_cpu_var(v))
+#define cpu_local_sub(i, v)	local_sub((i), &__get_cpu_var(v))
+
+#define __cpu_local_inc(v)	cpu_local_inc(v)
+#define __cpu_local_dec(v)	cpu_local_dec(v)
+#define __cpu_local_add(i, v)	cpu_local_add((i), (v))
+#define __cpu_local_sub(i, v)	cpu_local_sub((i), (v))
+
+#endif /* _ARCH_I386_LOCAL_H */
diff -Nru a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
--- a/include/asm-i386/thread_info.h	Sat Jul 19 12:54:23 2003
+++ b/include/asm-i386/thread_info.h	Sat Jul 19 12:54:23 2003
@@ -87,8 +87,8 @@
 
 /* thread information allocation */
 #define THREAD_SIZE (2*PAGE_SIZE)
-#define alloc_thread_info(tsk) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
+#define alloc_thread_info(task) ((struct thread_info *)kmalloc(THREAD_SIZE, GFP_KERNEL))
+#define free_thread_info(info)	kfree(info)
 #define get_thread_info(ti) get_task_struct((ti)->task)
 #define put_thread_info(ti) put_task_struct((ti)->task)
 
diff -Nru a/include/asm-ia64/atomic.h b/include/asm-ia64/atomic.h
--- a/include/asm-ia64/atomic.h	Sat Jul 19 12:54:23 2003
+++ b/include/asm-ia64/atomic.h	Sat Jul 19 12:54:23 2003
@@ -9,7 +9,7 @@
  * "int" types were carefully placed so as to ensure proper operation
  * of the macros.
  *
- * Copyright (C) 1998, 1999, 2002 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999, 2002-2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 #include <linux/types.h>
@@ -21,11 +21,16 @@
  * memory accesses are ordered.
  */
 typedef struct { volatile __s32 counter; } atomic_t;
+typedef struct { volatile __s64 counter; } atomic64_t;
 
 #define ATOMIC_INIT(i)		((atomic_t) { (i) })
+#define ATOMIC64_INIT(i)	((atomic64_t) { (i) })
 
 #define atomic_read(v)		((v)->counter)
+#define atomic64_read(v)	((v)->counter)
+
 #define atomic_set(v,i)		(((v)->counter) = (i))
+#define atomic64_set(v,i)	(((v)->counter) = (i))
 
 static __inline__ int
 ia64_atomic_add (int i, atomic_t *v)
@@ -37,7 +42,21 @@
 		CMPXCHG_BUGCHECK(v);
 		old = atomic_read(v);
 		new = old + i;
-	} while (ia64_cmpxchg("acq", v, old, old + i, sizeof(atomic_t)) != old);
+	} while (ia64_cmpxchg("acq", v, old, new, sizeof(atomic_t)) != old);
+	return new;
+}
+
+static __inline__ int
+ia64_atomic64_add (int i, atomic64_t *v)
+{
+	__s64 old, new;
+	CMPXCHG_BUGCHECK_DECL
+
+	do {
+		CMPXCHG_BUGCHECK(v);
+		old = atomic_read(v);
+		new = old + i;
+	} while (ia64_cmpxchg("acq", v, old, new, sizeof(atomic_t)) != old);
 	return new;
 }
 
@@ -55,6 +74,20 @@
 	return new;
 }
 
+static __inline__ int
+ia64_atomic64_sub (int i, atomic64_t *v)
+{
+	__s64 old, new;
+	CMPXCHG_BUGCHECK_DECL
+
+	do {
+		CMPXCHG_BUGCHECK(v);
+		old = atomic_read(v);
+		new = old - i;
+	} while (ia64_cmpxchg("acq", v, old, new, sizeof(atomic_t)) != old);
+	return new;
+}
+
 #define atomic_add_return(i,v)						\
 ({									\
 	int __ia64_aar_i = (i);						\
@@ -67,6 +100,18 @@
 		: ia64_atomic_add(__ia64_aar_i, v);			\
 })
 
+#define atomic64_add_return(i,v)					\
+({									\
+	long __ia64_aar_i = (i);					\
+	(__builtin_constant_p(i)					\
+	 && (   (__ia64_aar_i ==  1) || (__ia64_aar_i ==   4)		\
+	     || (__ia64_aar_i ==  8) || (__ia64_aar_i ==  16)		\
+	     || (__ia64_aar_i == -1) || (__ia64_aar_i ==  -4)		\
+	     || (__ia64_aar_i == -8) || (__ia64_aar_i == -16)))		\
+		? ia64_fetch_and_add(__ia64_aar_i, &(v)->counter)	\
+		: ia64_atomic64_add(__ia64_aar_i, v);			\
+})
+
 /*
  * Atomically add I to V and return TRUE if the resulting value is
  * negative.
@@ -77,6 +122,12 @@
 	return atomic_add_return(i, v) < 0;
 }
 
+static __inline__ int
+atomic64_add_negative (int i, atomic64_t *v)
+{
+	return atomic64_add_return(i, v) < 0;
+}
+
 #define atomic_sub_return(i,v)						\
 ({									\
 	int __ia64_asr_i = (i);						\
@@ -89,17 +140,39 @@
 		: ia64_atomic_sub(__ia64_asr_i, v);			\
 })
 
+#define atomic64_sub_return(i,v)					\
+({									\
+	long __ia64_asr_i = (i);					\
+	(__builtin_constant_p(i)					\
+	 && (   (__ia64_asr_i ==   1) || (__ia64_asr_i ==   4)		\
+	     || (__ia64_asr_i ==   8) || (__ia64_asr_i ==  16)		\
+	     || (__ia64_asr_i ==  -1) || (__ia64_asr_i ==  -4)		\
+	     || (__ia64_asr_i ==  -8) || (__ia64_asr_i == -16)))	\
+		? ia64_fetch_and_add(-__ia64_asr_i, &(v)->counter)	\
+		: ia64_atomic64_sub(__ia64_asr_i, v);			\
+})
+
 #define atomic_dec_return(v)		atomic_sub_return(1, (v))
 #define atomic_inc_return(v)		atomic_add_return(1, (v))
+#define atomic64_dec_return(v)		atomic64_sub_return(1, (v))
+#define atomic64_inc_return(v)		atomic64_add_return(1, (v))
 
 #define atomic_sub_and_test(i,v)	(atomic_sub_return((i), (v)) == 0)
 #define atomic_dec_and_test(v)		(atomic_sub_return(1, (v)) == 0)
 #define atomic_inc_and_test(v)		(atomic_add_return(1, (v)) != 0)
+#define atomic64_sub_and_test(i,v)	(atomic64_sub_return((i), (v)) == 0)
+#define atomic64_dec_and_test(v)	(atomic64_sub_return(1, (v)) == 0)
+#define atomic64_inc_and_test(v)	(atomic64_add_return(1, (v)) != 0)
 
 #define atomic_add(i,v)			atomic_add_return((i), (v))
 #define atomic_sub(i,v)			atomic_sub_return((i), (v))
 #define atomic_inc(v)			atomic_add(1, (v))
 #define atomic_dec(v)			atomic_sub(1, (v))
+
+#define atomic64_add(i,v)		atomic64_add_return((i), (v))
+#define atomic64_sub(i,v)		atomic64_sub_return((i), (v))
+#define atomic64_inc(v)			atomic64_add(1, (v))
+#define atomic64_dec(v)			atomic64_sub(1, (v))
 
 /* Atomic operations are already serializing */
 #define smp_mb__before_atomic_dec()	barrier()
diff -Nru a/include/asm-ia64/elf.h b/include/asm-ia64/elf.h
--- a/include/asm-ia64/elf.h	Sat Jul 19 12:54:26 2003
+++ b/include/asm-ia64/elf.h	Sat Jul 19 12:54:26 2003
@@ -199,11 +199,11 @@
 
 #define GATE_EHDR	((const struct elfhdr *) GATE_ADDR)
 
-#define ARCH_DLINFO							\
-do {									\
-	extern char __kernel_syscall_via_epc[];				\
-	NEW_AUX_ENT(AT_SYSINFO, __kernel_syscall_via_epc);		\
-	NEW_AUX_ENT(AT_SYSINFO_EHDR, (unsigned long) GATE_EHDR);	\
+#define ARCH_DLINFO								\
+do {										\
+	extern char __kernel_syscall_via_epc[];					\
+	NEW_AUX_ENT(AT_SYSINFO, (unsigned long) __kernel_syscall_via_epc);	\
+	NEW_AUX_ENT(AT_SYSINFO_EHDR, (unsigned long) GATE_EHDR);		\
 } while (0)
 
 /*
diff -Nru a/include/asm-ia64/local.h b/include/asm-ia64/local.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-ia64/local.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,50 @@
+#ifndef _ASM_IA64_LOCAL_H
+#define _ASM_IA64_LOCAL_H
+
+/*
+ * Copyright (C) 2003 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <linux/percpu.h>
+
+typedef struct {
+	atomic64_t val;
+} local_t;
+
+#define LOCAL_INIT(i)	((local_t) { { (i) } })
+#define local_read(l)	atomic64_read(&(l)->val)
+#define local_set(l, i)	atomic64_set(&(l)->val, i)
+#define local_inc(l)	atomic64_inc(&(l)->val)
+#define local_dec(l)	atomic64_dec(&(l)->val)
+#define local_add(l)	atomic64_add(&(l)->val)
+#define local_sub(l)	atomic64_sub(&(l)->val)
+
+/* Non-atomic variants, i.e., preemption disabled and won't be touched in interrupt, etc.  */
+
+#define __local_inc(l)		(++(l)->val.counter)
+#define __local_dec(l)		(--(l)->val.counter)
+#define __local_add(i,l)	((l)->val.counter += (i))
+#define __local_sub(i,l)	((l)->val.counter -= (i))
+
+/*
+ * Use these for per-cpu local_t variables.  Note they take a variable (eg. mystruct.foo),
+ * not an address.
+ */
+#define cpu_local_read(v)	local_read(&__ia64_per_cpu_var(v))
+#define cpu_local_set(v, i)	local_set(&__ia64_per_cpu_var(v), (i))
+#define cpu_local_inc(v)	local_inc(&__ia64_per_cpu_var(v))
+#define cpu_local_dec(v)	local_dec(&__ia64_per_cpu_var(v))
+#define cpu_local_add(i, v)	local_add((i), &__ia64_per_cpu_var(v))
+#define cpu_local_sub(i, v)	local_sub((i), &__ia64_per_cpu_var(v))
+
+/*
+ * Non-atomic increments, i.e., preemption disabled and won't be touched in interrupt,
+ * etc.
+ */
+#define __cpu_local_inc(v)	__local_inc(&__ia64_per_cpu_var(v))
+#define __cpu_local_dec(v)	__local_dec(&__ia64_per_cpu_var(v))
+#define __cpu_local_add(i, v)	__local_add((i), &__ia64_per_cpu_var(v))
+#define __cpu_local_sub(i, v)	__local_sub((i), &__ia64_per_cpu_var(v))
+
+#endif /* _ASM_IA64_LOCAL_H */
diff -Nru a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h
--- a/include/asm-ia64/mmu_context.h	Sat Jul 19 12:54:23 2003
+++ b/include/asm-ia64/mmu_context.h	Sat Jul 19 12:54:23 2003
@@ -86,9 +86,9 @@
 {
 	extern void local_flush_tlb_all (void);
 
-	if (unlikely(__get_cpu_var(ia64_need_tlb_flush))) {
+	if (unlikely(__ia64_per_cpu_var(ia64_need_tlb_flush))) {
 		local_flush_tlb_all();
-		__get_cpu_var(ia64_need_tlb_flush) = 0;
+		__ia64_per_cpu_var(ia64_need_tlb_flush) = 0;
 	}
 }
 
diff -Nru a/include/asm-ia64/percpu.h b/include/asm-ia64/percpu.h
--- a/include/asm-ia64/percpu.h	Sat Jul 19 12:54:26 2003
+++ b/include/asm-ia64/percpu.h	Sat Jul 19 12:54:26 2003
@@ -1,42 +1,72 @@
 #ifndef _ASM_IA64_PERCPU_H
 #define _ASM_IA64_PERCPU_H
 
-#include <linux/config.h>
-#include <linux/compiler.h>
-
 /*
  * Copyright (C) 2002-2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
+
 #define PERCPU_ENOUGH_ROOM PERCPU_PAGE_SIZE
 
 #ifdef __ASSEMBLY__
-
-#define THIS_CPU(var)	(var##__per_cpu)  /* use this to mark accesses to per-CPU variables... */
-
+# define THIS_CPU(var)	(per_cpu__##var)  /* use this to mark accesses to per-CPU variables... */
 #else /* !__ASSEMBLY__ */
 
+#include <linux/config.h>
+
 #include <linux/threads.h>
 
-extern unsigned long __per_cpu_offset[NR_CPUS];
+#ifdef HAVE_MODEL_SMALL_ATTRIBUTE
+# define __SMALL_ADDR_AREA	__attribute__((__model__ (__small__)))
+#else
+# define __SMALL_ADDR_AREA
+#endif
 
-#define DEFINE_PER_CPU(type, name) \
-    __attribute__((__section__(".data.percpu"))) __typeof__(type) name##__per_cpu
-#define DECLARE_PER_CPU(type, name) extern __typeof__(type) name##__per_cpu
+#define DECLARE_PER_CPU(type, name)				\
+	extern __SMALL_ADDR_AREA __typeof__(type) per_cpu__##name
 
-#define __get_cpu_var(var)	(var##__per_cpu)
+/* Separate out the type, so (int[3], foo) works. */
+#define DEFINE_PER_CPU(type, name)				\
+	__attribute__((__section__(".data.percpu")))		\
+	__SMALL_ADDR_AREA __typeof__(type) per_cpu__##name
+
+/*
+ * Pretty much a literal copy of asm-generic/percpu.h, except that percpu_modcopy() is an
+ * external routine, to avoid include-hell.
+ */
 #ifdef CONFIG_SMP
-# define per_cpu(var, cpu)	(*RELOC_HIDE(&var##__per_cpu, __per_cpu_offset[cpu]))
+
+extern unsigned long __per_cpu_offset[NR_CPUS];
+
+/* Equal to __per_cpu_offset[smp_processor_id()], but faster to access: */
+DECLARE_PER_CPU(unsigned long, local_per_cpu_offset);
+
+#define per_cpu(var, cpu)  (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
+#define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __ia64_per_cpu_var(local_per_cpu_offset)))
 
 extern void percpu_modcopy(void *pcpudst, const void *src, unsigned long size);
-#else
-# define per_cpu(var, cpu)	((void)cpu, __get_cpu_var(var))
-#endif
 
-#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(var##__per_cpu)
-#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(var##__per_cpu)
+#else /* ! SMP */
+
+#define per_cpu(var, cpu)			((void)cpu, per_cpu__##var)
+#define __get_cpu_var(var)			per_cpu__##var
+
+#endif	/* SMP */
+
+#define EXPORT_PER_CPU_SYMBOL(var)		EXPORT_SYMBOL(per_cpu__##var)
+#define EXPORT_PER_CPU_SYMBOL_GPL(var)		EXPORT_SYMBOL_GPL(per_cpu__##var)
+
+/* ia64-specific part: */
 
 extern void setup_per_cpu_areas (void);
+
+/*
+ * Be extremely careful when taking the address of this variable!  Due to virtual
+ * remapping, it is different from the canonical address returned by __get_cpu_var(var)!
+ * On the positive side, using __ia64_per_cpu_var() instead of __get_cpu_var() is slightly
+ * more efficient.
+ */
+#define __ia64_per_cpu_var(var)	(per_cpu__##var)
 
 #endif /* !__ASSEMBLY__ */
 
diff -Nru a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
--- a/include/asm-ia64/processor.h	Sat Jul 19 12:54:24 2003
+++ b/include/asm-ia64/processor.h	Sat Jul 19 12:54:24 2003
@@ -191,10 +191,12 @@
 DECLARE_PER_CPU(struct cpuinfo_ia64, cpu_info);
 
 /*
- * The "local" data pointer.  It points to the per-CPU data of the currently executing
+ * The "local" data variable.  It refers to the per-CPU data of the currently executing
  * CPU, much like "current" points to the per-task data of the currently executing task.
+ * Do not use the address of local_cpu_data, since it will be different from
+ * cpu_data(smp_processor_id())!
  */
-#define local_cpu_data		(&__get_cpu_var(cpu_info))
+#define local_cpu_data		(&__ia64_per_cpu_var(cpu_info))
 #define cpu_data(cpu)		(&per_cpu(cpu_info, cpu))
 
 extern void identify_cpu (struct cpuinfo_ia64 *);
diff -Nru a/include/asm-ia64/system.h b/include/asm-ia64/system.h
--- a/include/asm-ia64/system.h	Sat Jul 19 12:54:24 2003
+++ b/include/asm-ia64/system.h	Sat Jul 19 12:54:24 2003
@@ -20,9 +20,9 @@
 #include <asm/percpu.h>
 
 /* 0xa000000000000000 - 0xa000000000000000+PERCPU_PAGE_SIZE remain unmapped */
-#define PERCPU_ADDR		(0xa000000000000000 + PERCPU_PAGE_SIZE)
-#define GATE_ADDR		(0xa000000000000000 + 2*PERCPU_PAGE_SIZE)
+#define GATE_ADDR		(0xa000000000000000 + PERCPU_PAGE_SIZE)
 #define KERNEL_START		 0xa000000100000000
+#define PERCPU_ADDR		(-PERCPU_PAGE_SIZE)
 
 #ifndef __ASSEMBLY__
 
diff -Nru a/include/asm-ia64/tlb.h b/include/asm-ia64/tlb.h
--- a/include/asm-ia64/tlb.h	Sat Jul 19 12:54:24 2003
+++ b/include/asm-ia64/tlb.h	Sat Jul 19 12:54:24 2003
@@ -126,7 +126,7 @@
 static inline struct mmu_gather *
 tlb_gather_mmu (struct mm_struct *mm, unsigned int full_mm_flush)
 {
-	struct mmu_gather *tlb = &per_cpu(mmu_gathers, smp_processor_id());
+	struct mmu_gather *tlb = &__get_cpu_var(mmu_gathers);
 
 	tlb->mm = mm;
 	/*
diff -Nru a/include/asm-ppc/hardirq.h b/include/asm-ppc/hardirq.h
--- a/include/asm-ppc/hardirq.h	Sat Jul 19 12:54:21 2003
+++ b/include/asm-ppc/hardirq.h	Sat Jul 19 12:54:21 2003
@@ -14,8 +14,6 @@
  */
 typedef struct {
 	unsigned long __softirq_pending;	/* set_bit is used on this */
-	unsigned int __syscall_count;
-	struct task_struct * __ksoftirqd_task;
 	unsigned int __last_jiffy_stamp;
 } ____cacheline_aligned irq_cpustat_t;
 
diff -Nru a/include/asm-ppc/ipc.h b/include/asm-ppc/ipc.h
--- a/include/asm-ppc/ipc.h	Sat Jul 19 12:54:30 2003
+++ b/include/asm-ppc/ipc.h	Sat Jul 19 12:54:30 2003
@@ -14,6 +14,7 @@
 #define SEMOP		 1
 #define SEMGET		 2
 #define SEMCTL		 3
+#define SEMTIMEDOP	 4
 #define MSGSND		11
 #define MSGRCV		12
 #define MSGGET		13
diff -Nru a/include/asm-ppc/pci.h b/include/asm-ppc/pci.h
--- a/include/asm-ppc/pci.h	Sat Jul 19 12:54:26 2003
+++ b/include/asm-ppc/pci.h	Sat Jul 19 12:54:26 2003
@@ -53,18 +53,12 @@
 extern unsigned long pci_phys_to_bus(unsigned long pa, int busnr);
 extern unsigned long pci_bus_to_phys(unsigned int ba, int busnr);
     
-/* Dynamic DMA Mapping stuff, stolen from i386
- * 	++ajoshi
+/*
+ * Dynamic DMA Mapping stuff
+ * Originally stolen from i386 by ajoshi and updated by paulus
+ * Non-consistent cache support by Dan Malek
  */
 
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <asm/scatterlist.h>
-#include <asm/io.h>
-
-struct pci_dev;
-
 /* The PCI address space does equal the physical memory
  * address space.  The networking and block device layers use
  * this boolean for bounce buffer decisions.
@@ -101,8 +95,7 @@
 static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
 					size_t size, int direction)
 {
-	if (direction == PCI_DMA_NONE)
-		BUG();
+	BUG_ON(direction == PCI_DMA_NONE);
 
 	consistent_sync(ptr, size, direction);
 
@@ -130,10 +123,11 @@
  * to pci_map_single, but takes a struct page instead of a virtual address
  */
 static inline dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page,
-				      unsigned long offset, size_t size, int direction)
+				      unsigned long offset, size_t size,
+				      int direction)
 {
-	if (direction == PCI_DMA_NONE)
-		BUG();
+	BUG_ON(direction == PCI_DMA_NONE);
+	consistent_sync_page(page, offset, size, direction);
 	return (page - mem_map) * PAGE_SIZE + PCI_DRAM_OFFSET + offset;
 }
 
@@ -171,10 +165,11 @@
 	/*
 	 * temporary 2.4 hack
 	 */
-	for (i = 0; i < nents; i++) {
-		if (!sg[i].page)
-			BUG();
-		sg[i].dma_address = page_to_bus(sg[i].page) + sg[i].offset;
+	for (i = 0; i < nents; i++, sg++) {
+		BUG_ON(!sg->page);
+		consistent_sync_page(sg->page, sg->offset,
+				     sg->length, direction);
+		sg->dma_address = page_to_bus(sg->page) + sg->offset;
 	}
 
 	return nents;
@@ -187,8 +182,7 @@
 static inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
 				int nents, int direction)
 {
-	if (direction == PCI_DMA_NONE)
-		BUG();
+	BUG_ON(direction == PCI_DMA_NONE);
 	/* nothing to do */
 }
 
@@ -205,8 +199,7 @@
 				       dma_addr_t dma_handle,
 				       size_t size, int direction)
 {
-	if (direction == PCI_DMA_NONE)
-		BUG();
+	BUG_ON(direction == PCI_DMA_NONE);
 
 	consistent_sync(bus_to_virt(dma_handle), size, direction);
 }
@@ -221,9 +214,13 @@
 				   struct scatterlist *sg,
 				   int nelems, int direction)
 {
-	if (direction == PCI_DMA_NONE)
-		BUG();
-	/* nothing to do */
+	int i;
+
+	BUG_ON(direction == PCI_DMA_NONE);
+
+	for (i = 0; i < nelems; i++, sg++)
+		consistent_sync_page(sg->page, sg->offset,
+				     sg->length, direction);
 }
 
 /* Return whether the given PCI device DMA address mask can
diff -Nru a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h
--- a/include/asm-ppc/processor.h	Sat Jul 19 12:54:21 2003
+++ b/include/asm-ppc/processor.h	Sat Jul 19 12:54:21 2003
@@ -705,6 +705,7 @@
 	.ksp = INIT_SP, \
 	.fs = KERNEL_DS, \
 	.pgdir = swapper_pg_dir, \
+	.fpexc_mode = MSR_FE0 | MSR_FE1, \
 }
 
 /*
diff -Nru a/include/asm-ppc/uaccess.h b/include/asm-ppc/uaccess.h
--- a/include/asm-ppc/uaccess.h	Sat Jul 19 12:54:21 2003
+++ b/include/asm-ppc/uaccess.h	Sat Jul 19 12:54:21 2003
@@ -16,10 +16,13 @@
  * get_fs() == KERNEL_DS, checking is bypassed.
  *
  * For historical reasons, these macros are grossly misnamed.
+ *
+ * The fs/ds values are now the highest legal address in the "segment".
+ * This simplifies the checking in the routines below.
  */
 
-#define KERNEL_DS	((mm_segment_t) { 0 })
-#define USER_DS		((mm_segment_t) { 1 })
+#define KERNEL_DS	((mm_segment_t) { ~0UL })
+#define USER_DS		((mm_segment_t) { TASK_SIZE - 1 })
 
 #define get_ds()	(KERNEL_DS)
 #define get_fs()	(current->thread.fs)
@@ -27,14 +30,15 @@
 
 #define segment_eq(a,b)	((a).seg == (b).seg)
 
-#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
-#define __user_ok(addr,size) (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size)))
-#define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size)))
-#define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
+#define __access_ok(addr,size)						    \
+	((addr) <= current->thread.fs.seg				    \
+	 && ((size) == 0 || (size) - 1 <= current->thread.fs.seg - (addr)))
+
+#define access_ok(type, addr, size) __access_ok((unsigned long)(addr),(size))
 
 extern inline int verify_area(int type, const void __user * addr, unsigned long size)
 {
-	return access_ok(type,addr,size) ? 0 : -EFAULT;
+	return access_ok(type, addr, size) ? 0 : -EFAULT;
 }
 
 
@@ -303,7 +307,7 @@
  */
 extern __inline__ int strnlen_user(const char __user *str, long len)
 {
-	unsigned long top = __kernel_ok? ~0UL: TASK_SIZE - 1;
+	unsigned long top = current->thread.fs.seg;
 
 	if ((unsigned long)str > top)
 		return 0;
diff -Nru a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h
--- a/include/asm-ppc/unistd.h	Sat Jul 19 12:54:23 2003
+++ b/include/asm-ppc/unistd.h	Sat Jul 19 12:54:23 2003
@@ -253,177 +253,112 @@
 #define __NR_clock_gettime	246
 #define __NR_clock_getres	247
 #define __NR_clock_nanosleep	248
+#define __NR_swapcontext	249
+#define __NR_tgkill		250
+#define __NR_utimes		251
+#define __NR_statfs64		252
+#define __NR_fstatfs64		253
 
-#define __NR_syscalls		249
+#define __NR_syscalls		254
 
 #define __NR(n)	#n
 
-#define __syscall_return(type) \
-	return (__sc_err & 0x10000000 ? errno = __sc_ret, __sc_ret = -1 : 0), \
-	       (type) __sc_ret
-
-#define __syscall_clobbers \
-	"r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
+/* On powerpc a system call basically clobbers the same registers like a
+ * function call, with the exception of LR (which is needed for the
+ * "sc; bnslr" sequence) and CR (where only CR0.SO is clobbered to signal
+ * an error return status).
+ */
+
+#define __syscall_nr(nr, type, name, args...)				\
+	unsigned long __sc_ret, __sc_err;				\
+	{								\
+		register unsigned long __sc_0  __asm__ ("r0");		\
+		register unsigned long __sc_3  __asm__ ("r3");		\
+		register unsigned long __sc_4  __asm__ ("r4");		\
+		register unsigned long __sc_5  __asm__ ("r5");		\
+		register unsigned long __sc_6  __asm__ ("r6");		\
+		register unsigned long __sc_7  __asm__ ("r7");		\
+									\
+		__sc_loadargs_##nr(name, args);				\
+		__asm__ __volatile__					\
+			("sc           \n\t"				\
+			 "mfcr %0      "				\
+			: "=&r" (__sc_0),				\
+			  "=&r" (__sc_3),  "=&r" (__sc_4),		\
+			  "=&r" (__sc_5),  "=&r" (__sc_6),		\
+			  "=&r" (__sc_7)				\
+			: __sc_asm_input_##nr				\
+			: "cr0", "ctr", "memory",			\
+			  "r8", "r9", "r10","r11", "r12");		\
+		__sc_ret = __sc_3;					\
+		__sc_err = __sc_0;					\
+	}								\
+	if (__sc_err & 0x10000000)					\
+	{								\
+		errno = __sc_ret;					\
+		__sc_ret = -1;						\
+	}								\
+	return (type) __sc_ret
+
+#define __sc_loadargs_0(name, dummy...)					\
+	__sc_0 = __NR_##name
+#define __sc_loadargs_1(name, arg1)					\
+	__sc_loadargs_0(name);						\
+	__sc_3 = (unsigned long) (arg1)
+#define __sc_loadargs_2(name, arg1, arg2)				\
+	__sc_loadargs_1(name, arg1);					\
+	__sc_4 = (unsigned long) (arg2)
+#define __sc_loadargs_3(name, arg1, arg2, arg3)				\
+	__sc_loadargs_2(name, arg1, arg2);				\
+	__sc_5 = (unsigned long) (arg3)
+#define __sc_loadargs_4(name, arg1, arg2, arg3, arg4)			\
+	__sc_loadargs_3(name, arg1, arg2, arg3);			\
+	__sc_6 = (unsigned long) (arg4)
+#define __sc_loadargs_5(name, arg1, arg2, arg3, arg4, arg5)		\
+	__sc_loadargs_4(name, arg1, arg2, arg3, arg4);			\
+	__sc_7 = (unsigned long) (arg5)
+
+#define __sc_asm_input_0 "0" (__sc_0)
+#define __sc_asm_input_1 __sc_asm_input_0, "1" (__sc_3)
+#define __sc_asm_input_2 __sc_asm_input_1, "2" (__sc_4)
+#define __sc_asm_input_3 __sc_asm_input_2, "3" (__sc_5)
+#define __sc_asm_input_4 __sc_asm_input_3, "4" (__sc_6)
+#define __sc_asm_input_5 __sc_asm_input_4, "5" (__sc_7)
 
 #define _syscall0(type,name)						\
 type name(void)								\
 {									\
-	unsigned long __sc_ret, __sc_err;				\
-	{								\
-		register unsigned long __sc_0 __asm__ ("r0");		\
-		register unsigned long __sc_3 __asm__ ("r3");		\
-									\
-		__sc_0 = __NR_##name;					\
-		__asm__ __volatile__					\
-			("sc           \n\t"				\
-			 "mfcr %1      "				\
-			: "=&r" (__sc_3), "=&r" (__sc_0)		\
-			: "0"   (__sc_3), "1"   (__sc_0)		\
-			: __syscall_clobbers);				\
-		__sc_ret = __sc_3;					\
-		__sc_err = __sc_0;					\
-	}								\
-	__syscall_return (type);					\
+	__syscall_nr(0, type, name);					\
 }
 
 #define _syscall1(type,name,type1,arg1)					\
 type name(type1 arg1)							\
 {									\
-	unsigned long __sc_ret, __sc_err;				\
-	{								\
-		register unsigned long __sc_0 __asm__ ("r0");		\
-		register unsigned long __sc_3 __asm__ ("r3");		\
-									\
-		__sc_3 = (unsigned long) (arg1);			\
-		__sc_0 = __NR_##name;					\
-		__asm__ __volatile__					\
-			("sc           \n\t"				\
-			 "mfcr %1      "				\
-			: "=&r" (__sc_3), "=&r" (__sc_0)		\
-			: "0"   (__sc_3), "1"   (__sc_0)		\
-			: __syscall_clobbers);				\
-		__sc_ret = __sc_3;					\
-		__sc_err = __sc_0;					\
-	}								\
-	__syscall_return (type);					\
+	__syscall_nr(1, type, name, arg1);				\
 }
 
 #define _syscall2(type,name,type1,arg1,type2,arg2)			\
 type name(type1 arg1, type2 arg2)					\
 {									\
-	unsigned long __sc_ret, __sc_err;				\
-	{								\
-		register unsigned long __sc_0 __asm__ ("r0");		\
-		register unsigned long __sc_3 __asm__ ("r3");		\
-		register unsigned long __sc_4 __asm__ ("r4");		\
-									\
-		__sc_3 = (unsigned long) (arg1);			\
-		__sc_4 = (unsigned long) (arg2);			\
-		__sc_0 = __NR_##name;					\
-		__asm__ __volatile__					\
-			("sc           \n\t"				\
-			 "mfcr %1      "				\
-			: "=&r" (__sc_3), "=&r" (__sc_0)		\
-			: "0"   (__sc_3), "1"   (__sc_0),		\
-			  "r"   (__sc_4)				\
-			: __syscall_clobbers);				\
-		__sc_ret = __sc_3;					\
-		__sc_err = __sc_0;					\
-	}								\
-	__syscall_return (type);					\
+	__syscall_nr(2, type, name, arg1, arg2);			\
 }
 
 #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)		\
 type name(type1 arg1, type2 arg2, type3 arg3)				\
 {									\
-	unsigned long __sc_ret, __sc_err;				\
-	{								\
-		register unsigned long __sc_0 __asm__ ("r0");		\
-		register unsigned long __sc_3 __asm__ ("r3");		\
-		register unsigned long __sc_4 __asm__ ("r4");		\
-		register unsigned long __sc_5 __asm__ ("r5");		\
-									\
-		__sc_3 = (unsigned long) (arg1);			\
-		__sc_4 = (unsigned long) (arg2);			\
-		__sc_5 = (unsigned long) (arg3);			\
-		__sc_0 = __NR_##name;					\
-		__asm__ __volatile__					\
-			("sc           \n\t"				\
-			 "mfcr %1      "				\
-			: "=&r" (__sc_3), "=&r" (__sc_0)		\
-			: "0"   (__sc_3), "1"   (__sc_0),		\
-			  "r"   (__sc_4),				\
-			  "r"   (__sc_5)				\
-			: __syscall_clobbers);				\
-		__sc_ret = __sc_3;					\
-		__sc_err = __sc_0;					\
-	}								\
-	__syscall_return (type);					\
+	__syscall_nr(3, type, name, arg1, arg2, arg3);			\
 }
 
 #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
 type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4)		\
 {									\
-	unsigned long __sc_ret, __sc_err;				\
-	{								\
-		register unsigned long __sc_0 __asm__ ("r0");		\
-		register unsigned long __sc_3 __asm__ ("r3");		\
-		register unsigned long __sc_4 __asm__ ("r4");		\
-		register unsigned long __sc_5 __asm__ ("r5");		\
-		register unsigned long __sc_6 __asm__ ("r6");		\
-									\
-		__sc_3 = (unsigned long) (arg1);			\
-		__sc_4 = (unsigned long) (arg2);			\
-		__sc_5 = (unsigned long) (arg3);			\
-		__sc_6 = (unsigned long) (arg4);			\
-		__sc_0 = __NR_##name;					\
-		__asm__ __volatile__					\
-			("sc           \n\t"				\
-			 "mfcr %1      "				\
-			: "=&r" (__sc_3), "=&r" (__sc_0)		\
-			: "0"   (__sc_3), "1"   (__sc_0),		\
-			  "r"   (__sc_4),				\
-			  "r"   (__sc_5),				\
-			  "r"   (__sc_6)				\
-			: __syscall_clobbers);				\
-		__sc_ret = __sc_3;					\
-		__sc_err = __sc_0;					\
-	}								\
-	__syscall_return (type);					\
+	__syscall_nr(4, type, name, arg1, arg2, arg3, arg4);		\
 }
 
 #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
 type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)	\
 {									\
-	unsigned long __sc_ret, __sc_err;				\
-	{								\
-		register unsigned long __sc_0 __asm__ ("r0");		\
-		register unsigned long __sc_3 __asm__ ("r3");		\
-		register unsigned long __sc_4 __asm__ ("r4");		\
-		register unsigned long __sc_5 __asm__ ("r5");		\
-		register unsigned long __sc_6 __asm__ ("r6");		\
-		register unsigned long __sc_7 __asm__ ("r7");		\
-									\
-		__sc_3 = (unsigned long) (arg1);			\
-		__sc_4 = (unsigned long) (arg2);			\
-		__sc_5 = (unsigned long) (arg3);			\
-		__sc_6 = (unsigned long) (arg4);			\
-		__sc_7 = (unsigned long) (arg5);			\
-		__sc_0 = __NR_##name;					\
-		__asm__ __volatile__					\
-			("sc           \n\t"				\
-			 "mfcr %1      "				\
-			: "=&r" (__sc_3), "=&r" (__sc_0)		\
-			: "0"   (__sc_3), "1"   (__sc_0),		\
-			  "r"   (__sc_4),				\
-			  "r"   (__sc_5),				\
-			  "r"   (__sc_6),				\
-			  "r"   (__sc_7)				\
-			: __syscall_clobbers);				\
-		__sc_ret = __sc_3;					\
-		__sc_err = __sc_0;					\
-	}								\
-	__syscall_return (type);					\
+	__syscall_nr(5, type, name, arg1, arg2, arg3, arg4, arg5);	\
 }
 
 #ifdef __KERNEL__
diff -Nru a/include/asm-s390/dma-mapping.h b/include/asm-s390/dma-mapping.h
--- a/include/asm-s390/dma-mapping.h	Sat Jul 19 12:54:30 2003
+++ b/include/asm-s390/dma-mapping.h	Sat Jul 19 12:54:30 2003
@@ -1 +1,11 @@
-#include <asm-generic/dma-mapping.h>
+/*
+ *  include/asm-s390/dma-mapping.h
+ *
+ *  S390 version
+ *
+ *  This file exists so that #include <dma-mapping.h> doesn't break anything.
+ */
+
+#ifndef _ASM_DMA_MAPPING_H
+#define _ASM_DMA_MAPPING_H
+#endif /* _ASM_DMA_MAPPING_H */
diff -Nru a/include/asm-s390/dma.h b/include/asm-s390/dma.h
--- a/include/asm-s390/dma.h	Sat Jul 19 12:54:27 2003
+++ b/include/asm-s390/dma.h	Sat Jul 19 12:54:27 2003
@@ -2,8 +2,6 @@
  *  include/asm-s390/dma.h
  *
  *  S390 version
- *
- *  This file exists so that an #include <dma.h> doesn't break anything.
  */
 
 #ifndef _ASM_DMA_H
diff -Nru a/include/asm-s390/irq.h b/include/asm-s390/irq.h
--- a/include/asm-s390/irq.h	Sat Jul 19 12:54:27 2003
+++ b/include/asm-s390/irq.h	Sat Jul 19 12:54:27 2003
@@ -8,16 +8,13 @@
  * the definition of irqs has changed in 2.5.46:
  * NR_IRQS is no longer the number of i/o
  * interrupts (65536), but rather the number
- * of interrupt classes (6).
+ * of interrupt classes (2).
+ * Only external and i/o interrupts make much sense here (CH).
  */
 
 enum interruption_class {
 	EXTERNAL_INTERRUPT,
 	IO_INTERRUPT,
-	MACHINE_CHECK_INTERRUPT,
-	PROGRAM_INTERRUPT,
-	RESTART_INTERRUPT,
-	SUPERVISOR_CALL,
 
 	NR_IRQS,
 };
diff -Nru a/include/asm-s390/siginfo.h b/include/asm-s390/siginfo.h
--- a/include/asm-s390/siginfo.h	Sat Jul 19 12:54:27 2003
+++ b/include/asm-s390/siginfo.h	Sat Jul 19 12:54:27 2003
@@ -10,6 +10,9 @@
 #define _S390_SIGINFO_H
 
 #define HAVE_ARCH_SI_CODES
+#ifdef __s390x__
+#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
+#endif
 
 #include <asm-generic/siginfo.h>
 
diff -Nru a/include/asm-sparc64/atomic.h b/include/asm-sparc64/atomic.h
--- a/include/asm-sparc64/atomic.h	Sat Jul 19 12:54:29 2003
+++ b/include/asm-sparc64/atomic.h	Sat Jul 19 12:54:29 2003
@@ -9,25 +9,46 @@
 #define __ARCH_SPARC64_ATOMIC__
 
 typedef struct { volatile int counter; } atomic_t;
-#define ATOMIC_INIT(i)	{ (i) }
+typedef struct { volatile long counter; } atomic64_t;
+
+#define ATOMIC_INIT(i)		{ (i) }
+#define ATOMIC64_INIT(i)	{ (i) }
 
 #define atomic_read(v)		((v)->counter)
+#define atomic64_read(v)	((v)->counter)
+
 #define atomic_set(v, i)	(((v)->counter) = i)
+#define atomic64_set(v, i)	(((v)->counter) = i)
 
 extern int __atomic_add(int, atomic_t *);
+extern int __atomic64_add(int, atomic64_t *);
+
 extern int __atomic_sub(int, atomic_t *);
+extern int __atomic64_sub(int, atomic64_t *);
 
 #define atomic_add(i, v) ((void)__atomic_add(i, v))
+#define atomic64_add(i, v) ((void)__atomic64_add(i, v))
+
 #define atomic_sub(i, v) ((void)__atomic_sub(i, v))
+#define atomic64_sub(i, v) ((void)__atomic64_sub(i, v))
 
 #define atomic_dec_return(v) __atomic_sub(1, v)
+#define atomic64_dec_return(v) __atomic64_sub(1, v)
+
 #define atomic_inc_return(v) __atomic_add(1, v)
+#define atomic64_inc_return(v) __atomic64_add(1, v)
 
 #define atomic_sub_and_test(i, v) (__atomic_sub(i, v) == 0)
+#define atomic64_sub_and_test(i, v) (__atomic64_sub(i, v) == 0)
+
 #define atomic_dec_and_test(v) (__atomic_sub(1, v) == 0)
+#define atomic64_dec_and_test(v) (__atomic64_sub(1, v) == 0)
 
 #define atomic_inc(v) ((void)__atomic_add(1, v))
+#define atomic64_inc(v) ((void)__atomic64_add(1, v))
+
 #define atomic_dec(v) ((void)__atomic_sub(1, v))
+#define atomic64_dec(v) ((void)__atomic64_sub(1, v))
 
 /* Atomic operations are already serializing */
 #define smp_mb__before_atomic_dec()	barrier()
diff -Nru a/include/asm-sparc64/local.h b/include/asm-sparc64/local.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-sparc64/local.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,40 @@
+#ifndef _ARCH_SPARC64_LOCAL_H
+#define _ARCH_SPARC64_LOCAL_H
+
+#include <linux/percpu.h>
+#include <asm/atomic.h>
+
+typedef atomic64_t local_t;
+
+#define LOCAL_INIT(i)	ATOMIC64_INIT(i)
+#define local_read(v)	atomic64_read(v)
+#define local_set(v,i)	atomic64_set(v,i)
+
+#define local_inc(v)	atomic64_inc(v)
+#define local_dec(v)	atomic64_inc(v)
+#define local_add(i, v)	atomic64_add(i, v)
+#define local_sub(i, v)	atomic64_sub(i, v)
+
+#define __local_inc(v)		((v)->counter++)
+#define __local_dec(v)		((v)->counter++)
+#define __local_add(i,v)	((v)->counter+=(i))
+#define __local_sub(i,v)	((v)->counter-=(i))
+
+/* Use these for per-cpu local_t variables: on some archs they are
+ * much more efficient than these naive implementations.  Note they take
+ * a variable, not an address.
+ */
+#define cpu_local_read(v)	local_read(&__get_cpu_var(v))
+#define cpu_local_set(v, i)	local_set(&__get_cpu_var(v), (i))
+
+#define cpu_local_inc(v)	local_inc(&__get_cpu_var(v))
+#define cpu_local_dec(v)	local_dec(&__get_cpu_var(v))
+#define cpu_local_add(i, v)	local_add((i), &__get_cpu_var(v))
+#define cpu_local_sub(i, v)	local_sub((i), &__get_cpu_var(v))
+
+#define __cpu_local_inc(v)	__local_inc(&__get_cpu_var(v))
+#define __cpu_local_dec(v)	__local_dec(&__get_cpu_var(v))
+#define __cpu_local_add(i, v)	__local_add((i), &__get_cpu_var(v))
+#define __cpu_local_sub(i, v)	__local_sub((i), &__get_cpu_var(v))
+
+#endif /* _ARCH_SPARC64_LOCAL_H */
diff -Nru a/include/asm-sparc64/sections.h b/include/asm-sparc64/sections.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-sparc64/sections.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,7 @@
+#ifndef _SPARC64_SECTIONS_H
+#define _SPARC64_SECTIONS_H
+
+/* nothing to see, move along */
+#include <asm-generic/sections.h>
+
+#endif
diff -Nru a/include/asm-v850/anna.h b/include/asm-v850/anna.h
--- a/include/asm-v850/anna.h	Sat Jul 19 12:54:24 2003
+++ b/include/asm-v850/anna.h	Sat Jul 19 12:54:24 2003
@@ -1,8 +1,8 @@
 /*
  * include/asm-v850/anna.h -- Anna V850E2 evaluation cpu chip/board
  *
- *  Copyright (C) 2001,2002  NEC Corporation
- *  Copyright (C) 2001,2002  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -14,8 +14,9 @@
 #ifndef __V850_ANNA_H__
 #define __V850_ANNA_H__
 
+#include <asm/v850e2.h>		/* Based on V850E2 core.  */
+
 
-#define CPU_ARCH 	"v850e2"
 #define CPU_MODEL	"v850e2/anna"
 #define CPU_MODEL_LONG	"NEC V850E2/Anna"
 #define PLATFORM	"anna"
@@ -48,30 +49,6 @@
 
 
 /* Anna specific control registers.  */
-#define ANNA_CSC_ADDR(n)		(0xFFFFF060 + (n) * 2)
-#define ANNA_CSC(n)			(*(volatile u16 *)ANNA_CSC_ADDR(n))
-#define ANNA_BPC_ADDR			0xFFFFF064
-#define ANNA_BPC			(*(volatile u16 *)ANNA_BPC_ADDR)
-#define ANNA_BSC_ADDR			0xFFFFF066
-#define ANNA_BSC			(*(volatile u16 *)ANNA_BSC_ADDR)
-#define ANNA_BEC_ADDR			0xFFFFF068
-#define ANNA_BEC			(*(volatile u16 *)ANNA_BEC_ADDR)
-#define ANNA_BHC_ADDR			0xFFFFF06A
-#define ANNA_BHC			(*(volatile u16 *)ANNA_BHC_ADDR)
-#define ANNA_BCT_ADDR(n)		(0xFFFFF480 + (n) * 2)
-#define ANNA_BCT(n)			(*(volatile u16 *)ANNA_BCT_ADDR(n))
-#define ANNA_DWC_ADDR(n)		(0xFFFFF484 + (n) * 2)
-#define ANNA_DWC(n)			(*(volatile u16 *)ANNA_DWC_ADDR(n))
-#define ANNA_BCC_ADDR			0xFFFFF488
-#define ANNA_BCC			(*(volatile u16 *)ANNA_BCC_ADDR)
-#define ANNA_ASC_ADDR			0xFFFFF48A
-#define ANNA_ASC			(*(volatile u16 *)ANNA_ASC_ADDR)
-#define ANNA_LBS_ADDR			0xFFFFF48E
-#define ANNA_LBS			(*(volatile u16 *)ANNA_LBS_ADDR)
-#define ANNA_SCR3_ADDR			0xFFFFF4AC
-#define ANNA_SCR3			(*(volatile u16 *)ANNA_SCR3_ADDR)
-#define ANNA_RFS3_ADDR			0xFFFFF4AE
-#define ANNA_RFS3			(*(volatile u16 *)ANNA_RFS3_ADDR)
 #define ANNA_ILBEN_ADDR			0xFFFFF7F2
 #define ANNA_ILBEN			(*(volatile u16 *)ANNA_ILBEN_ADDR)
 
@@ -85,9 +62,6 @@
 #define ANNA_PORT_PM(n)			(*(volatile u8 *)ANNA_PORT_PM_ADDR(n))
 
 
-/* NB85E-style interrupt system.  */
-#include <asm/nb85e_intc.h>
-
 /* Hardware-specific interrupt numbers (in the kernel IRQ namespace).  */
 #define IRQ_INTP(n)	(n)	/* Pnnn (pin) interrupts 0-15 */
 #define IRQ_INTP_NUM	16
@@ -116,12 +90,15 @@
 
 
 /* Anna UART details (basically the same as the V850E/MA1, but 2 channels).  */
-#define NB85E_UART_NUM_CHANNELS		2
-#define NB85E_UART_BASE_FREQ		(SYS_CLOCK_FREQ / 2)
-#define NB85E_UART_CHIP_NAME 		"V850E2/NA85E2A"
+#define V850E_UART_NUM_CHANNELS		2
+#define V850E_UART_BASE_FREQ		(SYS_CLOCK_FREQ / 2)
+#define V850E_UART_CHIP_NAME 		"V850E2/NA85E2A"
+
+/* This is the UART channel that's actually connected on the board.  */
+#define V850E_UART_CONSOLE_CHANNEL	1
 
 /* This is a function that gets called before configuring the UART.  */
-#define NB85E_UART_PRE_CONFIGURE	anna_uart_pre_configure
+#define V850E_UART_PRE_CONFIGURE	anna_uart_pre_configure
 #ifndef __ASSEMBLY__
 extern void anna_uart_pre_configure (unsigned chan,
 				     unsigned cflags, unsigned baud);
@@ -130,9 +107,9 @@
 /* This board supports RTS/CTS for the on-chip UART, but only for channel 1. */
 
 /* CTS for UART channel 1 is pin P37 (bit 7 of port 3).  */
-#define NB85E_UART_CTS(chan)	((chan) == 1 ? !(ANNA_PORT_IO(3) & 0x80) : 1)
+#define V850E_UART_CTS(chan)	((chan) == 1 ? !(ANNA_PORT_IO(3) & 0x80) : 1)
 /* RTS for UART channel 1 is pin P07 (bit 7 of port 0).  */
-#define NB85E_UART_SET_RTS(chan, val)					      \
+#define V850E_UART_SET_RTS(chan, val)					      \
    do {									      \
 	   if (chan == 1) {						      \
 		   unsigned old = ANNA_PORT_IO(0); 			      \
@@ -145,16 +122,16 @@
 
 
 /* Timer C details.  */
-#define NB85E_TIMER_C_BASE_ADDR		0xFFFFF600
+#define V850E_TIMER_C_BASE_ADDR		0xFFFFF600
 
 /* Timer D details (the Anna actually has 5 of these; should change later). */
-#define NB85E_TIMER_D_BASE_ADDR		0xFFFFF540
-#define NB85E_TIMER_D_TMD_BASE_ADDR 	(NB85E_TIMER_D_BASE_ADDR + 0x0)
-#define NB85E_TIMER_D_CMD_BASE_ADDR 	(NB85E_TIMER_D_BASE_ADDR + 0x2)
-#define NB85E_TIMER_D_TMCD_BASE_ADDR 	(NB85E_TIMER_D_BASE_ADDR + 0x4)
+#define V850E_TIMER_D_BASE_ADDR		0xFFFFF540
+#define V850E_TIMER_D_TMD_BASE_ADDR 	(V850E_TIMER_D_BASE_ADDR + 0x0)
+#define V850E_TIMER_D_CMD_BASE_ADDR 	(V850E_TIMER_D_BASE_ADDR + 0x2)
+#define V850E_TIMER_D_TMCD_BASE_ADDR 	(V850E_TIMER_D_BASE_ADDR + 0x4)
 
-#define NB85E_TIMER_D_BASE_FREQ		SYS_CLOCK_FREQ
-#define NB85E_TIMER_D_TMCD_CS_MIN	1 /* min 2^1 divider */
+#define V850E_TIMER_D_BASE_FREQ		SYS_CLOCK_FREQ
+#define V850E_TIMER_D_TMCD_CS_MIN	1 /* min 2^1 divider */
 
 
 /* For <asm/param.h> */
diff -Nru a/include/asm-v850/as85ep1.h b/include/asm-v850/as85ep1.h
--- a/include/asm-v850/as85ep1.h	Sat Jul 19 12:54:27 2003
+++ b/include/asm-v850/as85ep1.h	Sat Jul 19 12:54:27 2003
@@ -1,8 +1,8 @@
 /*
  * include/asm-v850/as85ep1.h -- AS85EP1 evaluation CPU chip/board
  *
- *  Copyright (C) 2001,2002  NEC Corporation
- *  Copyright (C) 2001,2002  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -14,8 +14,9 @@
 #ifndef __V850_AS85EP1_H__
 #define __V850_AS85EP1_H__
 
+#include <asm/v850e.h>
+
 
-#define CPU_ARCH 	"v850e"
 #define CPU_MODEL	"as85ep1"
 #define CPU_MODEL_LONG	"NEC V850E/AS85EP1"
 #define PLATFORM	"AS85EP1"
@@ -86,9 +87,6 @@
 #define AS85EP1_PORT_PMC(n)	(*(volatile u8 *)AS85EP1_PORT_PMC_ADDR(n))
 
 
-/* NB85E-style interrupt system.  */
-#include <asm/nb85e_intc.h>
-
 /* Hardware-specific interrupt numbers (in the kernel IRQ namespace).  */
 #define IRQ_INTCCC(n)	(0x0C + (n))
 #define IRQ_INTCCC_NUM	8
@@ -110,12 +108,12 @@
 
 
 /* AS85EP1 UART details (basically the same as the V850E/MA1, but 2 channels).  */
-#define NB85E_UART_NUM_CHANNELS		2
-#define NB85E_UART_BASE_FREQ		(SYS_CLOCK_FREQ / 4)
-#define NB85E_UART_CHIP_NAME 		"V850E/NA85E"
+#define V850E_UART_NUM_CHANNELS		2
+#define V850E_UART_BASE_FREQ		(SYS_CLOCK_FREQ / 4)
+#define V850E_UART_CHIP_NAME 		"V850E/NA85E"
 
 /* This is a function that gets called before configuring the UART.  */
-#define NB85E_UART_PRE_CONFIGURE	as85ep1_uart_pre_configure
+#define V850E_UART_PRE_CONFIGURE	as85ep1_uart_pre_configure
 #ifndef __ASSEMBLY__
 extern void as85ep1_uart_pre_configure (unsigned chan,
 					unsigned cflags, unsigned baud);
@@ -124,9 +122,9 @@
 /* This board supports RTS/CTS for the on-chip UART, but only for channel 1. */
 
 /* CTS for UART channel 1 is pin P54 (bit 4 of port 5).  */
-#define NB85E_UART_CTS(chan)   ((chan) == 1 ? !(AS85EP1_PORT_IO(5) & 0x10) : 1)
+#define V850E_UART_CTS(chan)   ((chan) == 1 ? !(AS85EP1_PORT_IO(5) & 0x10) : 1)
 /* RTS for UART channel 1 is pin P53 (bit 3 of port 5).  */
-#define NB85E_UART_SET_RTS(chan, val)					      \
+#define V850E_UART_SET_RTS(chan, val)					      \
    do {									      \
 	   if (chan == 1) {						      \
 		   unsigned old = AS85EP1_PORT_IO(5); 			      \
@@ -139,16 +137,16 @@
 
 
 /* Timer C details.  */
-#define NB85E_TIMER_C_BASE_ADDR		0xFFFFF600
+#define V850E_TIMER_C_BASE_ADDR		0xFFFFF600
 
 /* Timer D details (the AS85EP1 actually has 5 of these; should change later). */
-#define NB85E_TIMER_D_BASE_ADDR		0xFFFFF540
-#define NB85E_TIMER_D_TMD_BASE_ADDR 	(NB85E_TIMER_D_BASE_ADDR + 0x0)
-#define NB85E_TIMER_D_CMD_BASE_ADDR 	(NB85E_TIMER_D_BASE_ADDR + 0x2)
-#define NB85E_TIMER_D_TMCD_BASE_ADDR 	(NB85E_TIMER_D_BASE_ADDR + 0x4)
+#define V850E_TIMER_D_BASE_ADDR		0xFFFFF540
+#define V850E_TIMER_D_TMD_BASE_ADDR 	(V850E_TIMER_D_BASE_ADDR + 0x0)
+#define V850E_TIMER_D_CMD_BASE_ADDR 	(V850E_TIMER_D_BASE_ADDR + 0x2)
+#define V850E_TIMER_D_TMCD_BASE_ADDR 	(V850E_TIMER_D_BASE_ADDR + 0x4)
 
-#define NB85E_TIMER_D_BASE_FREQ		SYS_CLOCK_FREQ
-#define NB85E_TIMER_D_TMCD_CS_MIN	2 /* min 2^2 divider */
+#define V850E_TIMER_D_BASE_FREQ		SYS_CLOCK_FREQ
+#define V850E_TIMER_D_TMCD_CS_MIN	2 /* min 2^2 divider */
 
 
 /* For <asm/param.h> */
diff -Nru a/include/asm-v850/asm.h b/include/asm-v850/asm.h
--- a/include/asm-v850/asm.h	Sat Jul 19 12:54:24 2003
+++ b/include/asm-v850/asm.h	Sat Jul 19 12:54:24 2003
@@ -1,7 +1,7 @@
 /*
  * include/asm-v850/asm.h -- Macros for writing assembly code
  *
- *  Copyright (C) 2001,02,03  NEC Corporation
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
  *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
diff -Nru a/include/asm-v850/cacheflush.h b/include/asm-v850/cacheflush.h
--- a/include/asm-v850/cacheflush.h	Sat Jul 19 12:54:24 2003
+++ b/include/asm-v850/cacheflush.h	Sat Jul 19 12:54:24 2003
@@ -1,8 +1,8 @@
 /*
  * include/asm-v850/cacheflush.h
  *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -21,21 +21,40 @@
 #include <asm/machdep.h>
 
 
-#ifndef flush_cache_all
-/* If there's no flush_cache_all macro defined by <asm/machdep.h>, then
-   this processor has no cache, so just define these as nops.  */
-
+/* The following are all used by the kernel in ways that only affect
+   systems with MMUs, so we don't need them.  */
 #define flush_cache_all()			((void)0)
 #define flush_cache_mm(mm)			((void)0)
 #define flush_cache_range(vma, start, end)	((void)0)
 #define flush_cache_page(vma, vmaddr)		((void)0)
 #define flush_dcache_page(page)			((void)0)
+
+#ifdef CONFIG_NO_CACHE
+
+/* Some systems have no cache at all, in which case we don't need these
+   either.  */
 #define flush_icache()				((void)0)
 #define flush_icache_range(start, end)		((void)0)
 #define flush_icache_page(vma,pg)		((void)0)
 #define flush_icache_user_range(vma,pg,adr,len)	((void)0)
 #define flush_cache_sigtramp(vaddr)		((void)0)
 
-#endif /* !flush_cache_all */
+#else /* !CONFIG_NO_CACHE */
+
+struct page;
+struct mm_struct;
+struct vm_area_struct;
+
+/* Otherwise, somebody had better define them.  */
+extern void flush_icache (void);
+extern void flush_icache_range (unsigned long start, unsigned long end);
+extern void flush_icache_page (struct vm_area_struct *vma, struct page *page);
+extern void flush_icache_user_range (struct vm_area_struct *vma,
+				     struct page *page,
+				     unsigned long adr, int len);
+extern void flush_cache_sigtramp (unsigned long addr);
+
+#endif /* CONFIG_NO_CACHE */
+
 
 #endif /* __V850_CACHEFLUSH_H__ */
diff -Nru a/include/asm-v850/entry.h b/include/asm-v850/entry.h
--- a/include/asm-v850/entry.h	Sat Jul 19 12:54:30 2003
+++ b/include/asm-v850/entry.h	Sat Jul 19 12:54:30 2003
@@ -65,10 +65,10 @@
 #define RESET_GUARD_ACTIVE	0xFAB4BEEF
 #endif /* CONFIG_RESET_GUARD */
 
-#ifdef CONFIG_V850E_MA1_HIGHRES_TIMER
+#ifdef CONFIG_V850E_HIGHRES_TIMER
 #define HIGHRES_TIMER_SLOW_TICKS_ADDR (KERNEL_VAR_SPACE_ADDR + 32)
 #define HIGHRES_TIMER_SLOW_TICKS     KERNEL_VAR (HIGHRES_TIMER_SLOW_TICKS_ADDR)
-#endif /* CONFIG_V850E_MA1_HIGHRES_TIMER */
+#endif /* CONFIG_V850E_HIGHRES_TIMER */
 
 #ifndef __ASSEMBLY__
 
diff -Nru a/include/asm-v850/fpga85e2c.h b/include/asm-v850/fpga85e2c.h
--- a/include/asm-v850/fpga85e2c.h	Sat Jul 19 12:54:25 2003
+++ b/include/asm-v850/fpga85e2c.h	Sat Jul 19 12:54:25 2003
@@ -2,8 +2,8 @@
  * include/asm-v850/fpga85e2c.h -- Machine-dependent defs for
  *	FPGA implementation of V850E2/NA85E2C
  *
- *  Copyright (C) 2002  NEC Corporation
- *  Copyright (C) 2002  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2002,03  NEC Electronics Corporation
+ *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -15,11 +15,10 @@
 #ifndef __V850_FPGA85E2C_H__
 #define __V850_FPGA85E2C_H__
 
-
+#include <asm/v850e2.h>
 #include <asm/clinkage.h>
 
 
-#define CPU_ARCH 	"v850e2"
 #define CPU_MODEL	"v850e2/fpga85e2c"
 #define CPU_MODEL_LONG	"NEC V850E2/NA85E2C"
 #define PLATFORM	"fpga85e2c"
@@ -42,27 +41,6 @@
 #define CSDEV_ADDR(n)		(0xFFE80110 + 2*(n))
 #define CSDEV(n)		(*(volatile unsigned char *)CSDEV_ADDR (n))
 
-/* The BSC register controls bus-sizing.  Each memory area CSn uses a pair
-   of bits N*2 and N*2+1, where 00 means an 8-bit bus size, 01 16-bit, and
-   10 32-bit.  */
-#define BSC_ADDR		0xFFFFF066
-#define BSC			(*(volatile unsigned short *)BSC_ADDR)
-
-#define DWC_ADDR(n)		(0xFFFFF484 + 2*(n))
-#define DWC(n)			(*(volatile unsigned short *)DWC_ADDR (n))
-
-#define ASC_ADDR		0xFFFFF48A
-#define ASC			(*(volatile unsigned short *)ASC_ADDR)
-
-#define BTSC_ADDR		0xFFFFF070
-#define BTSC			(*(volatile unsigned short *)BTSC_ADDR)
-
-#define BHC_ADDR		0xFFFFF06A
-#define BHC			(*(volatile unsigned short *)BHC_ADDR)
-
-
-/* NB85E-style interrupt system.  */
-#include <asm/nb85e_intc.h>
 
 /* Timer interrupts 0-3, interrupt at intervals from CLK/4096 to CLK/16384.  */
 #define IRQ_RPU(n)		(60 + (n))
diff -Nru a/include/asm-v850/highres_timer.h b/include/asm-v850/highres_timer.h
--- a/include/asm-v850/highres_timer.h	Sat Jul 19 12:54:29 2003
+++ b/include/asm-v850/highres_timer.h	Sat Jul 19 12:54:29 2003
@@ -1,8 +1,8 @@
 /*
  * include/asm-v850/highres_timer.h -- High resolution timing routines
  *
- *  Copyright (C) 2001  NEC Corporation
- *  Copyright (C) 2001  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -25,7 +25,7 @@
    counter overflows).  */
 #define HIGHRES_TIMER_SLOW_TICK_RATE	25
 
-/* Which timer in the nb85e `Timer D' we use.  */
+/* Which timer in the V850E `Timer D' we use.  */
 #define HIGHRES_TIMER_TIMER_D_UNIT	3
 
 
diff -Nru a/include/asm-v850/ma.h b/include/asm-v850/ma.h
--- a/include/asm-v850/ma.h	Sat Jul 19 12:54:22 2003
+++ b/include/asm-v850/ma.h	Sat Jul 19 12:54:22 2003
@@ -1,8 +1,8 @@
 /*
  * include/asm-v850/ma.h -- V850E/MA series of cpu chips
  *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -14,9 +14,8 @@
 #ifndef __V850_MA_H__
 #define __V850_MA_H__
 
-
-/* The MA series uses the NB85E cpu core.  */
-#include <asm/nb85e.h>
+/* The MA series uses the V850E cpu core.  */
+#include <asm/v850e.h>
 
 
 /* For <asm/entry.h> */
@@ -28,10 +27,10 @@
 
 
 /* MA series UART details.  */
-#define NB85E_UART_BASE_FREQ		CPU_CLOCK_FREQ
+#define V850E_UART_BASE_FREQ		CPU_CLOCK_FREQ
 
 /* This is a function that gets called before configuring the UART.  */
-#define NB85E_UART_PRE_CONFIGURE	ma_uart_pre_configure
+#define V850E_UART_PRE_CONFIGURE	ma_uart_pre_configure
 #ifndef __ASSEMBLY__
 extern void ma_uart_pre_configure (unsigned chan,
 				   unsigned cflags, unsigned baud);
@@ -39,16 +38,16 @@
 
 
 /* MA series timer C details.  */
-#define NB85E_TIMER_C_BASE_ADDR		0xFFFFF600
+#define V850E_TIMER_C_BASE_ADDR		0xFFFFF600
 
 
 /* MA series timer D details.  */
-#define NB85E_TIMER_D_BASE_ADDR		0xFFFFF540
-#define NB85E_TIMER_D_TMD_BASE_ADDR 	(NB85E_TIMER_D_BASE_ADDR + 0x0)
-#define NB85E_TIMER_D_CMD_BASE_ADDR 	(NB85E_TIMER_D_BASE_ADDR + 0x2)
-#define NB85E_TIMER_D_TMCD_BASE_ADDR 	(NB85E_TIMER_D_BASE_ADDR + 0x4)
+#define V850E_TIMER_D_BASE_ADDR		0xFFFFF540
+#define V850E_TIMER_D_TMD_BASE_ADDR 	(V850E_TIMER_D_BASE_ADDR + 0x0)
+#define V850E_TIMER_D_CMD_BASE_ADDR 	(V850E_TIMER_D_BASE_ADDR + 0x2)
+#define V850E_TIMER_D_TMCD_BASE_ADDR 	(V850E_TIMER_D_BASE_ADDR + 0x4)
 
-#define NB85E_TIMER_D_BASE_FREQ		CPU_CLOCK_FREQ
+#define V850E_TIMER_D_BASE_FREQ		CPU_CLOCK_FREQ
 
 
 /* Port 0 */
diff -Nru a/include/asm-v850/ma1.h b/include/asm-v850/ma1.h
--- a/include/asm-v850/ma1.h	Sat Jul 19 12:54:25 2003
+++ b/include/asm-v850/ma1.h	Sat Jul 19 12:54:25 2003
@@ -1,8 +1,8 @@
 /*
  * include/asm-v850/ma1.h -- V850E/MA1 cpu chip
  *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -40,12 +40,11 @@
 #define IRQ_INTST(n)	(0x27 + (n)*4) /* UART 0-2 transmission completion */
 #define IRQ_INTST_NUM	3
 
-/* For <asm/irq.h> */
 #define NUM_CPU_IRQS	0x30
 
 
 /* The MA1 has a UART with 3 channels.  */
-#define NB85E_UART_NUM_CHANNELS	3
+#define V850E_UART_NUM_CHANNELS	3
 
 
 #endif /* __V850_MA1_H__ */
diff -Nru a/include/asm-v850/machdep.h b/include/asm-v850/machdep.h
--- a/include/asm-v850/machdep.h	Sat Jul 19 12:54:24 2003
+++ b/include/asm-v850/machdep.h	Sat Jul 19 12:54:24 2003
@@ -1,8 +1,8 @@
 /*
  * include/asm-v850/machdep.h -- Machine-dependent definitions
  *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -20,6 +20,9 @@
 #ifdef CONFIG_V850E_MA1
 #include <asm/ma1.h>
 #endif
+#ifdef CONFIG_V850E_ME2
+#include <asm/me2.h>
+#endif
 #ifdef CONFIG_V850E_TEG
 #include <asm/teg.h>
 #endif
@@ -36,6 +39,9 @@
 #ifdef CONFIG_RTE_CB_MA1
 #include <asm/rte_ma1_cb.h>
 #endif
+#ifdef CONFIG_RTE_CB_ME2
+#include <asm/rte_me2_cb.h>
+#endif
 #ifdef CONFIG_RTE_CB_NB85E
 #include <asm/rte_nb85e_cb.h>
 #endif
@@ -44,6 +50,9 @@
 #endif
 #ifdef CONFIG_V850E2_SIM85E2C
 #include <asm/sim85e2c.h>
+#endif
+#ifdef CONFIG_V850E2_SIM85E2S
+#include <asm/sim85e2s.h>
 #endif
 #ifdef CONFIG_V850E2_FPGA85E2C
 #include <asm/fpga85e2c.h>
diff -Nru a/include/asm-v850/me2.h b/include/asm-v850/me2.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-v850/me2.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,182 @@
+/*
+ * include/asm-v850/me2.h -- V850E/ME2 cpu chip
+ *
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#ifndef __V850_ME2_H__
+#define __V850_ME2_H__
+
+#include <asm/v850e.h>
+#include <asm/v850e_cache.h>
+
+
+#define CPU_MODEL	"v850e/me2"
+#define CPU_MODEL_LONG	"NEC V850E/ME2"
+
+
+/* Hardware-specific interrupt numbers (in the kernel IRQ namespace).  */
+#define IRQ_INTP(n)       (n) /* Pnnn (pin) interrupts */
+#define IRQ_INTP_NUM      31
+#define IRQ_INTCMD(n)     (0x31 + (n)) /* interval timer interrupts 0-3 */
+#define IRQ_INTCMD_NUM    4
+#define IRQ_INTDMA(n)     (0x41 + (n)) /* DMA interrupts 0-3 */
+#define IRQ_INTDMA_NUM    4
+#define IRQ_INTUBTIRE(n)  (0x49 + (n)*5)/* UARTB 0-1 reception error */
+#define IRQ_INTUBTIRE_NUM 2
+#define IRQ_INTUBTIR(n)   (0x4a + (n)*5) /* UARTB 0-1 reception complete */
+#define IRQ_INTUBTIR_NUM  2
+#define IRQ_INTUBTIT(n)   (0x4b + (n)*5) /* UARTB 0-1 transmission complete */
+#define IRQ_INTUBTIT_NUM  2
+#define IRQ_INTUBTIF(n)   (0x4c + (n)*5) /* UARTB 0-1 FIFO trans. complete */
+#define IRQ_INTUBTIF_NUM  2
+#define IRQ_INTUBTITO(n)  (0x4d + (n)*5) /* UARTB 0-1 reception timeout */
+#define IRQ_INTUBTITO_NUM 2
+
+/* For <asm/irq.h> */
+#define NUM_CPU_IRQS		0x59 /* V850E/ME2 */
+
+
+/* For <asm/entry.h> */
+/* We use on-chip RAM, for a few miscellaneous variables that must be
+   accessible using a load instruction relative to R0.  */
+#define R0_RAM_ADDR			0xFFFFB000 /* V850E/ME2 */
+
+
+/* V850E/ME2 UARTB details.*/
+#define V850E_UART_NUM_CHANNELS		2
+#define V850E_UARTB_BASE_FREQ		(CPU_CLOCK_FREQ / 4)
+
+/* This is a function that gets called before configuring the UART.  */
+#define V850E_UART_PRE_CONFIGURE	me2_uart_pre_configure
+#ifndef __ASSEMBLY__
+extern void me2_uart_pre_configure (unsigned chan,
+				    unsigned cflags, unsigned baud);
+#endif /* __ASSEMBLY__ */
+
+
+/* V850E/ME2 timer C details.  */
+#define V850E_TIMER_C_BASE_ADDR		0xFFFFF600
+
+
+/* V850E/ME2 timer D details.  */
+#define V850E_TIMER_D_BASE_ADDR		0xFFFFF540
+#define V850E_TIMER_D_TMD_BASE_ADDR	(V850E_TIMER_D_BASE_ADDR + 0x0)
+#define V850E_TIMER_D_CMD_BASE_ADDR 	(V850E_TIMER_D_BASE_ADDR + 0x2)
+#define V850E_TIMER_D_TMCD_BASE_ADDR	(V850E_TIMER_D_BASE_ADDR + 0x4)
+
+#define V850E_TIMER_D_BASE_FREQ		(CPU_CLOCK_FREQ / 2)
+
+
+/* Select iRAM mode.  */
+#define ME2_IRAMM_ADDR			0xFFFFF80A
+#define ME2_IRAMM			(*(volatile u8*)ME2_IRAMM_ADDR)
+
+
+/* Interrupt edge-detection configuration.  INTF(n) and INTR(n) are only
+   valid for n == 1, 2, or 5.  */
+#define ME2_INTF_ADDR(n)		(0xFFFFFC00 + (n) * 0x2)
+#define ME2_INTF(n)			(*(volatile u8*)ME2_INTF_ADDR(n))
+#define ME2_INTR_ADDR(n)		(0xFFFFFC20 + (n) * 0x2)
+#define ME2_INTR(n)			(*(volatile u8*)ME2_INTR_ADDR(n))
+#define ME2_INTFAL_ADDR			0xFFFFFC10
+#define ME2_INTFAL			(*(volatile u8*)ME2_INTFAL_ADDR)
+#define ME2_INTRAL_ADDR			0xFFFFFC30
+#define ME2_INTRAL			(*(volatile u8*)ME2_INTRAL_ADDR)
+#define ME2_INTFDH_ADDR			0xFFFFFC16
+#define ME2_INTFDH			(*(volatile u16*)ME2_INTFDH_ADDR)
+#define ME2_INTRDH_ADDR			0xFFFFFC36
+#define ME2_INTRDH			(*(volatile u16*)ME2_INTRDH_ADDR)
+#define ME2_SESC_ADDR(n)		(0xFFFFF609 + (n) * 0x10)
+#define ME2_SESC(n)			(*(volatile u8*)ME2_SESC_ADDR(n))
+#define ME2_SESA10_ADDR			0xFFFFF5AD
+#define ME2_SESA10			(*(volatile u8*)ME2_SESA10_ADDR)
+#define ME2_SESA11_ADDR			0xFFFFF5DD
+#define ME2_SESA11			(*(volatile u8*)ME2_SESA11_ADDR)
+
+
+/* Port 1 */
+/* Direct I/O.  Bits 0-3 are pins P10-P13.  */
+#define ME2_PORT1_IO_ADDR		0xFFFFF402
+#define ME2_PORT1_IO			(*(volatile u8 *)ME2_PORT1_IO_ADDR)
+/* Port mode (for direct I/O, 0 = output, 1 = input).  */
+#define ME2_PORT1_PM_ADDR		0xFFFFF422
+#define ME2_PORT1_PM			(*(volatile u8 *)ME2_PORT1_PM_ADDR)
+/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode).  */
+#define ME2_PORT1_PMC_ADDR		0xFFFFF442
+#define ME2_PORT1_PMC			(*(volatile u8 *)ME2_PORT1_PMC_ADDR)
+/* Port function control (for serial interfaces, 0 = CSI30, 1 = UARTB0 ).  */
+#define ME2_PORT1_PFC_ADDR		0xFFFFF462
+#define ME2_PORT1_PFC			(*(volatile u8 *)ME2_PORT1_PFC_ADDR)
+
+/* Port 2 */
+/* Direct I/O.  Bits 0-3 are pins P20-P25.  */
+#define ME2_PORT2_IO_ADDR		0xFFFFF404
+#define ME2_PORT2_IO			(*(volatile u8 *)ME2_PORT2_IO_ADDR)
+/* Port mode (for direct I/O, 0 = output, 1 = input).  */
+#define ME2_PORT2_PM_ADDR		0xFFFFF424
+#define ME2_PORT2_PM			(*(volatile u8 *)ME2_PORT2_PM_ADDR)
+/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode).  */
+#define ME2_PORT2_PMC_ADDR		0xFFFFF444
+#define ME2_PORT2_PMC			(*(volatile u8 *)ME2_PORT2_PMC_ADDR)
+/* Port function control (for serial interfaces, 0 = INTP2x, 1 = UARTB1 ).  */
+#define ME2_PORT2_PFC_ADDR		0xFFFFF464
+#define ME2_PORT2_PFC			(*(volatile u8 *)ME2_PORT2_PFC_ADDR)
+
+/* Port 5 */
+/* Direct I/O.  Bits 0-5 are pins P50-P55.  */
+#define ME2_PORT5_IO_ADDR		0xFFFFF40A
+#define ME2_PORT5_IO			(*(volatile u8 *)ME2_PORT5_IO_ADDR)
+/* Port mode (for direct I/O, 0 = output, 1 = input).  */
+#define ME2_PORT5_PM_ADDR		0xFFFFF42A
+#define ME2_PORT5_PM			(*(volatile u8 *)ME2_PORT5_PM_ADDR)
+/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode).  */
+#define ME2_PORT5_PMC_ADDR		0xFFFFF44A
+#define ME2_PORT5_PMC			(*(volatile u8 *)ME2_PORT5_PMC_ADDR)
+/* Port function control ().  */
+#define ME2_PORT5_PFC_ADDR		0xFFFFF46A
+#define ME2_PORT5_PFC			(*(volatile u8 *)ME2_PORT5_PFC_ADDR)
+
+/* Port 6 */
+/* Direct I/O.  Bits 5-7 are pins P65-P67.  */
+#define ME2_PORT6_IO_ADDR		0xFFFFF40C
+#define ME2_PORT6_IO			(*(volatile u8 *)ME2_PORT6_IO_ADDR)
+/* Port mode (for direct I/O, 0 = output, 1 = input).  */
+#define ME2_PORT6_PM_ADDR		0xFFFFF42C
+#define ME2_PORT6_PM			(*(volatile u8 *)ME2_PORT6_PM_ADDR)
+/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode).  */
+#define ME2_PORT6_PMC_ADDR		0xFFFFF44C
+#define ME2_PORT6_PMC			(*(volatile u8 *)ME2_PORT6_PMC_ADDR)
+/* Port function control ().  */
+#define ME2_PORT6_PFC_ADDR		0xFFFFF46C
+#define ME2_PORT6_PFC			(*(volatile u8 *)ME2_PORT6_PFC_ADDR)
+
+/* Port 7 */
+/* Direct I/O.  Bits 2-7 are pins P72-P77.  */
+#define ME2_PORT7_IO_ADDR		0xFFFFF40E
+#define ME2_PORT7_IO			(*(volatile u8 *)ME2_PORT7_IO_ADDR)
+/* Port mode (for direct I/O, 0 = output, 1 = input).  */
+#define ME2_PORT7_PM_ADDR		0xFFFFF42E
+#define ME2_PORT7_PM			(*(volatile u8 *)ME2_PORT7_PM_ADDR)
+/* Port mode control (0 = direct I/O mode, 1 = alternative I/O mode).  */
+#define ME2_PORT7_PMC_ADDR		0xFFFFF44E
+#define ME2_PORT7_PMC			(*(volatile u8 *)ME2_PORT7_PMC_ADDR)
+/* Port function control ().  */
+#define ME2_PORT7_PFC_ADDR		0xFFFFF46E
+#define ME2_PORT7_PFC			(*(volatile u8 *)ME2_PORT7_PFC_ADDR)
+
+
+#ifndef __ASSEMBLY__
+/* Initialize V850E/ME2 chip interrupts.  */
+extern void me2_init_irqs (void);
+#endif /* !__ASSEMBLY__ */
+
+
+#endif /* __V850_ME2_H__ */
diff -Nru a/include/asm-v850/nb85e.h b/include/asm-v850/nb85e.h
--- a/include/asm-v850/nb85e.h	Sat Jul 19 12:54:25 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,21 +0,0 @@
-/*
- * include/asm-v850/nb85e.h -- NB85E cpu core
- *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_NB85E_H__
-#define __V850_NB85E_H__
-
-#include <asm/nb85e_intc.h>
-
-#define CPU_ARCH "v850e"
-
-#endif /* __V850_NB85E_H__ */
diff -Nru a/include/asm-v850/nb85e_cache.h b/include/asm-v850/nb85e_cache.h
--- a/include/asm-v850/nb85e_cache.h	Sat Jul 19 12:54:25 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,78 +0,0 @@
-/*
- * include/asm-v850/nb85e_cache_cache.h -- Cache control for NB85E_CACHE212 and
- * 	NB85E_CACHE213 cache memories
- *
- *  Copyright (C) 2001,03  NEC Electronics Corporation
- *  Copyright (C) 2001,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_NB85E_CACHE_H__
-#define __V850_NB85E_CACHE_H__
-
-#include <asm/types.h>
-
-
-/* Cache control registers.  */
-#define NB85E_CACHE_BHC_ADDR	0xFFFFF06A
-#define NB85E_CACHE_BHC		(*(volatile u16 *)NB85E_CACHE_BHC_ADDR)
-#define NB85E_CACHE_ICC_ADDR	0xFFFFF070
-#define NB85E_CACHE_ICC		(*(volatile u16 *)NB85E_CACHE_ICC_ADDR)
-#define NB85E_CACHE_ISI_ADDR	0xFFFFF072
-#define NB85E_CACHE_ISI		(*(volatile u16 *)NB85E_CACHE_ISI_ADDR)
-#define NB85E_CACHE_DCC_ADDR	0xFFFFF078
-#define NB85E_CACHE_DCC		(*(volatile u16 *)NB85E_CACHE_DCC_ADDR)
-
-/* Size of a cache line in bytes.  */
-#define NB85E_CACHE_LINE_SIZE	16
-
-/* For <asm/cache.h> */
-#define L1_CACHE_BYTES				NB85E_CACHE_LINE_SIZE
-
-
-#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
-
-/* Set caching params via the BHC and DCC registers.  */
-void nb85e_cache_enable (u16 bhc, u16 dcc);
-
-struct page;
-struct mm_struct;
-struct vm_area_struct;
-
-extern void nb85e_cache_flush_all (void);
-extern void nb85e_cache_flush_mm (struct mm_struct *mm);
-extern void nb85e_cache_flush_range (struct mm_struct *mm,
-				     unsigned long start,
-				     unsigned long end);
-extern void nb85e_cache_flush_page (struct vm_area_struct *vma,
-				    unsigned long page_addr);
-extern void nb85e_cache_flush_dcache_page (struct page *page);
-extern void nb85e_cache_flush_icache (void);
-extern void nb85e_cache_flush_icache_range (unsigned long start,
-					    unsigned long end);
-extern void nb85e_cache_flush_icache_page (struct vm_area_struct *vma,
-					   struct page *page);
-extern void nb85e_cache_flush_icache_user_range (struct vm_area_struct *vma,
-						 struct page *page,
-						 unsigned long adr, int len);
-extern void nb85e_cache_flush_sigtramp (unsigned long addr);
-
-#define flush_cache_all		nb85e_cache_flush_all
-#define flush_cache_mm		nb85e_cache_flush_mm
-#define flush_cache_range	nb85e_cache_flush_range
-#define flush_cache_page	nb85e_cache_flush_page
-#define flush_dcache_page	nb85e_cache_flush_dcache_page
-#define flush_icache		nb85e_cache_flush_icache
-#define flush_icache_range	nb85e_cache_flush_icache_range
-#define flush_icache_page	nb85e_cache_flush_icache_page
-#define flush_icache_user_range	nb85e_cache_flush_icache_user_range
-#define flush_cache_sigtramp	nb85e_cache_flush_sigtramp
-
-#endif /* __KERNEL__ && !__ASSEMBLY__ */
-
-#endif /* __V850_NB85E_CACHE_H__ */
diff -Nru a/include/asm-v850/nb85e_intc.h b/include/asm-v850/nb85e_intc.h
--- a/include/asm-v850/nb85e_intc.h	Sat Jul 19 12:54:26 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,133 +0,0 @@
-/*
- * include/asm-v850/nb85e_intc.h -- NB85E cpu core interrupt controller (INTC)
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_NB85E_INTC_H__
-#define __V850_NB85E_INTC_H__
-
-
-/* There are 4 16-bit `Interrupt Mask Registers' located contiguously
-   starting from this base.  Each interrupt uses a single bit to
-   indicated enabled/disabled status.  */
-#define NB85E_INTC_IMR_BASE_ADDR  0xFFFFF100
-#define NB85E_INTC_IMR_ADDR(irq)  (NB85E_INTC_IMR_BASE_ADDR + ((irq) >> 3))
-#define NB85E_INTC_IMR_BIT(irq)	  ((irq) & 0x7)
-
-/* Each maskable interrupt has a single-byte control register at this
-   address.  */
-#define NB85E_INTC_IC_BASE_ADDR	  0xFFFFF110
-#define NB85E_INTC_IC_ADDR(irq)	  (NB85E_INTC_IC_BASE_ADDR + ((irq) << 1))
-#define NB85E_INTC_IC(irq)	  (*(volatile u8 *)NB85E_INTC_IC_ADDR(irq))
-/* Encode priority PR for storing in an interrupt control register.  */
-#define NB85E_INTC_IC_PR(pr)	  (pr)
-/* Interrupt disable bit in an interrupt control register.  */
-#define NB85E_INTC_IC_MK_BIT	  6
-#define NB85E_INTC_IC_MK	  (1 << NB85E_INTC_IC_MK_BIT)
-/* Interrupt pending flag in an interrupt control register.  */
-#define NB85E_INTC_IC_IF_BIT	  7
-#define NB85E_INTC_IC_IF	  (1 << NB85E_INTC_IC_IF_BIT)
-
-/* The ISPR (In-service priority register) contains one bit for each interrupt
-   priority level, which is set to one when that level is currently being
-   serviced (and thus blocking any interrupts of equal or lesser level).  */
-#define NB85E_INTC_ISPR_ADDR	  0xFFFFF1FA
-#define NB85E_INTC_ISPR		  (*(volatile u8 *)NB85E_INTC_ISPR_ADDR)
-
-
-#ifndef __ASSEMBLY__
-
-/* Enable interrupt handling for interrupt IRQ.  */
-static inline void nb85e_intc_enable_irq (unsigned irq)
-{
-	__asm__ __volatile__ ("clr1 %0, [%1]"
-			      :: "r" (NB85E_INTC_IMR_BIT (irq)),
-			         "r" (NB85E_INTC_IMR_ADDR (irq))
-			      : "memory");
-}
-
-/* Disable interrupt handling for interrupt IRQ.  Note that any
-   interrupts received while disabled will be delivered once the
-   interrupt is enabled again, unless they are explicitly cleared using
-   `nb85e_intc_clear_pending_irq'.  */
-static inline void nb85e_intc_disable_irq (unsigned irq)
-{
-	__asm__ __volatile__ ("set1 %0, [%1]"
-			      :: "r" (NB85E_INTC_IMR_BIT (irq)),
-			         "r" (NB85E_INTC_IMR_ADDR (irq))
-			      : "memory");
-}
-
-/* Return true if interrupt handling for interrupt IRQ is enabled.  */
-static inline int nb85e_intc_irq_enabled (unsigned irq)
-{
-	int rval;
-	__asm__ __volatile__ ("tst1 %1, [%2]; setf z, %0"
-			      : "=r" (rval)
-			      : "r" (NB85E_INTC_IMR_BIT (irq)),
-			        "r" (NB85E_INTC_IMR_ADDR (irq)));
-	return rval;
-}
-
-/* Disable irqs from 0 until LIMIT.  LIMIT must be a multiple of 8.  */
-static inline void _nb85e_intc_disable_irqs (unsigned limit)
-{
-	unsigned long addr;
-	for (addr = NB85E_INTC_IMR_BASE_ADDR; limit >= 8; addr++, limit -= 8)
-		*(char *)addr = 0xFF;
-}
-
-/* Disable all irqs.  This is purposely a macro, because NUM_MACH_IRQS
-   will be only be defined later.  */
-#define nb85e_intc_disable_irqs()   _nb85e_intc_disable_irqs (NUM_MACH_IRQS)
-
-/* Clear any pending interrupts for IRQ.  */
-static inline void nb85e_intc_clear_pending_irq (unsigned irq)
-{
-	__asm__ __volatile__ ("clr1 %0, 0[%1]"
-			      :: "i" (NB85E_INTC_IC_IF_BIT),
-			         "r" (NB85E_INTC_IC_ADDR (irq))
-			      : "memory");
-}
-
-/* Return true if interrupt IRQ is pending (but disabled).  */
-static inline int nb85e_intc_irq_pending (unsigned irq)
-{
-	int rval;
-	__asm__ __volatile__ ("tst1 %1, 0[%2]; setf nz, %0"
-			      : "=r" (rval)
-			      : "i" (NB85E_INTC_IC_IF_BIT),
-			        "r" (NB85E_INTC_IC_ADDR (irq)));
-	return rval;
-}
-
-
-struct nb85e_intc_irq_init {
-	const char *name;	/* name of interrupt type */
-
-	/* Range of kernel irq numbers for this type:
-	   BASE, BASE+INTERVAL, ..., BASE+INTERVAL*NUM  */
-	unsigned base, num, interval;
-
-	unsigned priority;	/* interrupt priority to assign */
-};
-struct hw_interrupt_type;	/* fwd decl */
-
-/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
-   INITS (which is terminated by an entry with the name field == 0).  */
-extern void nb85e_intc_init_irq_types (struct nb85e_intc_irq_init *inits,
-				       struct hw_interrupt_type *hw_irq_types);
-
-
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_NB85E_INTC_H__ */
diff -Nru a/include/asm-v850/nb85e_timer_c.h b/include/asm-v850/nb85e_timer_c.h
--- a/include/asm-v850/nb85e_timer_c.h	Sat Jul 19 12:54:23 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,48 +0,0 @@
-/*
- * include/asm-v850/nb85e_timer_c.h -- `Timer C' component often used
- *	with the NB85E cpu core
- *
- *  Copyright (C) 2001  NEC Corporation
- *  Copyright (C) 2001  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-/* NOTE: this include file currently contains only enough to allow us to
-   use timer C as an interrupt pass-through.  */
-
-#ifndef __V850_NB85E_TIMER_C_H__
-#define __V850_NB85E_TIMER_C_H__
-
-#include <asm/types.h>
-#include <asm/machdep.h>	/* Pick up chip-specific defs.  */
-
-
-/* Timer C (16-bit interval timers).  */
-
-/* Control register 0 for timer C.  */
-#define NB85E_TIMER_C_TMCC0_ADDR(n) (NB85E_TIMER_C_BASE_ADDR + 0x6 + 0x10 *(n))
-#define NB85E_TIMER_C_TMCC0(n)	  (*(volatile u8 *)NB85E_TIMER_C_TMCC0_ADDR(n))
-#define NB85E_TIMER_C_TMCC0_CAE	  0x01 /* clock action enable */
-#define NB85E_TIMER_C_TMCC0_CE	  0x02 /* count enable */
-/* ... */
-
-/* Control register 1 for timer C.  */
-#define NB85E_TIMER_C_TMCC1_ADDR(n) (NB85E_TIMER_C_BASE_ADDR + 0x8 + 0x10 *(n))
-#define NB85E_TIMER_C_TMCC1(n)	  (*(volatile u8 *)NB85E_TIMER_C_TMCC1_ADDR(n))
-#define NB85E_TIMER_C_TMCC1_CMS0  0x01 /* capture/compare mode select (ccc0) */
-#define NB85E_TIMER_C_TMCC1_CMS1  0x02 /* capture/compare mode select (ccc1) */
-/* ... */
-
-/* Interrupt edge-sensitivity control for timer C.  */
-#define NB85E_TIMER_C_SESC_ADDR(n) (NB85E_TIMER_C_BASE_ADDR + 0x9 + 0x10 *(n))
-#define NB85E_TIMER_C_SESC(n)	  (*(volatile u8 *)NB85E_TIMER_C_SESC_ADDR(n))
-
-/* ...etc... */
-
-
-#endif /* __V850_NB85E_TIMER_C_H__  */
diff -Nru a/include/asm-v850/nb85e_timer_d.h b/include/asm-v850/nb85e_timer_d.h
--- a/include/asm-v850/nb85e_timer_d.h	Sat Jul 19 12:54:24 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,62 +0,0 @@
-/*
- * include/asm-v850/nb85e_timer_d.h -- `Timer D' component often used
- *	with the NB85E cpu core
- *
- *  Copyright (C) 2001,02,03  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_NB85E_TIMER_D_H__
-#define __V850_NB85E_TIMER_D_H__
-
-#include <asm/types.h>
-#include <asm/machdep.h>	/* Pick up chip-specific defs.  */
-
-
-/* Timer D (16-bit interval timers).  */
-
-/* Count registers for timer D.  */
-#define NB85E_TIMER_D_TMD_ADDR(n) (NB85E_TIMER_D_TMD_BASE_ADDR + 0x10 * (n))
-#define NB85E_TIMER_D_TMD(n)	  (*(volatile u16 *)NB85E_TIMER_D_TMD_ADDR(n))
-
-/* Count compare registers for timer D.  */
-#define NB85E_TIMER_D_CMD_ADDR(n) (NB85E_TIMER_D_CMD_BASE_ADDR + 0x10 * (n))
-#define NB85E_TIMER_D_CMD(n)	  (*(volatile u16 *)NB85E_TIMER_D_CMD_ADDR(n))
-
-/* Control registers for timer D.  */
-#define NB85E_TIMER_D_TMCD_ADDR(n) (NB85E_TIMER_D_TMCD_BASE_ADDR + 0x10 * (n))
-#define NB85E_TIMER_D_TMCD(n)	   (*(volatile u8 *)NB85E_TIMER_D_TMCD_ADDR(n))
-/* Control bits for timer D.  */
-#define NB85E_TIMER_D_TMCD_CE  	   0x2 /* count enable */
-#define NB85E_TIMER_D_TMCD_CAE	   0x1 /* clock action enable */
-/* Clock divider setting (log2).  */
-#define NB85E_TIMER_D_TMCD_CS(divlog2) (((divlog2) - NB85E_TIMER_D_TMCD_CS_MIN) << 4)
-/* Minimum clock divider setting (log2).  */
-#ifndef NB85E_TIMER_D_TMCD_CS_MIN /* Can be overridden by mach-specific hdrs */
-#define NB85E_TIMER_D_TMCD_CS_MIN  2 /* Default is correct for the v850e/ma1 */
-#endif
-/* Maximum clock divider setting (log2).  */
-#define NB85E_TIMER_D_TMCD_CS_MAX  (NB85E_TIMER_D_TMCD_CS_MIN + 7)
-
-/* Return the clock-divider (log2) of timer D unit N.  */
-#define NB85E_TIMER_D_DIVLOG2(n) \
-  (((NB85E_TIMER_D_TMCD(n) >> 4) & 0x7) + NB85E_TIMER_D_TMCD_CS_MIN)
-
-
-#ifndef __ASSEMBLY__
-
-/* Start interval timer TIMER (0-3).  The timer will issue the
-   corresponding INTCMD interrupt RATE times per second.  This function
-   does not enable the interrupt.  */
-extern void nb85e_timer_d_configure (unsigned timer, unsigned rate);
-
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_NB85E_TIMER_D_H__  */
diff -Nru a/include/asm-v850/nb85e_uart.h b/include/asm-v850/nb85e_uart.h
--- a/include/asm-v850/nb85e_uart.h	Sat Jul 19 12:54:30 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,144 +0,0 @@
-/*
- * include/asm-v850/nb85e_uart.h -- On-chip UART often used with the
- *	NB85E cpu core
- *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-/* There's not actually a single UART implementation used by nb85e
-   derivatives, but rather a series of implementations that are all
-   `close' to one another.  This file attempts to capture some
-   commonality between them.  */
-
-#ifndef __V850_NB85E_UART_H__
-#define __V850_NB85E_UART_H__
-
-#include <asm/types.h>
-#include <asm/machdep.h>	/* Pick up chip-specific defs.  */
-
-
-/* The base address of the UART control registers for channel N.
-   The default is the address used on the V850E/MA1.  */
-#ifndef NB85E_UART_BASE_ADDR
-#define NB85E_UART_BASE_ADDR(n)		(0xFFFFFA00 + 0x10 * (n))
-#endif 
-
-/* Addresses of specific UART control registers for channel N.
-   The defaults are the addresses used on the V850E/MA1; if a platform
-   wants to redefine any of these, it must redefine them all.  */
-#ifndef NB85E_UART_ASIM_ADDR
-#define NB85E_UART_ASIM_ADDR(n)		(NB85E_UART_BASE_ADDR(n) + 0x0)
-#define NB85E_UART_RXB_ADDR(n)		(NB85E_UART_BASE_ADDR(n) + 0x2)
-#define NB85E_UART_ASIS_ADDR(n)		(NB85E_UART_BASE_ADDR(n) + 0x3)
-#define NB85E_UART_TXB_ADDR(n)		(NB85E_UART_BASE_ADDR(n) + 0x4)
-#define NB85E_UART_ASIF_ADDR(n)		(NB85E_UART_BASE_ADDR(n) + 0x5)
-#define NB85E_UART_CKSR_ADDR(n)		(NB85E_UART_BASE_ADDR(n) + 0x6)
-#define NB85E_UART_BRGC_ADDR(n)		(NB85E_UART_BASE_ADDR(n) + 0x7)
-#endif
-
-#ifndef NB85E_UART_CKSR_MAX_FREQ
-#define NB85E_UART_CKSR_MAX_FREQ (25*1000*1000)
-#endif
-
-/* UART config registers.  */
-#define NB85E_UART_ASIM(n)	(*(volatile u8 *)NB85E_UART_ASIM_ADDR(n))
-/* Control bits for config registers.  */
-#define NB85E_UART_ASIM_CAE	0x80 /* clock enable */
-#define NB85E_UART_ASIM_TXE	0x40 /* transmit enable */
-#define NB85E_UART_ASIM_RXE	0x20 /* receive enable */
-#define NB85E_UART_ASIM_PS_MASK	0x18 /* mask covering parity-select bits */
-#define NB85E_UART_ASIM_PS_NONE	0x00 /* no parity */
-#define NB85E_UART_ASIM_PS_ZERO	0x08 /* zero parity */
-#define NB85E_UART_ASIM_PS_ODD	0x10 /* odd parity */
-#define NB85E_UART_ASIM_PS_EVEN	0x18 /* even parity */
-#define NB85E_UART_ASIM_CL_8	0x04 /* char len is 8 bits (otherwise, 7) */
-#define NB85E_UART_ASIM_SL_2	0x02 /* 2 stop bits (otherwise, 1) */
-#define NB85E_UART_ASIM_ISRM	0x01 /* generate INTSR interrupt on errors
-					(otherwise, generate INTSER) */
-
-/* UART serial interface status registers.  */
-#define NB85E_UART_ASIS(n)	(*(volatile u8 *)NB85E_UART_ASIS_ADDR(n))
-/* Control bits for status registers.  */
-#define NB85E_UART_ASIS_PE	0x04 /* parity error */
-#define NB85E_UART_ASIS_FE	0x02 /* framing error */
-#define NB85E_UART_ASIS_OVE	0x01 /* overrun error */
-
-/* UART serial interface transmission status registers.  */
-#define NB85E_UART_ASIF(n)	(*(volatile u8 *)NB85E_UART_ASIF_ADDR(n))
-#define NB85E_UART_ASIF_TXBF	0x02 /* transmit buffer flag (data in TXB) */
-#define NB85E_UART_ASIF_TXSF	0x01 /* transmit shift flag (sending data) */
-
-/* UART receive buffer register.  */
-#define NB85E_UART_RXB(n)	(*(volatile u8 *)NB85E_UART_RXB_ADDR(n))
-
-/* UART transmit buffer register.  */
-#define NB85E_UART_TXB(n)	(*(volatile u8 *)NB85E_UART_TXB_ADDR(n))
-
-/* UART baud-rate generator control registers.  */
-#define NB85E_UART_CKSR(n)	(*(volatile u8 *)NB85E_UART_CKSR_ADDR(n))
-#define NB85E_UART_CKSR_MAX	11
-#define NB85E_UART_BRGC(n)	(*(volatile u8 *)NB85E_UART_BRGC_ADDR(n))
-
-
-/* This UART doesn't implement RTS/CTS by default, but some platforms
-   implement them externally, so check to see if <asm/machdep.h> defined
-   anything.  */
-#ifdef NB85E_UART_CTS
-#define nb85e_uart_cts(n)	NB85E_UART_CTS(n)
-#else
-#define nb85e_uart_cts(n)	(1)
-#endif
-
-/* Do the same for RTS.  */
-#ifdef NB85E_UART_SET_RTS
-#define nb85e_uart_set_rts(n,v)	NB85E_UART_SET_RTS(n,v)
-#else
-#define nb85e_uart_set_rts(n,v)	((void)0)
-#endif
-
-/* Return true if all characters awaiting transmission on uart channel N
-   have been transmitted.  */
-#define nb85e_uart_xmit_done(n)						      \
-   (! (NB85E_UART_ASIF(n) & NB85E_UART_ASIF_TXBF))
-/* Wait for this to be true.  */
-#define nb85e_uart_wait_for_xmit_done(n)				      \
-   do { } while (! nb85e_uart_xmit_done (n))
-
-/* Return true if uart channel N is ready to transmit a character.  */
-#define nb85e_uart_xmit_ok(n)						      \
-   (nb85e_uart_xmit_done(n) && nb85e_uart_cts(n))
-/* Wait for this to be true.  */
-#define nb85e_uart_wait_for_xmit_ok(n)					      \
-   do { } while (! nb85e_uart_xmit_ok (n))
-
-/* Write character CH to uart channel N.  */
-#define nb85e_uart_putc(n, ch)	(NB85E_UART_TXB(n) = (ch))
-
-
-#define NB85E_UART_MINOR_BASE	64
-
-
-#ifndef __ASSEMBLY__
-
-/* Setup a console using channel 0 of the builtin uart.  */
-extern void nb85e_uart_cons_init (unsigned chan);
-
-/* Configure and turn on uart channel CHAN, using the termios `control
-   modes' bits in CFLAGS, and a baud-rate of BAUD.  */
-void nb85e_uart_configure (unsigned chan, unsigned cflags, unsigned baud);
-
-/* If the macro NB85E_UART_PRE_CONFIGURE is defined (presumably by a
-   <asm/machdep.h>), it is called from nb85e_uart_pre_configure before
-   anything else is done, with interrupts disabled.  */
-
-#endif /* !__ASSEMBLY__ */
-
-
-#endif /* __V850_NB85E_UART_H__ */
diff -Nru a/include/asm-v850/nb85e_utils.h b/include/asm-v850/nb85e_utils.h
--- a/include/asm-v850/nb85e_utils.h	Sat Jul 19 12:54:25 2003
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,35 +0,0 @@
-/*
- * include/asm-v850/nb85e_utils.h -- Utility functions associated with
- *	the NB85E cpu core
- *
- *  Copyright (C) 2001  NEC Corporation
- *  Copyright (C) 2001  Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef __V850_NB85E_UTILS_H__
-#define __V850_NB85E_UTILS_H__
-
-/* Calculate counter clock-divider and count values to attain the
-   desired frequency RATE from the base frequency BASE_FREQ.  The
-   counter is expected to have a clock-divider, which can divide the
-   system cpu clock by a power of two value from MIN_DIVLOG2 to
-   MAX_DIV_LOG2, and a word-size of COUNTER_SIZE bits (the counter
-   counts up and resets whenever it's equal to the compare register,
-   generating an interrupt or whatever when it does so).  The returned
-   values are: *DIVLOG2 -- log2 of the desired clock divider and *COUNT
-   -- the counter compare value to use.  Returns true if it was possible
-   to find a reasonable value, otherwise false (and the other return
-   values will be set to be as good as possible).  */
-extern int calc_counter_params (unsigned long base_freq,
-				unsigned long rate,
-				unsigned min_divlog2, unsigned max_divlog2,
-				unsigned counter_size,
-				unsigned *divlog2, unsigned *count);
-
-#endif /* __V850_NB85E_UTILS_H__ */
diff -Nru a/include/asm-v850/processor.h b/include/asm-v850/processor.h
--- a/include/asm-v850/processor.h	Sat Jul 19 12:54:24 2003
+++ b/include/asm-v850/processor.h	Sat Jul 19 12:54:24 2003
@@ -1,7 +1,7 @@
 /*
  * include/asm-v850/processor.h
  *
- *  Copyright (C) 2001,02,03  NEC Corporation
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
  *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
diff -Nru a/include/asm-v850/ptrace.h b/include/asm-v850/ptrace.h
--- a/include/asm-v850/ptrace.h	Sat Jul 19 12:54:30 2003
+++ b/include/asm-v850/ptrace.h	Sat Jul 19 12:54:30 2003
@@ -1,7 +1,7 @@
 /*
  * include/asm-v850/ptrace.h -- Access to CPU registers
  *
- *  Copyright (C) 2001,02,03  NEC Corporation
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
  *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
diff -Nru a/include/asm-v850/rte_cb.h b/include/asm-v850/rte_cb.h
--- a/include/asm-v850/rte_cb.h	Sat Jul 19 12:54:24 2003
+++ b/include/asm-v850/rte_cb.h	Sat Jul 19 12:54:24 2003
@@ -1,7 +1,7 @@
 /*
  * include/asm-v850/rte_cb.h -- Midas labs RTE-CB series of evaluation boards
  *
- *  Copyright (C) 2001,02,03  NEC Corporation
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
  *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
@@ -20,42 +20,54 @@
 #define MB_A_SRAM_SIZE		0x00200000 /* 2MB */
 
 
+#ifdef CONFIG_RTE_GBUS_INT
 /* GBUS interrupt support.  */
-#define GBUS_INT_BASE_IRQ	NUM_CPU_IRQS
-#define GBUS_INT_BASE_ADDR	(GCS2_ADDR + 0x00006000)
-#include <asm/gbus_int.h>
 
-/* We define NUM_MACH_IRQS to include extra interrupts from the GBUS.  */
-#define NUM_MACH_IRQS		(NUM_CPU_IRQS + IRQ_GBUS_INT_NUM)
+# include <asm/gbus_int.h>
+
+# define GBUS_INT_BASE_IRQ	NUM_RTE_CB_IRQS
+# define GBUS_INT_BASE_ADDR	(GCS2_ADDR + 0x00006000)
 
 /* Some specific interrupts.  */
-#define IRQ_MB_A_LAN		IRQ_GBUS_INT(10)
-#define IRQ_MB_A_PCI1(n)	(IRQ_GBUS_INT(16) + (n))
-#define IRQ_MB_A_PCI1_NUM	4
-#define IRQ_MB_A_PCI2(n)	(IRQ_GBUS_INT(20) + (n))
-#define IRQ_MB_A_PCI2_NUM	4
-#define IRQ_MB_A_EXT(n)		(IRQ_GBUS_INT(24) + (n))
-#define IRQ_MB_A_EXT_NUM	4
-#define IRQ_MB_A_USB_OC(n)	(IRQ_GBUS_INT(28) + (n))
-#define IRQ_MB_A_USB_OC_NUM	2
-#define IRQ_MB_A_PCMCIA_OC	IRQ_GBUS_INT(30)
+# define IRQ_MB_A_LAN		IRQ_GBUS_INT(10)
+# define IRQ_MB_A_PCI1(n)	(IRQ_GBUS_INT(16) + (n))
+# define IRQ_MB_A_PCI1_NUM	4
+# define IRQ_MB_A_PCI2(n)	(IRQ_GBUS_INT(20) + (n))
+# define IRQ_MB_A_PCI2_NUM	4
+# define IRQ_MB_A_EXT(n)	(IRQ_GBUS_INT(24) + (n))
+# define IRQ_MB_A_EXT_NUM	4
+# define IRQ_MB_A_USB_OC(n)	(IRQ_GBUS_INT(28) + (n))
+# define IRQ_MB_A_USB_OC_NUM	2
+# define IRQ_MB_A_PCMCIA_OC	IRQ_GBUS_INT(30)
+
+/* We define NUM_MACH_IRQS to include extra interrupts from the GBUS.  */
+# define NUM_MACH_IRQS		(NUM_RTE_CB_IRQS + IRQ_GBUS_INT_NUM)
 
+#else /* !CONFIG_RTE_GBUS_INT */
 
+# define NUM_MACH_IRQS		NUM_RTE_CB_IRQS
+
+#endif /* CONFIG_RTE_GBUS_INT */
+
+
+#ifdef CONFIG_RTE_MB_A_PCI
 /* Mother-A PCI bus support.  */
-#include <asm/rte_mb_a_pci.h>
+
+# include <asm/rte_mb_a_pci.h>
 
 /* These are the base addresses used for allocating device address
    space.  512K of the motherboard SRAM is in the same space, so we have
    to be careful not to let it be allocated.  */
-#define PCIBIOS_MIN_MEM		(MB_A_PCI_MEM_ADDR + 0x80000)
-#define PCIBIOS_MIN_IO		MB_A_PCI_IO_ADDR
+# define PCIBIOS_MIN_MEM	(MB_A_PCI_MEM_ADDR + 0x80000)
+# define PCIBIOS_MIN_IO		MB_A_PCI_IO_ADDR
 
 /* As we don't really support PCI DMA to cpu memory, and use bounce-buffers
    instead, perversely enough, this becomes always true! */
-#define pci_dma_supported(dev, mask)		1
-#define pci_dac_dma_supported(dev, mask)	0
-#define pcibios_assign_all_busses()		1
+# define pci_dma_supported(dev, mask)		1
+# define pci_dac_dma_supported(dev, mask)	0
+# define pcibios_assign_all_busses()		1
 
+#endif /* CONFIG_RTE_MB_A_PCI */
 
 
 /* For <asm/param.h> */
diff -Nru a/include/asm-v850/rte_ma1_cb.h b/include/asm-v850/rte_ma1_cb.h
--- a/include/asm-v850/rte_ma1_cb.h	Sat Jul 19 12:54:23 2003
+++ b/include/asm-v850/rte_ma1_cb.h	Sat Jul 19 12:54:23 2003
@@ -17,25 +17,6 @@
 #include <asm/rte_cb.h>		/* Common defs for Midas RTE-CB boards.  */
 
 
-/* CPU addresses of GBUS memory spaces.  */
-#define GCS0_ADDR		0x05000000 /* GCS0 - Common SRAM (2MB) */
-#define GCS0_SIZE		0x00200000 /*   2MB */
-#define GCS1_ADDR		0x06000000 /* GCS1 - Flash ROM (8MB) */
-#define GCS1_SIZE		0x00800000 /*   8MB */
-#define GCS2_ADDR		0x07900000 /* GCS2 - I/O registers */
-#define GCS2_SIZE		0x00400000 /*   4MB */
-#define GCS5_ADDR		0x04000000 /* GCS5 - PCI bus space */
-#define GCS5_SIZE		0x01000000 /*   16MB */
-#define GCS6_ADDR		0x07980000 /* GCS6 - PCI control registers */
-#define GCS6_SIZE		0x00000200 /*   512B */
-
-
-/* The GBUS GINT0 - GINT4 interrupts are connected to the INTP000 - INTP011
-   pins on the CPU.  These are shared among the GBUS interrupts.  */
-#define IRQ_GINT(n)		IRQ_INTP(n)
-#define IRQ_GINT_NUM		4
-
-
 #define PLATFORM		"rte-v850e/ma1-cb"
 #define PLATFORM_LONG		"Midas lab RTE-V850E/MA1-CB"
 
@@ -53,10 +34,32 @@
 #define SDRAM_SIZE		0x02000000 /* 32MB */
 
 
+/* CPU addresses of GBUS memory spaces.  */
+#define GCS0_ADDR		0x05000000 /* GCS0 - Common SRAM (2MB) */
+#define GCS0_SIZE		0x00200000 /*   2MB */
+#define GCS1_ADDR		0x06000000 /* GCS1 - Flash ROM (8MB) */
+#define GCS1_SIZE		0x00800000 /*   8MB */
+#define GCS2_ADDR		0x07900000 /* GCS2 - I/O registers */
+#define GCS2_SIZE		0x00400000 /*   4MB */
+#define GCS5_ADDR		0x04000000 /* GCS5 - PCI bus space */
+#define GCS5_SIZE		0x01000000 /*   16MB */
+#define GCS6_ADDR		0x07980000 /* GCS6 - PCI control registers */
+#define GCS6_SIZE		0x00000200 /*   512B */
+
+
 /* For <asm/page.h> */
 #define PAGE_OFFSET 		SRAM_ADDR
 
 
+/* The GBUS GINT0 - GINT3 interrupts are connected to the INTP000 - INTP011
+   pins on the CPU.  These are shared among the GBUS interrupts.  */
+#define IRQ_GINT(n)		IRQ_INTP(n)
+#define IRQ_GINT_NUM		4
+
+/* Used by <asm/rte_cb.h> to derive NUM_MACH_IRQS.  */
+#define NUM_RTE_CB_IRQS		NUM_CPU_IRQS
+
+
 #ifdef CONFIG_ROM_KERNEL
 /* Kernel is in ROM, starting at address 0.  */
 
@@ -98,8 +101,8 @@
 
 /* Override the basic MA uart pre-initialization so that we can
    initialize extra stuff.  */
-#undef NB85E_UART_PRE_CONFIGURE	/* should be defined by <asm/ma.h> */
-#define NB85E_UART_PRE_CONFIGURE	rte_ma1_cb_uart_pre_configure
+#undef V850E_UART_PRE_CONFIGURE	/* should be defined by <asm/ma.h> */
+#define V850E_UART_PRE_CONFIGURE	rte_ma1_cb_uart_pre_configure
 #ifndef __ASSEMBLY__
 extern void rte_ma1_cb_uart_pre_configure (unsigned chan,
 					   unsigned cflags, unsigned baud);
@@ -108,9 +111,9 @@
 /* This board supports RTS/CTS for the on-chip UART, but only for channel 0. */
 
 /* CTS for UART channel 0 is pin P43 (bit 3 of port 4).  */
-#define NB85E_UART_CTS(chan)	((chan) == 0 ? !(MA_PORT4_IO & 0x8) : 1)
+#define V850E_UART_CTS(chan)	((chan) == 0 ? !(MA_PORT4_IO & 0x8) : 1)
 /* RTS for UART channel 0 is pin P42 (bit 2 of port 4).  */
-#define NB85E_UART_SET_RTS(chan, val)					      \
+#define V850E_UART_SET_RTS(chan, val)					      \
    do {									      \
 	   if (chan == 0) {						      \
 		   unsigned old = MA_PORT4_IO; 				      \
diff -Nru a/include/asm-v850/rte_me2_cb.h b/include/asm-v850/rte_me2_cb.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-v850/rte_me2_cb.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,202 @@
+/*
+ * include/asm-v850/rte_me2_cb.h -- Midas labs RTE-V850E/ME2-CB board
+ *
+ *  Copyright (C) 2001,02,03  NEC Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#ifndef __V850_RTE_ME2_CB_H__
+#define __V850_RTE_ME2_CB_H__
+
+#include <asm/rte_cb.h>		/* Common defs for Midas RTE-CB boards.  */
+
+
+#define PLATFORM		"rte-v850e/me2-cb"
+#define PLATFORM_LONG		"Midas lab RTE-V850E/ME2-CB"
+
+#define CPU_CLOCK_FREQ		150000000 /* 150MHz */
+#define FIXED_BOGOMIPS		50
+
+/* 32MB of onbard SDRAM.  */
+#define SDRAM_ADDR		0x00800000
+#define SDRAM_SIZE		0x02000000 /* 32MB */
+
+
+/* CPU addresses of GBUS memory spaces.  */
+#define GCS0_ADDR		0x04000000 /* GCS0 - Common SRAM (2MB) */
+#define GCS0_SIZE		0x00800000 /*   8MB */
+#define GCS1_ADDR		0x04800000 /* GCS1 - Flash ROM (8MB) */
+#define GCS1_SIZE		0x00800000 /*   8MB */
+#define GCS2_ADDR		0x07000000 /* GCS2 - I/O registers */
+#define GCS2_SIZE		0x00800000 /*   8MB */
+#define GCS5_ADDR		0x08000000 /* GCS5 - PCI bus space */
+#define GCS5_SIZE		0x02000000 /*   32MB */
+#define GCS6_ADDR		0x07800000 /* GCS6 - PCI control registers */
+#define GCS6_SIZE		0x00800000 /*   8MB */
+
+
+/* For <asm/page.h> */
+#define PAGE_OFFSET 		SDRAM_ADDR
+
+
+#ifdef CONFIG_ROM_KERNEL
+/* Kernel is in ROM, starting at address 0.  */
+
+#define INTV_BASE		0
+#define ROOT_FS_IMAGE_RW	0
+
+#else /* !CONFIG_ROM_KERNEL */
+/* Using RAM-kernel.  Assume some sort of boot-loader got us loaded at
+   address 0.  */
+
+#define INTV_BASE		0
+#define ROOT_FS_IMAGE_RW	1
+
+#endif /* CONFIG_ROM_KERNEL */
+
+
+/* Some misc. on-board devices.  */
+
+/* Seven-segment LED display (four digits).  */
+#define LED_ADDR(n)		(0x0FE02000 + (n))
+#define LED(n)			(*(volatile unsigned char *)LED_ADDR(n))
+#define LED_NUM_DIGITS		4
+
+
+/* On-board PIC.  */
+
+#define CB_PIC_BASE_ADDR 	0x0FE04000
+
+#define CB_PIC_INT0M_ADDR 	(CB_PIC_BASE_ADDR + 0x00)
+#define CB_PIC_INT0M      	(*(volatile u16 *)CB_PIC_INT0M_ADDR)
+#define CB_PIC_INT1M_ADDR 	(CB_PIC_BASE_ADDR + 0x10)
+#define CB_PIC_INT1M      	(*(volatile u16 *)CB_PIC_INT1M_ADDR)
+#define CB_PIC_INTR_ADDR  	(CB_PIC_BASE_ADDR + 0x20)
+#define CB_PIC_INTR       	(*(volatile u16 *)CB_PIC_INTR_ADDR)
+#define CB_PIC_INTEN_ADDR 	(CB_PIC_BASE_ADDR + 0x30)
+#define CB_PIC_INTEN      	(*(volatile u16 *)CB_PIC_INTEN_ADDR)
+
+#define CB_PIC_INT0EN        	0x0001
+#define CB_PIC_INT1EN        	0x0002
+#define CB_PIC_INT0SEL       	0x0080
+
+/* The PIC interrupts themselves.  */
+#define CB_PIC_BASE_IRQ		NUM_CPU_IRQS
+#define IRQ_CB_PIC_NUM		10
+
+/* Some specific CB_PIC interrupts. */
+#define IRQ_CB_EXTTM0		(CB_PIC_BASE_IRQ + 0)
+#define IRQ_CB_EXTSIO		(CB_PIC_BASE_IRQ + 1)
+#define IRQ_CB_TOVER		(CB_PIC_BASE_IRQ + 2)
+#define IRQ_CB_GINT0		(CB_PIC_BASE_IRQ + 3)
+#define IRQ_CB_USB		(CB_PIC_BASE_IRQ + 4)
+#define IRQ_CB_LANC		(CB_PIC_BASE_IRQ + 5)
+#define IRQ_CB_USB_VBUS_ON	(CB_PIC_BASE_IRQ + 6)
+#define IRQ_CB_USB_VBUS_OFF	(CB_PIC_BASE_IRQ + 7)
+#define IRQ_CB_EXTTM1		(CB_PIC_BASE_IRQ + 8)
+#define IRQ_CB_EXTTM2		(CB_PIC_BASE_IRQ + 9)
+
+/* The GBUS GINT1 - GINT3 (note, not GINT0!) interrupts are connected to
+   the INTP65 - INTP67 pins on the CPU.  These are shared among the GBUS
+   interrupts.  */
+#define IRQ_GINT(n)		IRQ_INTP((n) + 9)  /* 0 is unused! */
+#define IRQ_GINT_NUM		4		   /* 0 is unused! */
+
+/* The shared interrupt line from the PIC is connected to CPU pin INTP23.  */
+#define IRQ_CB_PIC		IRQ_INTP(4) /* P23 */
+
+/* Used by <asm/rte_cb.h> to derive NUM_MACH_IRQS.  */
+#define NUM_RTE_CB_IRQS		(NUM_CPU_IRQS + IRQ_CB_PIC_NUM)
+
+
+#ifndef __ASSEMBLY__
+struct cb_pic_irq_init {
+	const char *name;	/* name of interrupt type */
+
+	/* Range of kernel irq numbers for this type:
+	   BASE, BASE+INTERVAL, ..., BASE+INTERVAL*NUM  */
+	unsigned base, num, interval;
+
+	unsigned priority;	/* interrupt priority to assign */
+};
+struct hw_interrupt_type;	/* fwd decl */
+
+/* Enable interrupt handling for interrupt IRQ.  */
+extern void cb_pic_enable_irq (unsigned irq);
+/* Disable interrupt handling for interrupt IRQ.  Note that any interrupts
+   received while disabled will be delivered once the interrupt is enabled
+   again, unless they are explicitly cleared using `cb_pic_clear_pending_irq'.  */
+extern void cb_pic_disable_irq (unsigned irq);
+/* Initialize HW_IRQ_TYPES for PIC irqs described in array INITS (which is
+   terminated by an entry with the name field == 0).  */
+extern void cb_pic_init_irq_types (struct cb_pic_irq_init *inits,
+				   struct hw_interrupt_type *hw_irq_types);
+/* Initialize PIC interrupts.  */
+extern void cb_pic_init_irqs (void);
+#endif /* __ASSEMBLY__ */
+
+
+/* TL16C550C on board UART see also asm/serial.h */
+#define CB_UART_BASE    	0x0FE08000
+#define CB_UART_REG_GAP 	0x10
+#define CB_UART_CLOCK   	0x16000000
+
+/* CompactFlash setting see also asm/ide.h, asm/hdreg.h.  */
+#define CB_CF_BASE     		0x0FE0C000
+#define CB_CF_CCR_ADDR 		(CB_CF_BASE+0x200)
+#define CB_CF_CCR      		(*(volatile u8 *)CB_CF_CCR_ADDR)
+#define CB_CF_REG0_ADDR		(CB_CF_BASE+0x1000)
+#define CB_CF_REG0     		(*(volatile u16 *)CB_CF_REG0_ADDR)
+#define CB_CF_STS0_ADDR		(CB_CF_BASE+0x1004)
+#define CB_CF_STS0     		(*(volatile u16 *)CB_CF_STS0_ADDR)
+#define CB_PCATA_BASE  		(CB_CF_BASE+0x800)
+#define CB_IDE_BASE    		(CB_CF_BASE+0x9F0)
+#define CB_IDE_CTRL    		(CB_CF_BASE+0xBF6)
+#define CB_IDE_REG_OFFS		0x1
+
+
+/* SMSC LAN91C111 setting */
+#if defined(CONFIG_SMC91111)
+#define CB_LANC_BASE 		0x0FE10300
+#define CONFIG_SMC16BITONLY
+#define ETH0_ADDR 		CB_LANC_BASE
+#define ETH0_IRQ 		IRQ_CB_LANC
+#endif /* CONFIG_SMC16BITONLY */
+
+
+#undef V850E_UART_PRE_CONFIGURE
+#define V850E_UART_PRE_CONFIGURE	rte_me2_cb_uart_pre_configure
+#ifndef __ASSEMBLY__
+extern void rte_me2_cb_uart_pre_configure (unsigned chan,
+					   unsigned cflags, unsigned baud);
+#endif /* __ASSEMBLY__ */
+
+/* This board supports RTS/CTS for the on-chip UART, but only for channel 0. */
+
+/* CTS for UART channel 0 is pin P22 (bit 2 of port 2).  */
+#define V850E_UART_CTS(chan)	((chan) == 0 ? !(ME2_PORT2_IO & 0x4) : 1)
+/* RTS for UART channel 0 is pin P21 (bit 1 of port 2).  */
+#define V850E_UART_SET_RTS(chan, val)					      \
+   do {									      \
+	   if (chan == 0) {						      \
+		   unsigned old = ME2_PORT2_IO; 			      \
+		   if (val)						      \
+			   ME2_PORT2_IO = old & ~0x2;			      \
+		   else							      \
+			   ME2_PORT2_IO = old | 0x2;			      \
+	   }								      \
+   } while (0)
+
+
+#ifndef __ASSEMBLY__
+extern void rte_me2_cb_init_irqs (void);
+#endif /* !__ASSEMBLY__ */
+
+
+#endif /* __V850_RTE_ME2_CB_H__ */
diff -Nru a/include/asm-v850/rte_nb85e_cb.h b/include/asm-v850/rte_nb85e_cb.h
--- a/include/asm-v850/rte_nb85e_cb.h	Sat Jul 19 12:54:27 2003
+++ b/include/asm-v850/rte_nb85e_cb.h	Sat Jul 19 12:54:27 2003
@@ -17,6 +17,21 @@
 #include <asm/rte_cb.h>		/* Common defs for Midas RTE-CB boards.  */
 
 
+#define PLATFORM		"rte-v850e/nb85e-cb"
+#define PLATFORM_LONG		"Midas lab RTE-V850E/NB85E-CB"
+
+#define CPU_CLOCK_FREQ		50000000 /* 50MHz */
+
+/* 1MB of onboard SRAM.  Note that the monitor ROM uses parts of this
+   for its own purposes, so care must be taken.  */
+#define SRAM_ADDR		0x03C00000
+#define SRAM_SIZE		0x00100000 /* 1MB */
+
+/* 16MB of onbard SDRAM.  */
+#define SDRAM_ADDR		0x01000000
+#define SDRAM_SIZE		0x01000000 /* 16MB */
+
+
 /* CPU addresses of GBUS memory spaces.  */
 #define GCS0_ADDR		0x00400000 /* GCS0 - Common SRAM (2MB) */
 #define GCS0_SIZE		0x00400000 /*   4MB */
@@ -39,20 +54,8 @@
 #define IRQ_GINT(n)		(10 + (n))
 #define IRQ_GINT_NUM		3
 
-
-#define PLATFORM	"rte-v850e/nb85e-cb"
-#define PLATFORM_LONG	"Midas lab RTE-V850E/NB85E-CB"
-
-#define CPU_CLOCK_FREQ	50000000 /* 50MHz */
-
-/* 1MB of onboard SRAM.  Note that the monitor ROM uses parts of this
-   for its own purposes, so care must be taken.  */
-#define SRAM_ADDR	0x03C00000
-#define SRAM_SIZE	0x00100000 /* 1MB */
-
-/* 16MB of onbard SDRAM.  */
-#define SDRAM_ADDR	0x01000000
-#define SDRAM_SIZE	0x01000000 /* 16MB */
+/* Used by <asm/rte_cb.h> to derive NUM_MACH_IRQS.  */
+#define NUM_RTE_CB_IRQS		NUM_CPU_IRQS
 
 
 #ifdef CONFIG_ROM_KERNEL
@@ -86,8 +89,8 @@
 
 /* Override the basic TEG UART pre-initialization so that we can
    initialize extra stuff.  */
-#undef NB85E_UART_PRE_CONFIGURE	/* should be defined by <asm/teg.h> */
-#define NB85E_UART_PRE_CONFIGURE	rte_nb85e_cb_uart_pre_configure
+#undef V850E_UART_PRE_CONFIGURE	/* should be defined by <asm/teg.h> */
+#define V850E_UART_PRE_CONFIGURE	rte_nb85e_cb_uart_pre_configure
 #ifndef __ASSEMBLY__
 extern void rte_nb85e_cb_uart_pre_configure (unsigned chan,
 					     unsigned cflags, unsigned baud);
@@ -96,9 +99,9 @@
 /* This board supports RTS/CTS for the on-chip UART. */
 
 /* CTS is pin P00.  */
-#define NB85E_UART_CTS(chan)	(! (TEG_PORT0_IO & 0x1))
+#define V850E_UART_CTS(chan)	(! (TEG_PORT0_IO & 0x1))
 /* RTS is pin P02.  */
-#define NB85E_UART_SET_RTS(chan, val)					      \
+#define V850E_UART_SET_RTS(chan, val)					      \
    do {									      \
 	   unsigned old = TEG_PORT0_IO;					      \
 	   TEG_PORT0_IO = val ? (old & ~0x4) : (old | 0x4);		      \
diff -Nru a/include/asm-v850/serial.h b/include/asm-v850/serial.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-v850/serial.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,58 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ */ 
+#include <linux/config.h>
+
+#ifdef CONFIG_RTE_CB_ME2
+
+#include <asm/rte_me2_cb.h>
+
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+
+#define irq_cannonicalize(x) (x)
+#define BASE_BAUD	250000	/* (16MHz / (16 * 38400)) * 9600 */
+#define RS_TABLE_SIZE	1
+#define SERIAL_PORT_DFNS \
+   { 0, BASE_BAUD, CB_UART_BASE, IRQ_CB_EXTSIO, STD_COM_FLAGS },
+
+/* Redefine UART register offsets.  */
+#undef UART_RX
+#undef UART_TX
+#undef UART_DLL
+#undef UART_TRG
+#undef UART_DLM
+#undef UART_IER
+#undef UART_FCTR
+#undef UART_IIR
+#undef UART_FCR
+#undef UART_EFR
+#undef UART_LCR
+#undef UART_MCR
+#undef UART_LSR
+#undef UART_MSR
+#undef UART_SCR
+#undef UART_EMSR
+
+#define UART_RX		(0 * CB_UART_REG_GAP)
+#define UART_TX		(0 * CB_UART_REG_GAP)
+#define UART_DLL	(0 * CB_UART_REG_GAP)
+#define UART_TRG	(0 * CB_UART_REG_GAP)
+#define UART_DLM	(1 * CB_UART_REG_GAP)
+#define UART_IER	(1 * CB_UART_REG_GAP)
+#define UART_FCTR	(1 * CB_UART_REG_GAP)
+#define UART_IIR	(2 * CB_UART_REG_GAP)
+#define UART_FCR	(2 * CB_UART_REG_GAP)
+#define UART_EFR	(2 * CB_UART_REG_GAP)
+#define UART_LCR	(3 * CB_UART_REG_GAP)
+#define UART_MCR	(4 * CB_UART_REG_GAP)
+#define UART_LSR	(5 * CB_UART_REG_GAP)
+#define UART_MSR	(6 * CB_UART_REG_GAP)
+#define UART_SCR	(7 * CB_UART_REG_GAP)
+#define UART_EMSR	(7 * CB_UART_REG_GAP)
+
+#endif /* CONFIG_RTE_CB_ME2 */
diff -Nru a/include/asm-v850/sim85e2.h b/include/asm-v850/sim85e2.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-v850/sim85e2.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,79 @@
+/*
+ * include/asm-v850/sim85e2.h -- Machine-dependent defs for
+ *	V850E2 RTL simulator
+ *
+ *  Copyright (C) 2002,03  NEC Electronics Corporation
+ *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#ifndef __V850_SIM85E2_H__
+#define __V850_SIM85E2_H__
+
+
+#include <asm/v850e2.h>		/* Based on V850E2 core.  */
+
+
+/* Various memory areas supported by the simulator.
+   These should match the corresponding definitions in the linker script.  */
+
+/* `instruction RAM'; instruction fetches are much faster from IRAM than
+   from DRAM.  */
+#define IRAM_ADDR		0
+#define IRAM_SIZE		0x00100000 /* 1MB */
+/* `data RAM', below and contiguous with the I/O space.
+   Data fetches are much faster from DRAM than from IRAM.  */
+#define DRAM_ADDR		0xfff00000
+#define DRAM_SIZE		0x000ff000 /* 1020KB */
+/* `external ram'.  Unlike the above RAM areas, this memory is cached,
+   so both instruction and data fetches should be (mostly) fast --
+   however, currently only write-through caching is supported, so writes
+   to ERAM will be slow.  */
+#define ERAM_ADDR		0x00100000
+#define ERAM_SIZE		0x07f00000 /* 127MB (max) */
+/* Dynamic RAM; uses memory controller.  */
+#define SDRAM_ADDR		0x10000000
+#if 0
+#define SDRAM_SIZE		0x01000000 /* 16MB */
+#else
+#define SDRAM_SIZE		0x00200000 /* Only use 2MB for testing */
+#endif
+
+
+/* Simulator specific control registers.  */
+/* NOTHAL controls whether the simulator will stop at a `halt' insn.  */
+#define SIM85E2_NOTHAL_ADDR	0xffffff22
+#define SIM85E2_NOTHAL		(*(volatile u8 *)SIM85E2_NOTHAL_ADDR)
+/* The simulator will stop N cycles after N is written to SIMFIN.  */
+#define SIM85E2_SIMFIN_ADDR	0xffffff24
+#define SIM85E2_SIMFIN		(*(volatile u16 *)SIM85E2_SIMFIN_ADDR)
+
+
+/* For <asm/irq.h> */
+#define NUM_CPU_IRQS		64
+
+
+/* For <asm/page.h> */
+#define PAGE_OFFSET		SDRAM_ADDR
+
+
+/* For <asm/entry.h> */
+/* `R0 RAM', used for a few miscellaneous variables that must be accessible
+   using a load instruction relative to R0.  The sim85e2 simulator
+   actually puts 1020K of RAM from FFF00000 to FFFFF000, so we arbitarily
+   choose a small portion at the end of that.  */
+#define R0_RAM_ADDR		0xFFFFE000
+
+
+/* For <asm/param.h> */
+#ifndef HZ
+#define HZ			24	/* Minimum supported frequency.  */
+#endif
+
+
+#endif /* __V850_SIM85E2_H__ */
diff -Nru a/include/asm-v850/sim85e2c.h b/include/asm-v850/sim85e2c.h
--- a/include/asm-v850/sim85e2c.h	Sat Jul 19 12:54:23 2003
+++ b/include/asm-v850/sim85e2c.h	Sat Jul 19 12:54:23 2003
@@ -15,78 +15,12 @@
 #ifndef __V850_SIM85E2C_H__
 #define __V850_SIM85E2C_H__
 
+/* Use generic sim85e2 settings, other than the various names.  */
+#include <asm/sim85e2.h>
 
-#define CPU_ARCH 	"v850e2"
 #define CPU_MODEL	"v850e2"
 #define CPU_MODEL_LONG	"NEC V850E2"
 #define PLATFORM	"sim85e2c"
 #define PLATFORM_LONG	"SIM85E2C V850E2 simulator"
-
-
-/* Various memory areas supported by the simulator.
-   These should match the corresponding definitions in the linker script.  */
-
-/* `instruction RAM'; instruction fetches are much faster from IRAM than
-   from DRAM.  */
-#define IRAM_ADDR		0
-#define IRAM_SIZE		0x00100000 /* 1MB */
-/* `data RAM', below and contiguous with the I/O space.
-   Data fetches are much faster from DRAM than from IRAM.  */
-#define DRAM_ADDR		0xfff00000
-#define DRAM_SIZE		0x000ff000 /* 1020KB */
-/* `external ram'.  Unlike the above RAM areas, this memory is cached,
-   so both instruction and data fetches should be (mostly) fast --
-   however, currently only write-through caching is supported, so writes
-   to ERAM will be slow.  */
-#define ERAM_ADDR		0x00100000
-#define ERAM_SIZE		0x07f00000 /* 127MB (max) */
-
-
-/* CPU core control registers; these should be expanded and moved into
-   separate header files when we support some other processors based on
-   the same E2 core.  */
-/* Bus Transaction Control Register */
-#define NA85E2C_CACHE_BTSC_ADDR	0xfffff070
-#define NA85E2C_CACHE_BTSC 	(*(volatile unsigned short *)NA85E2C_CACHE_BTSC_ADDR)
-#define NA85E2C_CACHE_BTSC_ICM	0x1 /* icache enable */
-#define NA85E2C_CACHE_BTSC_DCM0	0x4 /* dcache enable, bit 0 */
-#define NA85E2C_CACHE_BTSC_DCM1	0x8 /* dcache enable, bit 1 */
-/* Cache Configuration Register */
-#define NA85E2C_BUSM_BHC_ADDR	0xfffff06a
-#define NA85E2C_BUSM_BHC	(*(volatile unsigned short *)NA85E2C_BUSM_BHC_ADDR)
-
-/* Simulator specific control registers.  */
-/* NOTHAL controls whether the simulator will stop at a `halt' insn.  */
-#define NOTHAL_ADDR		0xffffff22
-#define NOTHAL			(*(volatile unsigned char *)NOTHAL_ADDR)
-/* The simulator will stop N cycles after N is written to SIMFIN.  */
-#define SIMFIN_ADDR		0xffffff24
-#define SIMFIN			(*(volatile unsigned short *)SIMFIN_ADDR)
-
-
-/* The simulator has an nb85e-style interrupt system.  */
-#include <asm/nb85e_intc.h>
-
-/* For <asm/irq.h> */
-#define NUM_CPU_IRQS		64
-
-
-/* For <asm/page.h> */
-#define PAGE_OFFSET		DRAM_ADDR
-
-
-/* For <asm/entry.h> */
-/* `R0 RAM', used for a few miscellaneous variables that must be accessible
-   using a load instruction relative to R0.  The sim85e2c simulator
-   actually puts 1020K of RAM from FFF00000 to FFFFF000, so we arbitarily
-   choose a small portion at the end of that.  */
-#define R0_RAM_ADDR		0xFFFFE000
-
-
-/* For <asm/param.h> */
-#ifndef HZ
-#define HZ			24	/* Minimum supported frequency.  */
-#endif
-
 
 #endif /* __V850_SIM85E2C_H__ */
diff -Nru a/include/asm-v850/sim85e2s.h b/include/asm-v850/sim85e2s.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-v850/sim85e2s.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,28 @@
+/*
+ * include/asm-v850/sim85e2s.h -- Machine-dependent defs for
+ *	V850E2 RTL simulator
+ *
+ *  Copyright (C) 2003  NEC Electronics Corporation
+ *  Copyright (C) 2003  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#ifndef __V850_SIM85E2S_H__
+#define __V850_SIM85E2S_H__
+
+#include <asm/sim85e2.h>	/* Use generic sim85e2 settings.  */
+#if 0
+#include <asm/v850e2_cache.h>	/* + cache */
+#endif
+
+#define CPU_MODEL	"v850e2"
+#define CPU_MODEL_LONG	"NEC V850E2"
+#define PLATFORM	"sim85e2s"
+#define PLATFORM_LONG	"SIM85E2S V850E2 simulator"
+
+#endif /* __V850_SIM85E2S_H__ */
diff -Nru a/include/asm-v850/stat.h b/include/asm-v850/stat.h
--- a/include/asm-v850/stat.h	Sat Jul 19 12:54:26 2003
+++ b/include/asm-v850/stat.h	Sat Jul 19 12:54:26 2003
@@ -1,7 +1,7 @@
 /*
  * include/asm-v850/stat.h -- v850 stat structure
  *
- *  Copyright (C) 2001,02,03  NEC Corporation
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
  *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
diff -Nru a/include/asm-v850/system.h b/include/asm-v850/system.h
--- a/include/asm-v850/system.h	Sat Jul 19 12:54:26 2003
+++ b/include/asm-v850/system.h	Sat Jul 19 12:54:26 2003
@@ -1,7 +1,7 @@
 /*
  * include/asm-v850/system.h -- Low-level interrupt/thread ops
  *
- *  Copyright (C) 2001,02,03  NEC Corporation
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
  *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
diff -Nru a/include/asm-v850/teg.h b/include/asm-v850/teg.h
--- a/include/asm-v850/teg.h	Sat Jul 19 12:54:21 2003
+++ b/include/asm-v850/teg.h	Sat Jul 19 12:54:21 2003
@@ -15,9 +15,9 @@
 #define __V850_TEG_H__
 
 
-/* The TEG uses the NB85E cpu core.  */
-#include <asm/nb85e.h>
-#include <asm/nb85e_cache.h>
+/* The TEG uses the V850E cpu core.  */
+#include <asm/v850e.h>
+#include <asm/v850e_cache.h>
 
 
 #define CPU_MODEL	"v850e/nb85e-teg"
@@ -51,18 +51,18 @@
 
 
 /* TEG UART details.  */
-#define NB85E_UART_BASE_ADDR(n)		(0xFFFFF600 + 0x10 * (n))
-#define NB85E_UART_ASIM_ADDR(n)		(NB85E_UART_BASE_ADDR(n) + 0x0)
-#define NB85E_UART_ASIS_ADDR(n)		(NB85E_UART_BASE_ADDR(n) + 0x2)
-#define NB85E_UART_ASIF_ADDR(n)		(NB85E_UART_BASE_ADDR(n) + 0x4)
-#define NB85E_UART_CKSR_ADDR(n)		(NB85E_UART_BASE_ADDR(n) + 0x6)
-#define NB85E_UART_BRGC_ADDR(n)		(NB85E_UART_BASE_ADDR(n) + 0x8)
-#define NB85E_UART_TXB_ADDR(n)		(NB85E_UART_BASE_ADDR(n) + 0xA)
-#define NB85E_UART_RXB_ADDR(n)		(NB85E_UART_BASE_ADDR(n) + 0xC)
-#define NB85E_UART_NUM_CHANNELS		1
-#define NB85E_UART_BASE_FREQ		CPU_CLOCK_FREQ
+#define V850E_UART_BASE_ADDR(n)		(0xFFFFF600 + 0x10 * (n))
+#define V850E_UART_ASIM_ADDR(n)		(V850E_UART_BASE_ADDR(n) + 0x0)
+#define V850E_UART_ASIS_ADDR(n)		(V850E_UART_BASE_ADDR(n) + 0x2)
+#define V850E_UART_ASIF_ADDR(n)		(V850E_UART_BASE_ADDR(n) + 0x4)
+#define V850E_UART_CKSR_ADDR(n)		(V850E_UART_BASE_ADDR(n) + 0x6)
+#define V850E_UART_BRGC_ADDR(n)		(V850E_UART_BASE_ADDR(n) + 0x8)
+#define V850E_UART_TXB_ADDR(n)		(V850E_UART_BASE_ADDR(n) + 0xA)
+#define V850E_UART_RXB_ADDR(n)		(V850E_UART_BASE_ADDR(n) + 0xC)
+#define V850E_UART_NUM_CHANNELS		1
+#define V850E_UART_BASE_FREQ		CPU_CLOCK_FREQ
 /* This is a function that gets called before configuring the UART.  */
-#define NB85E_UART_PRE_CONFIGURE	teg_uart_pre_configure
+#define V850E_UART_PRE_CONFIGURE	teg_uart_pre_configure
 #ifndef __ASSEMBLY__
 extern void teg_uart_pre_configure (unsigned chan,
 				    unsigned cflags, unsigned baud);
@@ -70,15 +70,15 @@
 
 
 /* The TEG RTPU.  */
-#define NB85E_RTPU_BASE_ADDR		0xFFFFF210
+#define V850E_RTPU_BASE_ADDR		0xFFFFF210
 
 
 /* TEG series timer D details.  */
-#define NB85E_TIMER_D_BASE_ADDR		0xFFFFF210
-#define NB85E_TIMER_D_TMCD_BASE_ADDR 	(NB85E_TIMER_D_BASE_ADDR + 0x0)
-#define NB85E_TIMER_D_TMD_BASE_ADDR 	(NB85E_TIMER_D_BASE_ADDR + 0x4)
-#define NB85E_TIMER_D_CMD_BASE_ADDR 	(NB85E_TIMER_D_BASE_ADDR + 0x8)
-#define NB85E_TIMER_D_BASE_FREQ		CPU_CLOCK_FREQ
+#define V850E_TIMER_D_BASE_ADDR		0xFFFFF210
+#define V850E_TIMER_D_TMCD_BASE_ADDR 	(V850E_TIMER_D_BASE_ADDR + 0x0)
+#define V850E_TIMER_D_TMD_BASE_ADDR 	(V850E_TIMER_D_BASE_ADDR + 0x4)
+#define V850E_TIMER_D_CMD_BASE_ADDR 	(V850E_TIMER_D_BASE_ADDR + 0x8)
+#define V850E_TIMER_D_BASE_FREQ		CPU_CLOCK_FREQ
 
 
 /* `Interrupt Source Select' control register.  */
diff -Nru a/include/asm-v850/v850e.h b/include/asm-v850/v850e.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-v850/v850e.h	Sat Jul 19 12:54:25 2003
@@ -0,0 +1,21 @@
+/*
+ * include/asm-v850/v850e.h -- V850E CPU
+ *
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#ifndef __V850_V850E_H__
+#define __V850_V850E_H__
+
+#include <asm/v850e_intc.h>
+
+#define CPU_ARCH "v850e"
+
+#endif /* __V850_V850E_H__ */
diff -Nru a/include/asm-v850/v850e2.h b/include/asm-v850/v850e2.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-v850/v850e2.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,69 @@
+/*
+ * include/asm-v850/v850e2.h -- Machine-dependent defs for V850E2 CPUs
+ *
+ *  Copyright (C) 2002,03  NEC Electronics Corporation
+ *  Copyright (C) 2002,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#ifndef __V850_V850E2_H__
+#define __V850_V850E2_H__
+
+#include <asm/v850e_intc.h>	/* v850e-style interrupt system.  */
+
+
+#define CPU_ARCH "v850e2"
+
+
+/* Control registers.  */
+
+/* Chip area select control */ 
+#define V850E2_CSC_ADDR(n)	(0xFFFFF060 + (n) * 2)
+#define V850E2_CSC(n)		(*(volatile u16 *)V850E2_CSC_ADDR(n))
+/* I/O area select control */
+#define V850E2_BPC_ADDR		0xFFFFF064
+#define V850E2_BPC		(*(volatile u16 *)V850E2_BPC_ADDR)
+/* Bus size configuration */
+#define V850E2_BSC_ADDR		0xFFFFF066
+#define V850E2_BSC		(*(volatile u16 *)V850E2_BSC_ADDR)
+/* Endian configuration */
+#define V850E2_BEC_ADDR		0xFFFFF068
+#define V850E2_BEC		(*(volatile u16 *)V850E2_BEC_ADDR)
+/* Cache configuration */
+#define V850E2_BHC_ADDR		0xFFFFF06A
+#define V850E2_BHC		(*(volatile u16 *)V850E2_BHC_ADDR)
+/* NPB strobe-wait configuration */
+#define V850E2_VSWC_ADDR	0xFFFFF06E
+#define V850E2_VSWC		(*(volatile u16 *)V850E2_VSWC_ADDR)
+/* Bus cycle type */
+#define V850E2_BCT_ADDR(n)	(0xFFFFF480 + (n) * 2)
+#define V850E2_BCT(n)		(*(volatile u16 *)V850E2_BCT_ADDR(n))
+/* Data wait control */
+#define V850E2_DWC_ADDR(n)	(0xFFFFF484 + (n) * 2)
+#define V850E2_DWC(n)		(*(volatile u16 *)V850E2_DWC_ADDR(n))
+/* Bus cycle control */
+#define V850E2_BCC_ADDR		0xFFFFF488
+#define V850E2_BCC		(*(volatile u16 *)V850E2_BCC_ADDR)
+/* Address wait control */
+#define V850E2_ASC_ADDR		0xFFFFF48A
+#define V850E2_ASC		(*(volatile u16 *)V850E2_ASC_ADDR)
+/* Local bus sizing control */
+#define V850E2_LBS_ADDR		0xFFFFF48E
+#define V850E2_LBS		(*(volatile u16 *)V850E2_LBS_ADDR)
+/* Line buffer control */
+#define V850E2_LBC_ADDR(n)	(0xFFFFF490 + (n) * 2)
+#define V850E2_LBC(n)		(*(volatile u16 *)V850E2_LBC_ADDR(n))
+/* SDRAM configuration */
+#define V850E2_SCR_ADDR(n)	(0xFFFFF4A0 + (n) * 4)
+#define V850E2_SCR(n)		(*(volatile u16 *)V850E2_SCR_ADDR(n))
+/* SDRAM refresh cycle control */
+#define V850E2_RFS_ADDR(n)	(0xFFFFF4A2 + (n) * 4)
+#define V850E2_RFS(n)		(*(volatile u16 *)V850E2_RFS_ADDR(n))
+
+
+#endif /* __V850_V850E2_H__ */
diff -Nru a/include/asm-v850/v850e2_cache.h b/include/asm-v850/v850e2_cache.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-v850/v850e2_cache.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,74 @@
+/*
+ * include/asm-v850/v850e2_cache_cache.h -- Cache control for V850E2
+ * 	cache memories
+ *
+ *  Copyright (C) 2003  NEC Electronics Corporation
+ *  Copyright (C) 2003  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#ifndef __V850_V850E2_CACHE_H__
+#define __V850_V850E2_CACHE_H__
+
+#include <asm/types.h>
+
+
+/* Cache control registers.  */
+
+/* Bus Transaction Control */
+#define V850E2_CACHE_BTSC_ADDR	0xFFFFF070
+#define V850E2_CACHE_BTSC 	(*(volatile u16 *)V850E2_CACHE_BTSC_ADDR)
+#define V850E2_CACHE_BTSC_ICM	0x0001 /* icache enable */
+#define V850E2_CACHE_BTSC_DCM0	0x0004 /* dcache enable, bit 0 */
+#define V850E2_CACHE_BTSC_DCM1	0x0008 /* dcache enable, bit 1 */
+#define V850E2_CACHE_BTSC_DCM_WT		      /* write-through */ \
+			V850E2_CACHE_BTSC_DCM0
+#ifdef CONFIG_V850E2_V850E2S
+# define V850E2_CACHE_BTSC_DCM_WB_NO_ALLOC    /* write-back, non-alloc */ \
+			V850E2_CACHE_BTSC_DCM1	
+# define V850E2_CACHE_BTSC_DCM_WB_ALLOC	      /* write-back, non-alloc */ \
+			(V850E2_CACHE_BTSC_DCM1 | V850E2_CACHE_BTSC_DCM0)
+# define V850E2_CACHE_BTSC_ISEQ	0x0010 /* icache `address sequence mode' */
+# define V850E2_CACHE_BTSC_DSEQ	0x0020 /* dcache `address sequence mode' */
+# define V850E2_CACHE_BTSC_IRFC	0x0030
+# define V850E2_CACHE_BTSC_ILCD	0x4000
+# define V850E2_CACHE_BTSC_VABE	0x8000
+#endif /* CONFIG_V850E2_V850E2S */
+
+/* Cache operation start address register (low-bits).  */
+#define V850E2_CACHE_CADL_ADDR	0xFFFFF074
+#define V850E2_CACHE_CADL 	(*(volatile u16 *)V850E2_CACHE_CADL_ADDR)
+/* Cache operation start address register (high-bits).  */
+#define V850E2_CACHE_CADH_ADDR	0xFFFFF076
+#define V850E2_CACHE_CADH 	(*(volatile u16 *)V850E2_CACHE_CADH_ADDR)
+/* Cache operation count register.  */
+#define V850E2_CACHE_CCNT_ADDR	0xFFFFF078
+#define V850E2_CACHE_CCNT 	(*(volatile u16 *)V850E2_CACHE_CCNT_ADDR)
+/* Cache operation specification register.  */
+#define V850E2_CACHE_COPR_ADDR	0xFFFFF07A
+#define V850E2_CACHE_COPR 	(*(volatile u16 *)V850E2_CACHE_COPR_ADDR)
+#define V850E2_CACHE_COPR_STRT	0x0001 /* start cache operation */
+#define V850E2_CACHE_COPR_LBSL	0x0100 /* 0 = icache, 1 = dcache */
+#define V850E2_CACHE_COPR_WSLE	0x0200 /* operate on cache way */
+#define V850E2_CACHE_COPR_WSL(way) ((way) * 0x0400) /* way select */
+#define V850E2_CACHE_COPR_CFC(op)  ((op)  * 0x1000) /* cache function code */
+
+
+/* Size of a cache line in bytes.  */
+#define V850E2_CACHE_LINE_SIZE_BITS	4
+#define V850E2_CACHE_LINE_SIZE		(1 << V850E2_CACHE_LINE_SIZE_BITS)
+
+/* The size of each cache `way' in lines.  */
+#define V850E2_CACHE_WAY_SIZE		256
+
+
+/* For <asm/cache.h> */
+#define L1_CACHE_BYTES			V850E2_CACHE_LINE_SIZE
+
+
+#endif /* __V850_V850E2_CACHE_H__ */
diff -Nru a/include/asm-v850/v850e_cache.h b/include/asm-v850/v850e_cache.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-v850/v850e_cache.h	Sat Jul 19 12:54:25 2003
@@ -0,0 +1,48 @@
+/*
+ * include/asm-v850/v850e_cache.h -- Cache control for V850E cache memories
+ *
+ *  Copyright (C) 2001,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+/* This file implements cache control for the rather simple cache used on
+   some V850E CPUs, specifically the NB85E/TEG CPU-core and the V850E/ME2
+   CPU.  V850E2 processors have their own (better) cache
+   implementation.  */
+
+#ifndef __V850_V850E_CACHE_H__
+#define __V850_V850E_CACHE_H__
+
+#include <asm/types.h>
+
+
+/* Cache control registers.  */
+#define V850E_CACHE_BHC_ADDR	0xFFFFF06A
+#define V850E_CACHE_BHC		(*(volatile u16 *)V850E_CACHE_BHC_ADDR)
+#define V850E_CACHE_ICC_ADDR	0xFFFFF070
+#define V850E_CACHE_ICC		(*(volatile u16 *)V850E_CACHE_ICC_ADDR)
+#define V850E_CACHE_ISI_ADDR	0xFFFFF072
+#define V850E_CACHE_ISI		(*(volatile u16 *)V850E_CACHE_ISI_ADDR)
+#define V850E_CACHE_DCC_ADDR	0xFFFFF078
+#define V850E_CACHE_DCC		(*(volatile u16 *)V850E_CACHE_DCC_ADDR)
+
+/* Size of a cache line in bytes.  */
+#define V850E_CACHE_LINE_SIZE	16
+
+/* For <asm/cache.h> */
+#define L1_CACHE_BYTES		V850E_CACHE_LINE_SIZE
+
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+/* Set caching params via the BHC, ICC, and DCC registers.  */
+void v850e_cache_enable (u16 bhc, u16 icc, u16 dcc);
+#endif /* __KERNEL__ && !__ASSEMBLY__ */
+
+
+#endif /* __V850_V850E_CACHE_H__ */
diff -Nru a/include/asm-v850/v850e_intc.h b/include/asm-v850/v850e_intc.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-v850/v850e_intc.h	Sat Jul 19 12:54:26 2003
@@ -0,0 +1,133 @@
+/*
+ * include/asm-v850/v850e_intc.h -- V850E CPU interrupt controller (INTC)
+ *
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#ifndef __V850_V850E_INTC_H__
+#define __V850_V850E_INTC_H__
+
+
+/* There are 4 16-bit `Interrupt Mask Registers' located contiguously
+   starting from this base.  Each interrupt uses a single bit to
+   indicated enabled/disabled status.  */
+#define V850E_INTC_IMR_BASE_ADDR  0xFFFFF100
+#define V850E_INTC_IMR_ADDR(irq)  (V850E_INTC_IMR_BASE_ADDR + ((irq) >> 3))
+#define V850E_INTC_IMR_BIT(irq)	  ((irq) & 0x7)
+
+/* Each maskable interrupt has a single-byte control register at this
+   address.  */
+#define V850E_INTC_IC_BASE_ADDR	  0xFFFFF110
+#define V850E_INTC_IC_ADDR(irq)	  (V850E_INTC_IC_BASE_ADDR + ((irq) << 1))
+#define V850E_INTC_IC(irq)	  (*(volatile u8 *)V850E_INTC_IC_ADDR(irq))
+/* Encode priority PR for storing in an interrupt control register.  */
+#define V850E_INTC_IC_PR(pr)	  (pr)
+/* Interrupt disable bit in an interrupt control register.  */
+#define V850E_INTC_IC_MK_BIT	  6
+#define V850E_INTC_IC_MK	  (1 << V850E_INTC_IC_MK_BIT)
+/* Interrupt pending flag in an interrupt control register.  */
+#define V850E_INTC_IC_IF_BIT	  7
+#define V850E_INTC_IC_IF	  (1 << V850E_INTC_IC_IF_BIT)
+
+/* The ISPR (In-service priority register) contains one bit for each interrupt
+   priority level, which is set to one when that level is currently being
+   serviced (and thus blocking any interrupts of equal or lesser level).  */
+#define V850E_INTC_ISPR_ADDR	  0xFFFFF1FA
+#define V850E_INTC_ISPR		  (*(volatile u8 *)V850E_INTC_ISPR_ADDR)
+
+
+#ifndef __ASSEMBLY__
+
+/* Enable interrupt handling for interrupt IRQ.  */
+static inline void v850e_intc_enable_irq (unsigned irq)
+{
+	__asm__ __volatile__ ("clr1 %0, [%1]"
+			      :: "r" (V850E_INTC_IMR_BIT (irq)),
+			         "r" (V850E_INTC_IMR_ADDR (irq))
+			      : "memory");
+}
+
+/* Disable interrupt handling for interrupt IRQ.  Note that any
+   interrupts received while disabled will be delivered once the
+   interrupt is enabled again, unless they are explicitly cleared using
+   `v850e_intc_clear_pending_irq'.  */
+static inline void v850e_intc_disable_irq (unsigned irq)
+{
+	__asm__ __volatile__ ("set1 %0, [%1]"
+			      :: "r" (V850E_INTC_IMR_BIT (irq)),
+			         "r" (V850E_INTC_IMR_ADDR (irq))
+			      : "memory");
+}
+
+/* Return true if interrupt handling for interrupt IRQ is enabled.  */
+static inline int v850e_intc_irq_enabled (unsigned irq)
+{
+	int rval;
+	__asm__ __volatile__ ("tst1 %1, [%2]; setf z, %0"
+			      : "=r" (rval)
+			      : "r" (V850E_INTC_IMR_BIT (irq)),
+			        "r" (V850E_INTC_IMR_ADDR (irq)));
+	return rval;
+}
+
+/* Disable irqs from 0 until LIMIT.  LIMIT must be a multiple of 8.  */
+static inline void _v850e_intc_disable_irqs (unsigned limit)
+{
+	unsigned long addr;
+	for (addr = V850E_INTC_IMR_BASE_ADDR; limit >= 8; addr++, limit -= 8)
+		*(char *)addr = 0xFF;
+}
+
+/* Disable all irqs.  This is purposely a macro, because NUM_MACH_IRQS
+   will be only be defined later.  */
+#define v850e_intc_disable_irqs()   _v850e_intc_disable_irqs (NUM_MACH_IRQS)
+
+/* Clear any pending interrupts for IRQ.  */
+static inline void v850e_intc_clear_pending_irq (unsigned irq)
+{
+	__asm__ __volatile__ ("clr1 %0, 0[%1]"
+			      :: "i" (V850E_INTC_IC_IF_BIT),
+			         "r" (V850E_INTC_IC_ADDR (irq))
+			      : "memory");
+}
+
+/* Return true if interrupt IRQ is pending (but disabled).  */
+static inline int v850e_intc_irq_pending (unsigned irq)
+{
+	int rval;
+	__asm__ __volatile__ ("tst1 %1, 0[%2]; setf nz, %0"
+			      : "=r" (rval)
+			      : "i" (V850E_INTC_IC_IF_BIT),
+			        "r" (V850E_INTC_IC_ADDR (irq)));
+	return rval;
+}
+
+
+struct v850e_intc_irq_init {
+	const char *name;	/* name of interrupt type */
+
+	/* Range of kernel irq numbers for this type:
+	   BASE, BASE+INTERVAL, ..., BASE+INTERVAL*NUM  */
+	unsigned base, num, interval;
+
+	unsigned priority;	/* interrupt priority to assign */
+};
+struct hw_interrupt_type;	/* fwd decl */
+
+/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array
+   INITS (which is terminated by an entry with the name field == 0).  */
+extern void v850e_intc_init_irq_types (struct v850e_intc_irq_init *inits,
+				       struct hw_interrupt_type *hw_irq_types);
+
+
+#endif /* !__ASSEMBLY__ */
+
+
+#endif /* __V850_V850E_INTC_H__ */
diff -Nru a/include/asm-v850/v850e_timer_c.h b/include/asm-v850/v850e_timer_c.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-v850/v850e_timer_c.h	Sat Jul 19 12:54:23 2003
@@ -0,0 +1,48 @@
+/*
+ * include/asm-v850/v850e_timer_c.h -- `Timer C' component often used
+ *	with the V850E cpu core
+ *
+ *  Copyright (C) 2001,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+/* NOTE: this include file currently contains only enough to allow us to
+   use timer C as an interrupt pass-through.  */
+
+#ifndef __V850_V850E_TIMER_C_H__
+#define __V850_V850E_TIMER_C_H__
+
+#include <asm/types.h>
+#include <asm/machdep.h>	/* Pick up chip-specific defs.  */
+
+
+/* Timer C (16-bit interval timers).  */
+
+/* Control register 0 for timer C.  */
+#define V850E_TIMER_C_TMCC0_ADDR(n) (V850E_TIMER_C_BASE_ADDR + 0x6 + 0x10 *(n))
+#define V850E_TIMER_C_TMCC0(n)	  (*(volatile u8 *)V850E_TIMER_C_TMCC0_ADDR(n))
+#define V850E_TIMER_C_TMCC0_CAE	  0x01 /* clock action enable */
+#define V850E_TIMER_C_TMCC0_CE	  0x02 /* count enable */
+/* ... */
+
+/* Control register 1 for timer C.  */
+#define V850E_TIMER_C_TMCC1_ADDR(n) (V850E_TIMER_C_BASE_ADDR + 0x8 + 0x10 *(n))
+#define V850E_TIMER_C_TMCC1(n)	  (*(volatile u8 *)V850E_TIMER_C_TMCC1_ADDR(n))
+#define V850E_TIMER_C_TMCC1_CMS0  0x01 /* capture/compare mode select (ccc0) */
+#define V850E_TIMER_C_TMCC1_CMS1  0x02 /* capture/compare mode select (ccc1) */
+/* ... */
+
+/* Interrupt edge-sensitivity control for timer C.  */
+#define V850E_TIMER_C_SESC_ADDR(n) (V850E_TIMER_C_BASE_ADDR + 0x9 + 0x10 *(n))
+#define V850E_TIMER_C_SESC(n)	  (*(volatile u8 *)V850E_TIMER_C_SESC_ADDR(n))
+
+/* ...etc... */
+
+
+#endif /* __V850_V850E_TIMER_C_H__  */
diff -Nru a/include/asm-v850/v850e_timer_d.h b/include/asm-v850/v850e_timer_d.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-v850/v850e_timer_d.h	Sat Jul 19 12:54:24 2003
@@ -0,0 +1,62 @@
+/*
+ * include/asm-v850/v850e_timer_d.h -- `Timer D' component often used
+ *	with the V850E cpu core
+ *
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#ifndef __V850_V850E_TIMER_D_H__
+#define __V850_V850E_TIMER_D_H__
+
+#include <asm/types.h>
+#include <asm/machdep.h>	/* Pick up chip-specific defs.  */
+
+
+/* Timer D (16-bit interval timers).  */
+
+/* Count registers for timer D.  */
+#define V850E_TIMER_D_TMD_ADDR(n) (V850E_TIMER_D_TMD_BASE_ADDR + 0x10 * (n))
+#define V850E_TIMER_D_TMD(n)	  (*(volatile u16 *)V850E_TIMER_D_TMD_ADDR(n))
+
+/* Count compare registers for timer D.  */
+#define V850E_TIMER_D_CMD_ADDR(n) (V850E_TIMER_D_CMD_BASE_ADDR + 0x10 * (n))
+#define V850E_TIMER_D_CMD(n)	  (*(volatile u16 *)V850E_TIMER_D_CMD_ADDR(n))
+
+/* Control registers for timer D.  */
+#define V850E_TIMER_D_TMCD_ADDR(n) (V850E_TIMER_D_TMCD_BASE_ADDR + 0x10 * (n))
+#define V850E_TIMER_D_TMCD(n)	   (*(volatile u8 *)V850E_TIMER_D_TMCD_ADDR(n))
+/* Control bits for timer D.  */
+#define V850E_TIMER_D_TMCD_CE  	   0x2 /* count enable */
+#define V850E_TIMER_D_TMCD_CAE	   0x1 /* clock action enable */
+/* Clock divider setting (log2).  */
+#define V850E_TIMER_D_TMCD_CS(divlog2) (((divlog2) - V850E_TIMER_D_TMCD_CS_MIN) << 4)
+/* Minimum clock divider setting (log2).  */
+#ifndef V850E_TIMER_D_TMCD_CS_MIN /* Can be overridden by mach-specific hdrs */
+#define V850E_TIMER_D_TMCD_CS_MIN  2 /* Default is correct for the v850e/ma1 */
+#endif
+/* Maximum clock divider setting (log2).  */
+#define V850E_TIMER_D_TMCD_CS_MAX  (V850E_TIMER_D_TMCD_CS_MIN + 7)
+
+/* Return the clock-divider (log2) of timer D unit N.  */
+#define V850E_TIMER_D_DIVLOG2(n) \
+  (((V850E_TIMER_D_TMCD(n) >> 4) & 0x7) + V850E_TIMER_D_TMCD_CS_MIN)
+
+
+#ifndef __ASSEMBLY__
+
+/* Start interval timer TIMER (0-3).  The timer will issue the
+   corresponding INTCMD interrupt RATE times per second.  This function
+   does not enable the interrupt.  */
+extern void v850e_timer_d_configure (unsigned timer, unsigned rate);
+
+#endif /* !__ASSEMBLY__ */
+
+
+#endif /* __V850_V850E_TIMER_D_H__  */
diff -Nru a/include/asm-v850/v850e_uart.h b/include/asm-v850/v850e_uart.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-v850/v850e_uart.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,77 @@
+/*
+ * include/asm-v850/v850e_uart.h -- common V850E on-chip UART driver
+ *
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+/* There's not actually a single UART implementation used by V850E CPUs,
+   but rather a series of implementations that are all `close' to one
+   another.  This file corresponds to the single driver which handles all
+   of them.  */
+
+#ifndef __V850_V850E_UART_H__
+#define __V850_V850E_UART_H__
+
+#include <linux/config.h>
+#include <linux/termios.h>
+
+#include <asm/v850e_utils.h>
+#include <asm/types.h>
+#include <asm/machdep.h>	/* Pick up chip-specific defs.  */
+
+
+/* Include model-specific definitions.  */
+#ifdef CONFIG_V850E_UART
+# ifdef CONFIG_V850E_UARTB
+#  include <asm-v850/v850e_uartb.h>
+# else
+#  include <asm-v850/v850e_uarta.h> /* original V850E UART */
+# endif
+#endif
+
+
+/* Optional capabilities some hardware provides.  */
+
+/* This UART doesn't implement RTS/CTS by default, but some platforms
+   implement them externally, so check to see if <asm/machdep.h> defined
+   anything.  */
+#ifdef V850E_UART_CTS
+#define v850e_uart_cts(n)		V850E_UART_CTS(n)
+#else
+#define v850e_uart_cts(n)		(1)
+#endif
+
+/* Do the same for RTS.  */
+#ifdef V850E_UART_SET_RTS
+#define v850e_uart_set_rts(n,v)		V850E_UART_SET_RTS(n,v)
+#else
+#define v850e_uart_set_rts(n,v)		((void)0)
+#endif
+
+
+/* This is the serial channel to use for the boot console (if desired).  */
+#ifndef V850E_UART_CONSOLE_CHANNEL
+# define V850E_UART_CONSOLE_CHANNEL 0
+#endif
+
+
+#ifndef __ASSEMBLY__
+
+/* Setup a console using channel 0 of the builtin uart.  */
+extern void v850e_uart_cons_init (unsigned chan);
+
+/* Configure and turn on uart channel CHAN, using the termios `control
+   modes' bits in CFLAGS, and a baud-rate of BAUD.  */
+void v850e_uart_configure (unsigned chan, unsigned cflags, unsigned baud);
+
+#endif /* !__ASSEMBLY__ */
+
+
+#endif /* __V850_V850E_UART_H__ */
diff -Nru a/include/asm-v850/v850e_uarta.h b/include/asm-v850/v850e_uarta.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-v850/v850e_uarta.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,278 @@
+/*
+ * include/asm-v850/v850e_uarta.h -- original V850E on-chip UART
+ *
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+/* This is the original V850E UART implementation is called just `UART' in
+   the docs, but we name this header file <asm/v850e_uarta.h> because the
+   name <asm/v850e_uart.h> is used for the common driver that handles both
+   `UART' and `UARTB' implementations.  */
+
+#ifndef __V850_V850E_UARTA_H__
+#define __V850_V850E_UARTA_H__
+
+
+/* Raw hardware interface.  */
+
+/* The base address of the UART control registers for channel N.
+   The default is the address used on the V850E/MA1.  */
+#ifndef V850E_UART_BASE_ADDR
+#define V850E_UART_BASE_ADDR(n)		(0xFFFFFA00 + 0x10 * (n))
+#endif 
+
+/* Addresses of specific UART control registers for channel N.
+   The defaults are the addresses used on the V850E/MA1; if a platform
+   wants to redefine any of these, it must redefine them all.  */
+#ifndef V850E_UART_ASIM_ADDR
+#define V850E_UART_ASIM_ADDR(n)		(V850E_UART_BASE_ADDR(n) + 0x0)
+#define V850E_UART_RXB_ADDR(n)		(V850E_UART_BASE_ADDR(n) + 0x2)
+#define V850E_UART_ASIS_ADDR(n)		(V850E_UART_BASE_ADDR(n) + 0x3)
+#define V850E_UART_TXB_ADDR(n)		(V850E_UART_BASE_ADDR(n) + 0x4)
+#define V850E_UART_ASIF_ADDR(n)		(V850E_UART_BASE_ADDR(n) + 0x5)
+#define V850E_UART_CKSR_ADDR(n)		(V850E_UART_BASE_ADDR(n) + 0x6)
+#define V850E_UART_BRGC_ADDR(n)		(V850E_UART_BASE_ADDR(n) + 0x7)
+#endif
+
+/* UART config registers.  */
+#define V850E_UART_ASIM(n)	(*(volatile u8 *)V850E_UART_ASIM_ADDR(n))
+/* Control bits for config registers.  */
+#define V850E_UART_ASIM_CAE	0x80 /* clock enable */
+#define V850E_UART_ASIM_TXE	0x40 /* transmit enable */
+#define V850E_UART_ASIM_RXE	0x20 /* receive enable */
+#define V850E_UART_ASIM_PS_MASK	0x18 /* mask covering parity-select bits */
+#define V850E_UART_ASIM_PS_NONE	0x00 /* no parity */
+#define V850E_UART_ASIM_PS_ZERO	0x08 /* zero parity */
+#define V850E_UART_ASIM_PS_ODD	0x10 /* odd parity */
+#define V850E_UART_ASIM_PS_EVEN	0x18 /* even parity */
+#define V850E_UART_ASIM_CL_8	0x04 /* char len is 8 bits (otherwise, 7) */
+#define V850E_UART_ASIM_SL_2	0x02 /* 2 stop bits (otherwise, 1) */
+#define V850E_UART_ASIM_ISRM	0x01 /* generate INTSR interrupt on errors
+					(otherwise, generate INTSER) */
+
+/* UART serial interface status registers.  */
+#define V850E_UART_ASIS(n)	(*(volatile u8 *)V850E_UART_ASIS_ADDR(n))
+/* Control bits for status registers.  */
+#define V850E_UART_ASIS_PE	0x04 /* parity error */
+#define V850E_UART_ASIS_FE	0x02 /* framing error */
+#define V850E_UART_ASIS_OVE	0x01 /* overrun error */
+
+/* UART serial interface transmission status registers.  */
+#define V850E_UART_ASIF(n)	(*(volatile u8 *)V850E_UART_ASIF_ADDR(n))
+#define V850E_UART_ASIF_TXBF	0x02 /* transmit buffer flag (data in TXB) */
+#define V850E_UART_ASIF_TXSF	0x01 /* transmit shift flag (sending data) */
+
+/* UART receive buffer register.  */
+#define V850E_UART_RXB(n)	(*(volatile u8 *)V850E_UART_RXB_ADDR(n))
+
+/* UART transmit buffer register.  */
+#define V850E_UART_TXB(n)	(*(volatile u8 *)V850E_UART_TXB_ADDR(n))
+
+/* UART baud-rate generator control registers.  */
+#define V850E_UART_CKSR(n)	(*(volatile u8 *)V850E_UART_CKSR_ADDR(n))
+#define V850E_UART_CKSR_MAX	11
+#define V850E_UART_BRGC(n)	(*(volatile u8 *)V850E_UART_BRGC_ADDR(n))
+#define V850E_UART_BRGC_MIN	8
+
+
+#ifndef V850E_UART_CKSR_MAX_FREQ
+#define V850E_UART_CKSR_MAX_FREQ (25*1000*1000)
+#endif
+
+/* Calculate the minimum value for CKSR on this processor.  */
+static inline unsigned v850e_uart_cksr_min (void)
+{
+	int min = 0;
+	unsigned freq = V850E_UART_BASE_FREQ;
+	while (freq > V850E_UART_CKSR_MAX_FREQ) {
+		freq >>= 1;
+		min++;
+	}
+	return min;
+}
+
+
+/* Slightly abstract interface used by driver.  */
+
+
+/* Interrupts used by the UART.  */
+
+/* Received when the most recently transmitted character has been sent.  */
+#define V850E_UART_TX_IRQ(chan)		IRQ_INTST (chan)
+/* Received when a new character has been received.  */
+#define V850E_UART_RX_IRQ(chan)		IRQ_INTSR (chan)
+
+
+/* UART clock generator interface.  */
+
+/* This type encapsulates a particular uart frequency.  */
+typedef struct {
+	unsigned clk_divlog2;
+	unsigned brgen_count;
+} v850e_uart_speed_t;
+
+/* Calculate a uart speed from BAUD for this uart.  */
+static inline v850e_uart_speed_t v850e_uart_calc_speed (unsigned baud)
+{
+	v850e_uart_speed_t speed;
+
+	/* Calculate the log2 clock divider and baud-rate counter values
+	   (note that the UART divides the resulting clock by 2, so
+	   multiply BAUD by 2 here to compensate).  */
+	calc_counter_params (V850E_UART_BASE_FREQ, baud * 2,
+			     v850e_uart_cksr_min(),
+			     V850E_UART_CKSR_MAX, 8/*bits*/,
+			     &speed.clk_divlog2, &speed.brgen_count);
+
+	return speed;
+}
+
+/* Return the current speed of uart channel CHAN.  */
+static inline v850e_uart_speed_t v850e_uart_speed (unsigned chan)
+{
+	v850e_uart_speed_t speed;
+	speed.clk_divlog2 = V850E_UART_CKSR (chan);
+	speed.brgen_count = V850E_UART_BRGC (chan);
+	return speed;
+}
+
+/* Set the current speed of uart channel CHAN.  */
+static inline void v850e_uart_set_speed(unsigned chan,v850e_uart_speed_t speed)
+{
+	V850E_UART_CKSR (chan) = speed.clk_divlog2;
+	V850E_UART_BRGC (chan) = speed.brgen_count;
+}
+
+static inline int
+v850e_uart_speed_eq (v850e_uart_speed_t speed1, v850e_uart_speed_t speed2)
+{
+	return speed1.clk_divlog2 == speed2.clk_divlog2
+		&& speed1.brgen_count == speed2.brgen_count;
+}
+
+/* Minimum baud rate possible.  */
+#define v850e_uart_min_baud() \
+   ((V850E_UART_BASE_FREQ >> V850E_UART_CKSR_MAX) / (2 * 255) + 1)
+
+/* Maximum baud rate possible.  The error is quite high at max, though.  */
+#define v850e_uart_max_baud() \
+   ((V850E_UART_BASE_FREQ >> v850e_uart_cksr_min()) / (2 *V850E_UART_BRGC_MIN))
+
+/* The `maximum' clock rate the uart can used, which is wanted (though not
+   really used in any useful way) by the serial framework.  */
+#define v850e_uart_max_clock() \
+   ((V850E_UART_BASE_FREQ >> v850e_uart_cksr_min()) / 2)
+
+
+/* UART configuration interface.  */
+
+/* Type of the uart config register; must be a scalar.  */
+typedef u16 v850e_uart_config_t;
+
+/* The uart hardware config register for channel CHAN.  */
+#define V850E_UART_CONFIG(chan)		V850E_UART_ASIM (chan)
+
+/* This config bit set if the uart is enabled.  */
+#define V850E_UART_CONFIG_ENABLED	V850E_UART_ASIM_CAE
+/* If the uart _isn't_ enabled, store this value to it to do so.  */
+#define V850E_UART_CONFIG_INIT		V850E_UART_ASIM_CAE
+/* Store this config value to disable the uart channel completely.  */
+#define V850E_UART_CONFIG_FINI		0
+
+/* Setting/clearing these bits enable/disable TX/RX, respectively (but
+   otherwise generally leave things running).  */
+#define V850E_UART_CONFIG_RX_ENABLE	V850E_UART_ASIM_RXE
+#define V850E_UART_CONFIG_TX_ENABLE	V850E_UART_ASIM_TXE
+
+/* These masks define which config bits affect TX/RX modes, respectively.  */
+#define V850E_UART_CONFIG_RX_BITS \
+  (V850E_UART_ASIM_PS_MASK | V850E_UART_ASIM_CL_8 | V850E_UART_ASIM_ISRM)
+#define V850E_UART_CONFIG_TX_BITS \
+  (V850E_UART_ASIM_PS_MASK | V850E_UART_ASIM_CL_8 | V850E_UART_ASIM_SL_2)
+
+static inline v850e_uart_config_t v850e_uart_calc_config (unsigned cflags)
+{
+	v850e_uart_config_t config = 0;
+
+	/* Figure out new configuration of control register.  */
+	if (cflags & CSTOPB)
+		/* Number of stop bits, 1 or 2.  */
+		config |= V850E_UART_ASIM_SL_2;
+	if ((cflags & CSIZE) == CS8)
+		/* Number of data bits, 7 or 8.  */
+		config |= V850E_UART_ASIM_CL_8;
+	if (! (cflags & PARENB))
+		/* No parity check/generation.  */
+		config |= V850E_UART_ASIM_PS_NONE;
+	else if (cflags & PARODD)
+		/* Odd parity check/generation.  */
+		config |= V850E_UART_ASIM_PS_ODD;
+	else
+		/* Even parity check/generation.  */
+		config |= V850E_UART_ASIM_PS_EVEN;
+	if (cflags & CREAD)
+		/* Reading enabled.  */
+		config |= V850E_UART_ASIM_RXE;
+
+	config |= V850E_UART_ASIM_CAE;
+	config |= V850E_UART_ASIM_TXE; /* Writing is always enabled.  */
+	config |= V850E_UART_ASIM_ISRM; /* Errors generate a read-irq.  */
+
+	return config;
+}
+
+/* This should delay as long as necessary for a recently written config
+   setting to settle, before we turn the uart back on.  */
+static inline void
+v850e_uart_config_delay (v850e_uart_config_t config, v850e_uart_speed_t speed)
+{
+	/* The UART may not be reset properly unless we wait at least 2
+	   `basic-clocks' until turning on the TXE/RXE bits again.
+	   A `basic clock' is the clock used by the baud-rate generator,
+	   i.e., the cpu clock divided by the 2^new_clk_divlog2.
+	   The loop takes 2 insns, so loop CYCLES / 2 times.  */
+	register unsigned count = 1 << speed.clk_divlog2;
+	while (--count != 0)
+		/* nothing */;
+}
+
+
+/* RX/TX interface.  */
+
+/* Return true if all characters awaiting transmission on uart channel N
+   have been transmitted.  */
+#define v850e_uart_xmit_done(n)						      \
+   (! (V850E_UART_ASIF(n) & V850E_UART_ASIF_TXBF))
+/* Wait for this to be true.  */
+#define v850e_uart_wait_for_xmit_done(n)				      \
+   do { } while (! v850e_uart_xmit_done (n))
+
+/* Return true if uart channel N is ready to transmit a character.  */
+#define v850e_uart_xmit_ok(n)						      \
+   (v850e_uart_xmit_done(n) && v850e_uart_cts(n))
+/* Wait for this to be true.  */
+#define v850e_uart_wait_for_xmit_ok(n)					      \
+   do { } while (! v850e_uart_xmit_ok (n))
+
+/* Write character CH to uart channel CHAN.  */
+#define v850e_uart_putc(chan, ch)	(V850E_UART_TXB(chan) = (ch))
+
+/* Return latest character read on channel CHAN.  */
+#define v850e_uart_getc(chan)		V850E_UART_RXB (chan)
+
+/* Return bit-mask of uart error status.  */
+#define v850e_uart_err(chan)		V850E_UART_ASIS (chan)
+/* Various error bits set in the error result.  */
+#define V850E_UART_ERR_OVERRUN		V850E_UART_ASIS_OVE
+#define V850E_UART_ERR_FRAME		V850E_UART_ASIS_FE
+#define V850E_UART_ERR_PARITY		V850E_UART_ASIS_PE
+
+
+#endif /* __V850_V850E_UARTA_H__ */
diff -Nru a/include/asm-v850/v850e_uartb.h b/include/asm-v850/v850e_uartb.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-v850/v850e_uartb.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,262 @@
+/*
+ * include/asm-v850/v850e_uartb.h -- V850E on-chip `UARTB' UART
+ *
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+/* The V850E UARTB is basically a superset of the original V850E UART, but
+   even where it's the same, the names and details have changed a bit.
+   It's similar enough to use the same driver (v850e_uart.c), but the
+   details have been abstracted slightly to do so.  */
+
+#ifndef __V850_V850E_UARTB_H__
+#define __V850_V850E_UARTB_H__
+
+
+/* Raw hardware interface.  */
+
+#define V850E_UARTB_BASE_ADDR(n)	(0xFFFFFA00 + 0x10 * (n))
+
+/* Addresses of specific UART control registers for channel N.  */
+#define V850E_UARTB_CTL0_ADDR(n)	(V850E_UARTB_BASE_ADDR(n) + 0x0)
+#define V850E_UARTB_CTL2_ADDR(n)	(V850E_UARTB_BASE_ADDR(n) + 0x2)
+#define V850E_UARTB_STR_ADDR(n)		(V850E_UARTB_BASE_ADDR(n) + 0x4)
+#define V850E_UARTB_RX_ADDR(n)		(V850E_UARTB_BASE_ADDR(n) + 0x6)
+#define V850E_UARTB_RXAP_ADDR(n)	(V850E_UARTB_BASE_ADDR(n) + 0x6)
+#define V850E_UARTB_TX_ADDR(n)		(V850E_UARTB_BASE_ADDR(n) + 0x8)
+#define V850E_UARTB_FIC0_ADDR(n)	(V850E_UARTB_BASE_ADDR(n) + 0xA)
+#define V850E_UARTB_FIC1_ADDR(n)	(V850E_UARTB_BASE_ADDR(n) + 0xB)
+#define V850E_UARTB_FIC2_ADDR(n)	(V850E_UARTB_BASE_ADDR(n) + 0xC)
+#define V850E_UARTB_FIS0_ADDR(n)	(V850E_UARTB_BASE_ADDR(n) + 0xE)
+#define V850E_UARTB_FIS1_ADDR(n)	(V850E_UARTB_BASE_ADDR(n) + 0xF)
+
+/* UARTB control register 0 (general config).  */
+#define V850E_UARTB_CTL0(n)	(*(volatile u8 *)V850E_UARTB_CTL0_ADDR(n))
+/* Control bits for config registers.  */
+#define V850E_UARTB_CTL0_PWR		0x80	/* clock enable */
+#define V850E_UARTB_CTL0_TXE		0x40	/* transmit enable */
+#define V850E_UARTB_CTL0_RXE		0x20	/* receive enable */
+#define V850E_UARTB_CTL0_DIR		0x10	/*  */
+#define V850E_UARTB_CTL0_PS1		0x08	/* parity */
+#define V850E_UARTB_CTL0_PS0		0x04	/* parity */
+#define V850E_UARTB_CTL0_CL		0x02	/* char len 1:8bit, 0:7bit */
+#define V850E_UARTB_CTL0_SL		0x01	/* stop bit 1:2bit, 0:1bit */
+#define V850E_UARTB_CTL0_PS_MASK	0x0C	/* mask covering parity bits */
+#define V850E_UARTB_CTL0_PS_NONE	0x00	/* no parity */
+#define V850E_UARTB_CTL0_PS_ZERO	0x04	/* zero parity */
+#define V850E_UARTB_CTL0_PS_ODD		0x08	/* odd parity */
+#define V850E_UARTB_CTL0_PS_EVEN	0x0C	/* even parity */
+#define V850E_UARTB_CTL0_CL_8		0x02	/* char len 1:8bit, 0:7bit */
+#define V850E_UARTB_CTL0_SL_2		0x01	/* stop bit 1:2bit, 0:1bit */
+
+/* UARTB control register 2 (clock divider).  */
+#define V850E_UARTB_CTL2(n)	(*(volatile u16 *)V850E_UARTB_CTL2_ADDR(n))
+#define V850E_UARTB_CTL2_MIN	4
+#define V850E_UARTB_CTL2_MAX	0xFFFF
+
+/* UARTB serial interface status register.  */
+#define V850E_UARTB_STR(n)	(*(volatile u8 *)V850E_UARTB_STR_ADDR(n))
+/* Control bits for status registers.  */
+#define V850E_UARTB_STR_TSF	0x80	/* UBTX or FIFO exist data  */
+#define V850E_UARTB_STR_OVF	0x08	/* overflow error */
+#define V850E_UARTB_STR_PE	0x04	/* parity error */
+#define V850E_UARTB_STR_FE	0x02	/* framing error */
+#define V850E_UARTB_STR_OVE	0x01	/* overrun error */
+
+/* UARTB receive data register.  */
+#define V850E_UARTB_RX(n)	(*(volatile u8 *)V850E_UARTB_RX_ADDR(n))
+#define V850E_UARTB_RXAP(n)	(*(volatile u16 *)V850E_UARTB_RXAP_ADDR(n))
+/* Control bits for status registers.  */
+#define V850E_UARTB_RXAP_PEF	0x0200 /* parity error */
+#define V850E_UARTB_RXAP_FEF	0x0100 /* framing error */
+
+/* UARTB transmit data register.  */
+#define V850E_UARTB_TX(n)	(*(volatile u8 *)V850E_UARTB_TX_ADDR(n))
+
+/* UARTB FIFO control register 0.  */
+#define V850E_UARTB_FIC0(n)	(*(volatile u8 *)V850E_UARTB_FIC0_ADDR(n))
+
+/* UARTB FIFO control register 1.  */
+#define V850E_UARTB_FIC1(n)	(*(volatile u8 *)V850E_UARTB_FIC1_ADDR(n))
+
+/* UARTB FIFO control register 2.  */
+#define V850E_UARTB_FIC2(n)	(*(volatile u16 *)V850E_UARTB_FIC2_ADDR(n))
+
+/* UARTB FIFO status register 0.  */
+#define V850E_UARTB_FIS0(n)	(*(volatile u8 *)V850E_UARTB_FIS0_ADDR(n))
+
+/* UARTB FIFO status register 1.  */
+#define V850E_UARTB_FIS1(n)	(*(volatile u8 *)V850E_UARTB_FIS1_ADDR(n))
+
+
+/* Slightly abstract interface used by driver.  */
+
+
+/* Interrupts used by the UART.  */
+
+/* Received when the most recently transmitted character has been sent.  */
+#define V850E_UART_TX_IRQ(chan)		IRQ_INTUBTIT (chan)
+/* Received when a new character has been received.  */
+#define V850E_UART_RX_IRQ(chan)		IRQ_INTUBTIR (chan)
+
+/* Use by serial driver for information purposes.  */
+#define V850E_UART_BASE_ADDR(chan)	V850E_UARTB_BASE_ADDR(chan)
+
+
+/* UART clock generator interface.  */
+
+/* This type encapsulates a particular uart frequency.  */
+typedef u16 v850e_uart_speed_t;
+
+/* Calculate a uart speed from BAUD for this uart.  */
+static inline v850e_uart_speed_t v850e_uart_calc_speed (unsigned baud)
+{
+	v850e_uart_speed_t speed;
+
+	/*
+	 * V850E/ME2 UARTB baud rate is determined by the value of UBCTL2
+	 * fx = V850E_UARTB_BASE_FREQ = CPU_CLOCK_FREQ/4
+	 * baud = fx / 2*speed   [ speed >= 4 ]
+	 */
+	speed = V850E_UARTB_CTL2_MIN;
+	while (((V850E_UARTB_BASE_FREQ / 2) / speed ) > baud)
+		speed++;
+
+	return speed;
+}
+
+/* Return the current speed of uart channel CHAN.  */
+#define v850e_uart_speed(chan)		    V850E_UARTB_CTL2 (chan)
+
+/* Set the current speed of uart channel CHAN.  */
+#define v850e_uart_set_speed(chan, speed)   (V850E_UARTB_CTL2 (chan) = (speed))
+
+/* Return true if SPEED1 and SPEED2 are the same.  */
+#define v850e_uart_speed_eq(speed1, speed2) ((speed1) == (speed2))
+
+/* Minimum baud rate possible.  */
+#define v850e_uart_min_baud() \
+   ((V850E_UARTB_BASE_FREQ / 2) / V850E_UARTB_CTL2_MAX)
+
+/* Maximum baud rate possible.  The error is quite high at max, though.  */
+#define v850e_uart_max_baud() \
+   ((V850E_UARTB_BASE_FREQ / 2) / V850E_UARTB_CTL2_MIN)
+
+/* The `maximum' clock rate the uart can used, which is wanted (though not
+   really used in any useful way) by the serial framework.  */
+#define v850e_uart_max_clock() \
+   (V850E_UARTB_BASE_FREQ / 2)
+
+
+/* UART configuration interface.  */
+
+/* Type of the uart config register; must be a scalar.  */
+typedef u16 v850e_uart_config_t;
+
+/* The uart hardware config register for channel CHAN.  */
+#define V850E_UART_CONFIG(chan)		V850E_UARTB_CTL0 (chan)
+
+/* This config bit set if the uart is enabled.  */
+#define V850E_UART_CONFIG_ENABLED	V850E_UARTB_CTL0_PWR
+/* If the uart _isn't_ enabled, store this value to it to do so.  */
+#define V850E_UART_CONFIG_INIT		V850E_UARTB_CTL0_PWR
+/* Store this config value to disable the uart channel completely.  */
+#define V850E_UART_CONFIG_FINI		0
+
+/* Setting/clearing these bits enable/disable TX/RX, respectively (but
+   otherwise generally leave things running).  */
+#define V850E_UART_CONFIG_RX_ENABLE	V850E_UARTB_CTL0_RXE
+#define V850E_UART_CONFIG_TX_ENABLE	V850E_UARTB_CTL0_TXE
+
+/* These masks define which config bits affect TX/RX modes, respectively.  */
+#define V850E_UART_CONFIG_RX_BITS \
+  (V850E_UARTB_CTL0_PS_MASK | V850E_UARTB_CTL0_CL_8)
+#define V850E_UART_CONFIG_TX_BITS \
+  (V850E_UARTB_CTL0_PS_MASK | V850E_UARTB_CTL0_CL_8 | V850E_UARTB_CTL0_SL_2)
+
+static inline v850e_uart_config_t v850e_uart_calc_config (unsigned cflags)
+{
+	v850e_uart_config_t config = 0;
+
+	/* Figure out new configuration of control register.  */
+	if (cflags & CSTOPB)
+		/* Number of stop bits, 1 or 2.  */
+		config |= V850E_UARTB_CTL0_SL_2;
+	if ((cflags & CSIZE) == CS8)
+		/* Number of data bits, 7 or 8.  */
+		config |= V850E_UARTB_CTL0_CL_8;
+	if (! (cflags & PARENB))
+		/* No parity check/generation.  */
+		config |= V850E_UARTB_CTL0_PS_NONE;
+	else if (cflags & PARODD)
+		/* Odd parity check/generation.  */
+		config |= V850E_UARTB_CTL0_PS_ODD;
+	else
+		/* Even parity check/generation.  */
+		config |= V850E_UARTB_CTL0_PS_EVEN;
+	if (cflags & CREAD)
+		/* Reading enabled.  */
+		config |= V850E_UARTB_CTL0_RXE;
+
+	config |= V850E_UARTB_CTL0_PWR;
+	config |= V850E_UARTB_CTL0_TXE; /* Writing is always enabled.  */
+	config |= V850E_UARTB_CTL0_DIR; /* LSB first.  */
+
+	return config;
+}
+
+/* This should delay as long as necessary for a recently written config
+   setting to settle, before we turn the uart back on.  */
+static inline void
+v850e_uart_config_delay (v850e_uart_config_t config, v850e_uart_speed_t speed)
+{
+	/* The UART may not be reset properly unless we wait at least 2
+	   `basic-clocks' until turning on the TXE/RXE bits again.
+	   A `basic clock' is the clock used by the baud-rate generator,
+	   i.e., the cpu clock divided by the 2^new_clk_divlog2.
+	   The loop takes 2 insns, so loop CYCLES / 2 times.  */
+	register unsigned count = 1 << speed;
+	while (--count != 0)
+		/* nothing */;
+}
+
+
+/* RX/TX interface.  */
+
+/* Return true if all characters awaiting transmission on uart channel N
+   have been transmitted.  */
+#define v850e_uart_xmit_done(n)						      \
+   (! (V850E_UARTB_STR(n) & V850E_UARTB_STR_TSF))
+/* Wait for this to be true.  */
+#define v850e_uart_wait_for_xmit_done(n)				      \
+   do { } while (! v850e_uart_xmit_done (n))
+
+/* Return true if uart channel N is ready to transmit a character.  */
+#define v850e_uart_xmit_ok(n)						      \
+   (v850e_uart_xmit_done(n) && v850e_uart_cts(n))
+/* Wait for this to be true.  */
+#define v850e_uart_wait_for_xmit_ok(n)					      \
+   do { } while (! v850e_uart_xmit_ok (n))
+
+/* Write character CH to uart channel CHAN.  */
+#define v850e_uart_putc(chan, ch)	(V850E_UARTB_TX(chan) = (ch))
+
+/* Return latest character read on channel CHAN.  */
+#define v850e_uart_getc(chan)		V850E_UARTB_RX (chan)
+
+/* Return bit-mask of uart error status.  */
+#define v850e_uart_err(chan)		V850E_UARTB_STR (chan)
+/* Various error bits set in the error result.  */
+#define V850E_UART_ERR_OVERRUN		V850E_UARTB_STR_OVE
+#define V850E_UART_ERR_FRAME		V850E_UARTB_STR_FE
+#define V850E_UART_ERR_PARITY		V850E_UARTB_STR_PE
+
+
+#endif /* __V850_V850E_UARTB_H__ */
diff -Nru a/include/asm-v850/v850e_utils.h b/include/asm-v850/v850e_utils.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/asm-v850/v850e_utils.h	Sat Jul 19 12:54:25 2003
@@ -0,0 +1,35 @@
+/*
+ * include/asm-v850/v850e_utils.h -- Utility functions associated with
+ *	V850E CPUs
+ *
+ *  Copyright (C) 2001,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,03  Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ */
+
+#ifndef __V850_V850E_UTILS_H__
+#define __V850_V850E_UTILS_H__
+
+/* Calculate counter clock-divider and count values to attain the
+   desired frequency RATE from the base frequency BASE_FREQ.  The
+   counter is expected to have a clock-divider, which can divide the
+   system cpu clock by a power of two value from MIN_DIVLOG2 to
+   MAX_DIV_LOG2, and a word-size of COUNTER_SIZE bits (the counter
+   counts up and resets whenever it's equal to the compare register,
+   generating an interrupt or whatever when it does so).  The returned
+   values are: *DIVLOG2 -- log2 of the desired clock divider and *COUNT
+   -- the counter compare value to use.  Returns true if it was possible
+   to find a reasonable value, otherwise false (and the other return
+   values will be set to be as good as possible).  */
+extern int calc_counter_params (unsigned long base_freq,
+				unsigned long rate,
+				unsigned min_divlog2, unsigned max_divlog2,
+				unsigned counter_size,
+				unsigned *divlog2, unsigned *count);
+
+#endif /* __V850_V850E_UTILS_H__ */
diff -Nru a/include/linux/atmdev.h b/include/linux/atmdev.h
--- a/include/linux/atmdev.h	Sat Jul 19 12:54:27 2003
+++ b/include/linux/atmdev.h	Sat Jul 19 12:54:27 2003
@@ -252,6 +252,7 @@
 	ATM_VF_SESSION,		/* VCC is p2mp session control descriptor */
 	ATM_VF_HASSAP,		/* SAP has been set */
 	ATM_VF_CLOSE,		/* asynchronous close - treat like VF_RELEASED*/
+	ATM_VF_WAITING,		/* waiting for reply from sigd */
 };
 
 
@@ -291,14 +292,11 @@
 	void		*dev_data;	/* per-device data */
 	void		*proto_data;	/* per-protocol data */
 	struct k_atm_aal_stats *stats;	/* pointer to AAL stats group */
-	wait_queue_head_t sleep;	/* if socket is busy */
 	struct sock	*sk;		/* socket backpointer */
 	/* SVC part --- may move later ------------------------------------- */
 	short		itf;		/* interface number */
 	struct sockaddr_atmsvc local;
 	struct sockaddr_atmsvc remote;
-	void (*callback)(struct atm_vcc *vcc);
-	int		reply;		/* also used by ATMTCP */
 	/* Multipoint part ------------------------------------------------- */
 	struct atm_vcc	*session;	/* session VCC descriptor */
 	/* Other stuff ----------------------------------------------------- */
diff -Nru a/include/linux/blk.h b/include/linux/blk.h
--- a/include/linux/blk.h	Sat Jul 19 12:54:27 2003
+++ b/include/linux/blk.h	Sat Jul 19 12:54:27 2003
@@ -1,2 +1,2 @@
-/* this file is obsolete, please use <linux/blkdev.h> instead */
+#warning this file is obsolete, please use <linux/blkdev.h> instead
 #include <linux/blkdev.h>
diff -Nru a/include/linux/blkdev.h b/include/linux/blkdev.h
--- a/include/linux/blkdev.h	Sat Jul 19 12:54:23 2003
+++ b/include/linux/blkdev.h	Sat Jul 19 12:54:23 2003
@@ -44,9 +44,9 @@
 	unsigned long ttime_samples;
 	unsigned long ttime_mean;
 	/* Layout pattern */
-	long seek_samples;
+	unsigned int seek_samples;
 	sector_t last_request_pos;
-	sector_t seek_total;
+	u64 seek_total;
 	sector_t seek_mean;
 };
 
@@ -491,6 +491,7 @@
 extern struct request *blk_get_request(request_queue_t *, int, int);
 extern void blk_put_request(struct request *);
 extern void blk_insert_request(request_queue_t *, struct request *, int, void *);
+extern void blk_requeue_request(request_queue_t *, struct request *);
 extern void blk_plug_device(request_queue_t *);
 extern int blk_remove_plug(request_queue_t *);
 extern void blk_recount_segments(request_queue_t *, struct bio *);
diff -Nru a/include/linux/dm-ioctl-v1.h b/include/linux/dm-ioctl-v1.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/dm-ioctl-v1.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
+ *
+ * This file is released under the LGPL.
+ */
+
+#ifndef _LINUX_DM_IOCTL_V1_H
+#define _LINUX_DM_IOCTL_V1_H
+
+#include <linux/types.h>
+
+#define DM_DIR "mapper"	/* Slashes not supported */
+#define DM_MAX_TYPE_NAME 16
+#define DM_NAME_LEN 128
+#define DM_UUID_LEN 129
+
+/*
+ * Implements a traditional ioctl interface to the device mapper.
+ */
+
+/*
+ * All ioctl arguments consist of a single chunk of memory, with
+ * this structure at the start.  If a uuid is specified any
+ * lookup (eg. for a DM_INFO) will be done on that, *not* the
+ * name.
+ */
+struct dm_ioctl {
+	/*
+	 * The version number is made up of three parts:
+	 * major - no backward or forward compatibility,
+	 * minor - only backwards compatible,
+	 * patch - both backwards and forwards compatible.
+	 *
+	 * All clients of the ioctl interface should fill in the
+	 * version number of the interface that they were
+	 * compiled with.
+	 *
+	 * All recognised ioctl commands (ie. those that don't
+	 * return -ENOTTY) fill out this field, even if the
+	 * command failed.
+	 */
+	uint32_t version[3];	/* in/out */
+	uint32_t data_size;	/* total size of data passed in
+				 * including this struct */
+
+	uint32_t data_start;	/* offset to start of data
+				 * relative to start of this struct */
+
+	uint32_t target_count;	/* in/out */
+	uint32_t open_count;	/* out */
+	uint32_t flags;		/* in/out */
+
+	__kernel_dev_t dev;	/* in/out */
+
+	char name[DM_NAME_LEN];	/* device name */
+	char uuid[DM_UUID_LEN];	/* unique identifier for
+				 * the block device */
+};
+
+/*
+ * Used to specify tables.  These structures appear after the
+ * dm_ioctl.
+ */
+struct dm_target_spec {
+	int32_t status;		/* used when reading from kernel only */
+	uint64_t sector_start;
+	uint32_t length;
+
+	/*
+	 * Offset in bytes (from the start of this struct) to
+	 * next target_spec.
+	 */
+	uint32_t next;
+
+	char target_type[DM_MAX_TYPE_NAME];
+
+	/*
+	 * Parameter string starts immediately after this object.
+	 * Be careful to add padding after string to ensure correct
+	 * alignment of subsequent dm_target_spec.
+	 */
+};
+
+/*
+ * Used to retrieve the target dependencies.
+ */
+struct dm_target_deps {
+	uint32_t count;
+
+	__kernel_dev_t dev[0];	/* out */
+};
+
+/*
+ * If you change this make sure you make the corresponding change
+ * to dm-ioctl.c:lookup_ioctl()
+ */
+enum {
+	/* Top level cmds */
+	DM_VERSION_CMD = 0,
+	DM_REMOVE_ALL_CMD,
+
+	/* device level cmds */
+	DM_DEV_CREATE_CMD,
+	DM_DEV_REMOVE_CMD,
+	DM_DEV_RELOAD_CMD,
+	DM_DEV_RENAME_CMD,
+	DM_DEV_SUSPEND_CMD,
+	DM_DEV_DEPS_CMD,
+	DM_DEV_STATUS_CMD,
+
+	/* target level cmds */
+	DM_TARGET_STATUS_CMD,
+	DM_TARGET_WAIT_CMD
+};
+
+#define DM_IOCTL 0xfd
+
+#define DM_VERSION       _IOWR(DM_IOCTL, DM_VERSION_CMD, struct dm_ioctl)
+#define DM_REMOVE_ALL    _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD, struct dm_ioctl)
+
+#define DM_DEV_CREATE    _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD, struct dm_ioctl)
+#define DM_DEV_REMOVE    _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD, struct dm_ioctl)
+#define DM_DEV_RELOAD    _IOWR(DM_IOCTL, DM_DEV_RELOAD_CMD, struct dm_ioctl)
+#define DM_DEV_SUSPEND   _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl)
+#define DM_DEV_RENAME    _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD, struct dm_ioctl)
+#define DM_DEV_DEPS      _IOWR(DM_IOCTL, DM_DEV_DEPS_CMD, struct dm_ioctl)
+#define DM_DEV_STATUS    _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl)
+
+#define DM_TARGET_STATUS _IOWR(DM_IOCTL, DM_TARGET_STATUS_CMD, struct dm_ioctl)
+#define DM_TARGET_WAIT   _IOWR(DM_IOCTL, DM_TARGET_WAIT_CMD, struct dm_ioctl)
+
+#define DM_VERSION_MAJOR	1
+#define DM_VERSION_MINOR	0
+#define DM_VERSION_PATCHLEVEL	6
+#define DM_VERSION_EXTRA	"-ioctl (2002-10-15)"
+
+/* Status bits */
+#define DM_READONLY_FLAG	0x00000001
+#define DM_SUSPEND_FLAG		0x00000002
+#define DM_EXISTS_FLAG		0x00000004
+#define DM_PERSISTENT_DEV_FLAG	0x00000008
+
+/*
+ * Flag passed into ioctl STATUS command to get table information
+ * rather than current status.
+ */
+#define DM_STATUS_TABLE_FLAG	0x00000010
+
+#endif				/* _LINUX_DM_IOCTL_H */
diff -Nru a/include/linux/dm-ioctl-v4.h b/include/linux/dm-ioctl-v4.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/include/linux/dm-ioctl-v4.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2001 - 2003 Sistina Software (UK) Limited.
+ *
+ * This file is released under the LGPL.
+ */
+
+#ifndef _LINUX_DM_IOCTL_V4_H
+#define _LINUX_DM_IOCTL_V4_H
+
+#include <linux/types.h>
+
+#define DM_DIR "mapper"		/* Slashes not supported */
+#define DM_MAX_TYPE_NAME 16
+#define DM_NAME_LEN 128
+#define DM_UUID_LEN 129
+
+/*
+ * A traditional ioctl interface for the device mapper.
+ *
+ * Each device can have two tables associated with it, an
+ * 'active' table which is the one currently used by io passing
+ * through the device, and an 'inactive' one which is a table
+ * that is being prepared as a replacement for the 'active' one.
+ *
+ * DM_VERSION:
+ * Just get the version information for the ioctl interface.
+ *
+ * DM_REMOVE_ALL:
+ * Remove all dm devices, destroy all tables.  Only really used
+ * for debug.
+ *
+ * DM_LIST_DEVICES:
+ * Get a list of all the dm device names.
+ *
+ * DM_DEV_CREATE:
+ * Create a new device, neither the 'active' or 'inactive' table
+ * slots will be filled.  The device will be in suspended state
+ * after creation, however any io to the device will get errored
+ * since it will be out-of-bounds.
+ *
+ * DM_DEV_REMOVE:
+ * Remove a device, destroy any tables.
+ *
+ * DM_DEV_RENAME:
+ * Rename a device.
+ *
+ * DM_SUSPEND:
+ * This performs both suspend and resume, depending which flag is
+ * passed in.
+ * Suspend: This command will not return until all pending io to
+ * the device has completed.  Further io will be deferred until
+ * the device is resumed.
+ * Resume: It is no longer an error to issue this command on an
+ * unsuspended device.  If a table is present in the 'inactive'
+ * slot, it will be moved to the active slot, then the old table
+ * from the active slot will be _destroyed_.  Finally the device
+ * is resumed.
+ *
+ * DM_DEV_STATUS:
+ * Retrieves the status for the table in the 'active' slot.
+ *
+ * DM_DEV_WAIT:
+ * Wait for a significant event to occur to the device.  This
+ * could either be caused by an event triggered by one of the
+ * targets of the table in the 'active' slot, or a table change.
+ *
+ * DM_TABLE_LOAD:
+ * Load a table into the 'inactive' slot for the device.  The
+ * device does _not_ need to be suspended prior to this command.
+ *
+ * DM_TABLE_CLEAR:
+ * Destroy any table in the 'inactive' slot (ie. abort).
+ *
+ * DM_TABLE_DEPS:
+ * Return a set of device dependencies for the 'active' table.
+ *
+ * DM_TABLE_STATUS:
+ * Return the targets status for the 'active' table.
+ */
+
+/*
+ * All ioctl arguments consist of a single chunk of memory, with
+ * this structure at the start.  If a uuid is specified any
+ * lookup (eg. for a DM_INFO) will be done on that, *not* the
+ * name.
+ */
+struct dm_ioctl {
+	/*
+	 * The version number is made up of three parts:
+	 * major - no backward or forward compatibility,
+	 * minor - only backwards compatible,
+	 * patch - both backwards and forwards compatible.
+	 *
+	 * All clients of the ioctl interface should fill in the
+	 * version number of the interface that they were
+	 * compiled with.
+	 *
+	 * All recognised ioctl commands (ie. those that don't
+	 * return -ENOTTY) fill out this field, even if the
+	 * command failed.
+	 */
+	uint32_t version[3];	/* in/out */
+	uint32_t data_size;	/* total size of data passed in
+				 * including this struct */
+
+	uint32_t data_start;	/* offset to start of data
+				 * relative to start of this struct */
+
+	uint32_t target_count;	/* in/out */
+	int32_t open_count;	/* out */
+	uint32_t flags;		/* in/out */
+	uint32_t event_nr;      	/* in/out */
+	uint32_t padding;
+
+	uint64_t dev;		/* in/out */
+
+	char name[DM_NAME_LEN];	/* device name */
+	char uuid[DM_UUID_LEN];	/* unique identifier for
+				 * the block device */
+};
+
+/*
+ * Used to specify tables.  These structures appear after the
+ * dm_ioctl.
+ */
+struct dm_target_spec {
+	uint64_t sector_start;
+	uint64_t length;
+	int32_t status;		/* used when reading from kernel only */
+
+	/*
+	 * Offset in bytes (from the start of this struct) to
+	 * next target_spec.
+	 */
+	uint32_t next;
+
+	char target_type[DM_MAX_TYPE_NAME];
+
+	/*
+	 * Parameter string starts immediately after this object.
+	 * Be careful to add padding after string to ensure correct
+	 * alignment of subsequent dm_target_spec.
+	 */
+};
+
+/*
+ * Used to retrieve the target dependencies.
+ */
+struct dm_target_deps {
+	uint32_t count;	/* Array size */
+	uint32_t padding;	/* unused */
+	uint64_t dev[0];	/* out */
+};
+
+/*
+ * Used to get a list of all dm devices.
+ */
+struct dm_name_list {
+	uint64_t dev;
+	uint32_t next;		/* offset to the next record from
+				   the _start_ of this */
+	char name[0];
+};
+
+/*
+ * If you change this make sure you make the corresponding change
+ * to dm-ioctl.c:lookup_ioctl()
+ */
+enum {
+	/* Top level cmds */
+	DM_VERSION_CMD = 0,
+	DM_REMOVE_ALL_CMD,
+	DM_LIST_DEVICES_CMD,
+
+	/* device level cmds */
+	DM_DEV_CREATE_CMD,
+	DM_DEV_REMOVE_CMD,
+	DM_DEV_RENAME_CMD,
+	DM_DEV_SUSPEND_CMD,
+	DM_DEV_STATUS_CMD,
+	DM_DEV_WAIT_CMD,
+
+	/* Table level cmds */
+	DM_TABLE_LOAD_CMD,
+	DM_TABLE_CLEAR_CMD,
+	DM_TABLE_DEPS_CMD,
+	DM_TABLE_STATUS_CMD,
+};
+
+#define DM_IOCTL 0xfd
+
+#define DM_VERSION       _IOWR(DM_IOCTL, DM_VERSION_CMD, struct dm_ioctl)
+#define DM_REMOVE_ALL    _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD, struct dm_ioctl)
+#define DM_LIST_DEVICES  _IOWR(DM_IOCTL, DM_LIST_DEVICES_CMD, struct dm_ioctl)
+
+#define DM_DEV_CREATE    _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD, struct dm_ioctl)
+#define DM_DEV_REMOVE    _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD, struct dm_ioctl)
+#define DM_DEV_RENAME    _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD, struct dm_ioctl)
+#define DM_DEV_SUSPEND   _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl)
+#define DM_DEV_STATUS    _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl)
+#define DM_DEV_WAIT      _IOWR(DM_IOCTL, DM_DEV_WAIT_CMD, struct dm_ioctl)
+
+#define DM_TABLE_LOAD    _IOWR(DM_IOCTL, DM_TABLE_LOAD_CMD, struct dm_ioctl)
+#define DM_TABLE_CLEAR   _IOWR(DM_IOCTL, DM_TABLE_CLEAR_CMD, struct dm_ioctl)
+#define DM_TABLE_DEPS    _IOWR(DM_IOCTL, DM_TABLE_DEPS_CMD, struct dm_ioctl)
+#define DM_TABLE_STATUS  _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, struct dm_ioctl)
+
+#define DM_VERSION_MAJOR	4
+#define DM_VERSION_MINOR	0
+#define DM_VERSION_PATCHLEVEL	0
+#define DM_VERSION_EXTRA	"-ioctl (2003-06-04)"
+
+/* Status bits */
+#define DM_READONLY_FLAG	(1 << 0) /* In/Out */
+#define DM_SUSPEND_FLAG		(1 << 1) /* In/Out */
+#define DM_PERSISTENT_DEV_FLAG	(1 << 3) /* In */
+
+/*
+ * Flag passed into ioctl STATUS command to get table information
+ * rather than current status.
+ */
+#define DM_STATUS_TABLE_FLAG	(1 << 4) /* In */
+
+/*
+ * Flags that indicate whether a table is present in either of
+ * the two table slots that a device has.
+ */
+#define DM_ACTIVE_PRESENT_FLAG   (1 << 5) /* Out */
+#define DM_INACTIVE_PRESENT_FLAG (1 << 6) /* Out */
+
+/*
+ * Indicates that the buffer passed in wasn't big enough for the
+ * results.
+ */
+#define DM_BUFFER_FULL_FLAG	(1 << 8) /* Out */
+
+#endif				/* _LINUX_DM_IOCTL_H */
diff -Nru a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h
--- a/include/linux/dm-ioctl.h	Sat Jul 19 12:54:21 2003
+++ b/include/linux/dm-ioctl.h	Sat Jul 19 12:54:21 2003
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001 Sistina Software (UK) Limited.
+ * Copyright (C) 2003 Sistina Software (UK) Limited.
  *
  * This file is released under the LGPL.
  */
@@ -7,143 +7,12 @@
 #ifndef _LINUX_DM_IOCTL_H
 #define _LINUX_DM_IOCTL_H
 
-#include <linux/types.h>
+#include <linux/config.h>
 
-#define DM_DIR "mapper"	/* Slashes not supported */
-#define DM_MAX_TYPE_NAME 16
-#define DM_NAME_LEN 128
-#define DM_UUID_LEN 129
+#ifdef CONFIG_DM_IOCTL_V4
+#include "dm-ioctl-v4.h"
+#else
+#include "dm-ioctl-v1.h"
+#endif
 
-/*
- * Implements a traditional ioctl interface to the device mapper.
- */
-
-/*
- * All ioctl arguments consist of a single chunk of memory, with
- * this structure at the start.  If a uuid is specified any
- * lookup (eg. for a DM_INFO) will be done on that, *not* the
- * name.
- */
-struct dm_ioctl {
-	/*
-	 * The version number is made up of three parts:
-	 * major - no backward or forward compatibility,
-	 * minor - only backwards compatible,
-	 * patch - both backwards and forwards compatible.
-	 *
-	 * All clients of the ioctl interface should fill in the
-	 * version number of the interface that they were
-	 * compiled with.
-	 *
-	 * All recognised ioctl commands (ie. those that don't
-	 * return -ENOTTY) fill out this field, even if the
-	 * command failed.
-	 */
-	uint32_t version[3];	/* in/out */
-	uint32_t data_size;	/* total size of data passed in
-				 * including this struct */
-
-	uint32_t data_start;	/* offset to start of data
-				 * relative to start of this struct */
-
-	uint32_t target_count;	/* in/out */
-	uint32_t open_count;	/* out */
-	uint32_t flags;		/* in/out */
-
-	__kernel_dev_t dev;	/* in/out */
-
-	char name[DM_NAME_LEN];	/* device name */
-	char uuid[DM_UUID_LEN];	/* unique identifier for
-				 * the block device */
-};
-
-/*
- * Used to specify tables.  These structures appear after the
- * dm_ioctl.
- */
-struct dm_target_spec {
-	int32_t status;		/* used when reading from kernel only */
-	uint64_t sector_start;
-	uint32_t length;
-
-	/*
-	 * Offset in bytes (from the start of this struct) to
-	 * next target_spec.
-	 */
-	uint32_t next;
-
-	char target_type[DM_MAX_TYPE_NAME];
-
-	/*
-	 * Parameter string starts immediately after this object.
-	 * Be careful to add padding after string to ensure correct
-	 * alignment of subsequent dm_target_spec.
-	 */
-};
-
-/*
- * Used to retrieve the target dependencies.
- */
-struct dm_target_deps {
-	uint32_t count;
-
-	__kernel_dev_t dev[0];	/* out */
-};
-
-/*
- * If you change this make sure you make the corresponding change
- * to dm-ioctl.c:lookup_ioctl()
- */
-enum {
-	/* Top level cmds */
-	DM_VERSION_CMD = 0,
-	DM_REMOVE_ALL_CMD,
-
-	/* device level cmds */
-	DM_DEV_CREATE_CMD,
-	DM_DEV_REMOVE_CMD,
-	DM_DEV_RELOAD_CMD,
-	DM_DEV_RENAME_CMD,
-	DM_DEV_SUSPEND_CMD,
-	DM_DEV_DEPS_CMD,
-	DM_DEV_STATUS_CMD,
-
-	/* target level cmds */
-	DM_TARGET_STATUS_CMD,
-	DM_TARGET_WAIT_CMD
-};
-
-#define DM_IOCTL 0xfd
-
-#define DM_VERSION       _IOWR(DM_IOCTL, DM_VERSION_CMD, struct dm_ioctl)
-#define DM_REMOVE_ALL    _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD, struct dm_ioctl)
-
-#define DM_DEV_CREATE    _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD, struct dm_ioctl)
-#define DM_DEV_REMOVE    _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD, struct dm_ioctl)
-#define DM_DEV_RELOAD    _IOWR(DM_IOCTL, DM_DEV_RELOAD_CMD, struct dm_ioctl)
-#define DM_DEV_SUSPEND   _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl)
-#define DM_DEV_RENAME    _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD, struct dm_ioctl)
-#define DM_DEV_DEPS      _IOWR(DM_IOCTL, DM_DEV_DEPS_CMD, struct dm_ioctl)
-#define DM_DEV_STATUS    _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl)
-
-#define DM_TARGET_STATUS _IOWR(DM_IOCTL, DM_TARGET_STATUS_CMD, struct dm_ioctl)
-#define DM_TARGET_WAIT   _IOWR(DM_IOCTL, DM_TARGET_WAIT_CMD, struct dm_ioctl)
-
-#define DM_VERSION_MAJOR	1
-#define DM_VERSION_MINOR	0
-#define DM_VERSION_PATCHLEVEL	6
-#define DM_VERSION_EXTRA	"-ioctl (2002-10-15)"
-
-/* Status bits */
-#define DM_READONLY_FLAG	0x00000001
-#define DM_SUSPEND_FLAG		0x00000002
-#define DM_EXISTS_FLAG		0x00000004
-#define DM_PERSISTENT_DEV_FLAG	0x00000008
-
-/*
- * Flag passed into ioctl STATUS command to get table information
- * rather than current status.
- */
-#define DM_STATUS_TABLE_FLAG	0x00000010
-
-#endif				/* _LINUX_DM_IOCTL_H */
+#endif
diff -Nru a/include/linux/elevator.h b/include/linux/elevator.h
--- a/include/linux/elevator.h	Sat Jul 19 12:54:21 2003
+++ b/include/linux/elevator.h	Sat Jul 19 12:54:21 2003
@@ -13,6 +13,7 @@
 typedef void (elevator_add_req_fn) (request_queue_t *, struct request *, struct list_head *);
 typedef int (elevator_queue_empty_fn) (request_queue_t *);
 typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *);
+typedef void (elevator_requeue_req_fn) (request_queue_t *, struct request *);
 typedef struct request *(elevator_request_list_fn) (request_queue_t *, struct request *);
 typedef struct list_head *(elevator_get_sort_head_fn) (request_queue_t *, struct request *);
 typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *);
@@ -33,6 +34,7 @@
 	elevator_next_req_fn *elevator_next_req_fn;
 	elevator_add_req_fn *elevator_add_req_fn;
 	elevator_remove_req_fn *elevator_remove_req_fn;
+	elevator_requeue_req_fn *elevator_requeue_req_fn;
 
 	elevator_queue_empty_fn *elevator_queue_empty_fn;
 	elevator_completed_req_fn *elevator_completed_req_fn;
@@ -64,6 +66,7 @@
 			       struct request *);
 extern void elv_merged_request(request_queue_t *, struct request *);
 extern void elv_remove_request(request_queue_t *, struct request *);
+extern void elv_requeue_request(request_queue_t *, struct request *);
 extern int elv_queue_empty(request_queue_t *);
 extern struct request *elv_next_request(struct request_queue *q);
 extern struct request *elv_former_request(request_queue_t *, struct request *);
diff -Nru a/include/linux/elfcore.h b/include/linux/elfcore.h
--- a/include/linux/elfcore.h	Sat Jul 19 12:54:30 2003
+++ b/include/linux/elfcore.h	Sat Jul 19 12:54:30 2003
@@ -107,12 +107,12 @@
 
 extern int dump_fpu (struct pt_regs *, elf_fpregset_t *);
 
-static inline int elf_core_copy_task_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
+static inline int elf_core_copy_task_fpregs(struct task_struct *t, struct pt_regs *regs, elf_fpregset_t *fpu)
 {
 #ifdef ELF_CORE_COPY_FPREGS
 	return ELF_CORE_COPY_FPREGS(t, fpu);
 #else
-	return dump_fpu(NULL, fpu);
+	return dump_fpu(regs, fpu);
 #endif
 }
 
diff -Nru a/include/linux/ext3_jbd.h b/include/linux/ext3_jbd.h
--- a/include/linux/ext3_jbd.h	Sat Jul 19 12:54:22 2003
+++ b/include/linux/ext3_jbd.h	Sat Jul 19 12:54:22 2003
@@ -30,10 +30,11 @@
 
 #define EXT3_SINGLEDATA_TRANS_BLOCKS	8U
 
-/* Extended attributes may touch two data buffers, two bitmap buffers,
- * and two group and summaries. */
+/* Extended attribute operations touch at most two data buffers,
+ * two bitmap buffers, and two group summaries, in addition to the inode
+ * and the superblock, which are already accounted for. */
 
-#define EXT3_XATTR_TRANS_BLOCKS		8
+#define EXT3_XATTR_TRANS_BLOCKS		6U
 
 /* Define the minimum size for a transaction which modifies data.  This
  * needs to take into account the fact that we may end up modifying two
diff -Nru a/include/linux/hfs_sysdep.h b/include/linux/hfs_sysdep.h
--- a/include/linux/hfs_sysdep.h	Sat Jul 19 12:54:23 2003
+++ b/include/linux/hfs_sysdep.h	Sat Jul 19 12:54:23 2003
@@ -28,9 +28,6 @@
 
 extern struct timezone sys_tz;
 
-#undef offsetof
-#define offsetof(TYPE, MEMB) ((size_t) &((TYPE *)0)->MEMB)
-
 /* Typedefs for integer types by size and signedness */
 typedef __u8            hfs_u8;
 typedef __u16           hfs_u16;
diff -Nru a/include/linux/ide.h b/include/linux/ide.h
--- a/include/linux/ide.h	Sat Jul 19 12:54:24 2003
+++ b/include/linux/ide.h	Sat Jul 19 12:54:24 2003
@@ -1288,12 +1288,6 @@
 #endif
 extern int noautodma;
 
-/*
- * We need blk.h, but we replace its end_request by our own version.
- */
-#define IDE_DRIVER		/* Toggle some magic bits in blk.h */
-#include <linux/blk.h>
-
 extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs);
 
 /*
diff -Nru a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
--- a/include/linux/kernel_stat.h	Sat Jul 19 12:54:29 2003
+++ b/include/linux/kernel_stat.h	Sat Jul 19 12:54:29 2003
@@ -23,9 +23,7 @@
 
 struct kernel_stat {
 	struct cpu_usage_stat	cpustat;
-#if !defined(CONFIG_ARCH_S390)
 	unsigned int irqs[NR_IRQS];
-#endif
 };
 
 DECLARE_PER_CPU(struct kernel_stat, kstat);
@@ -36,7 +34,6 @@
 
 extern unsigned long nr_context_switches(void);
 
-#if !defined(CONFIG_ARCH_S390)
 /*
  * Number of interrupts per specific IRQ source, since bootup
  */
@@ -50,6 +47,5 @@
 
 	return sum;
 }
-#endif
 
 #endif /* _LINUX_KERNEL_STAT_H */
diff -Nru a/include/linux/loop.h b/include/linux/loop.h
--- a/include/linux/loop.h	Sat Jul 19 12:54:30 2003
+++ b/include/linux/loop.h	Sat Jul 19 12:54:30 2003
@@ -15,7 +15,7 @@
 
 #ifdef __KERNEL__
 #include <linux/bio.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/spinlock.h>
 
 /* Possible states of device */
diff -Nru a/include/linux/module.h b/include/linux/module.h
--- a/include/linux/module.h	Sat Jul 19 12:54:26 2003
+++ b/include/linux/module.h	Sat Jul 19 12:54:26 2003
@@ -16,6 +16,7 @@
 #include <linux/kmod.h>
 #include <linux/elf.h>
 #include <linux/stringify.h>
+#include <asm/local.h>
 
 #include <asm/module.h>
 
@@ -171,7 +172,7 @@
 
 struct module_ref
 {
-	atomic_t count;
+	local_t count;
 } ____cacheline_aligned;
 
 enum module_state
@@ -276,19 +277,17 @@
 				  char *type,
 				  char namebuf[128]);
 int is_exported(const char *name, const struct module *mod);
-#ifdef CONFIG_MODULE_UNLOAD
 
+extern void __module_put_and_exit(struct module *mod, long code)
+	__attribute__((noreturn));
+#define module_put_and_exit(code) __module_put_and_exit(THIS_MODULE, code);
+
+#ifdef CONFIG_MODULE_UNLOAD
 unsigned int module_refcount(struct module *mod);
 void __symbol_put(const char *symbol);
 #define symbol_put(x) __symbol_put(MODULE_SYMBOL_PREFIX #x)
 void symbol_put_addr(void *addr);
 
-/* We only need protection against local interrupts. */
-#ifndef __HAVE_ARCH_LOCAL_INC
-#define local_inc(x) atomic_inc(x)
-#define local_dec(x) atomic_dec(x)
-#endif
-
 /* Sometimes we know we already have a refcount, and it's easier not
    to handle the error case (which only happens with rmmod --wait). */
 static inline void __module_get(struct module *module)
@@ -444,6 +443,8 @@
 {
 	return 0;
 }
+
+#define module_put_and_exit(code) do_exit(code)
 
 #endif /* CONFIG_MODULES */
 
diff -Nru a/include/linux/namespace.h b/include/linux/namespace.h
--- a/include/linux/namespace.h	Sat Jul 19 12:54:25 2003
+++ b/include/linux/namespace.h	Sat Jul 19 12:54:25 2003
@@ -2,7 +2,7 @@
 #define _NAMESPACE_H_
 #ifdef __KERNEL__
 
-#include <linux/dcache.h>
+#include <linux/mount.h>
 #include <linux/sched.h>
 
 struct namespace {
@@ -14,17 +14,12 @@
 
 extern void umount_tree(struct vfsmount *);
 extern int copy_namespace(int, struct task_struct *);
+void __put_namespace(struct namespace *namespace);
 
 static inline void put_namespace(struct namespace *namespace)
 {
-	if (atomic_dec_and_test(&namespace->count)) {
-		down_write(&namespace->sem);
-		spin_lock(&dcache_lock);
-		umount_tree(namespace->root);
-		spin_unlock(&dcache_lock);
-		up_write(&namespace->sem);
-		kfree(namespace);
-	}
+	if (atomic_dec_and_test(&namespace->count))
+		__put_namespace(namespace);
 }
 
 static inline void exit_namespace(struct task_struct *p)
diff -Nru a/include/linux/netdevice.h b/include/linux/netdevice.h
--- a/include/linux/netdevice.h	Sat Jul 19 12:54:29 2003
+++ b/include/linux/netdevice.h	Sat Jul 19 12:54:29 2003
@@ -29,6 +29,7 @@
 #include <linux/if_ether.h>
 #include <linux/if_packet.h>
 #include <linux/device.h>
+#include <linux/percpu.h>
 
 #include <asm/atomic.h>
 #include <asm/cache.h>
@@ -544,10 +545,9 @@
 	struct sk_buff		*completion_queue;
 
 	struct net_device	backlog_dev;	/* Sorry. 8) */
-} ____cacheline_aligned;
-
+};
 
-extern struct softnet_data softnet_data[NR_CPUS];
+DECLARE_PER_CPU(struct softnet_data,softnet_data);
 
 #define HAVE_NETIF_QUEUE
 
@@ -555,12 +555,12 @@
 {
 	if (!test_and_set_bit(__LINK_STATE_SCHED, &dev->state)) {
 		unsigned long flags;
-		int cpu;
+		struct softnet_data *sd;
 
 		local_irq_save(flags);
-		cpu = smp_processor_id();
-		dev->next_sched = softnet_data[cpu].output_queue;
-		softnet_data[cpu].output_queue = dev;
+		sd = &__get_cpu_var(softnet_data);
+		dev->next_sched = sd->output_queue;
+		sd->output_queue = dev;
 		raise_softirq_irqoff(NET_TX_SOFTIRQ);
 		local_irq_restore(flags);
 	}
@@ -605,13 +605,13 @@
 static inline void dev_kfree_skb_irq(struct sk_buff *skb)
 {
 	if (atomic_dec_and_test(&skb->users)) {
-		int cpu;
+		struct softnet_data *sd;
 		unsigned long flags;
 
 		local_irq_save(flags);
-		cpu = smp_processor_id();
-		skb->next = softnet_data[cpu].completion_queue;
-		softnet_data[cpu].completion_queue = skb;
+		sd = &__get_cpu_var(softnet_data);
+		skb->next = sd->completion_queue;
+		sd->completion_queue = skb;
 		raise_softirq_irqoff(NET_TX_SOFTIRQ);
 		local_irq_restore(flags);
 	}
@@ -769,12 +769,10 @@
 static inline void __netif_rx_schedule(struct net_device *dev)
 {
 	unsigned long flags;
-	int cpu;
 
 	local_irq_save(flags);
-	cpu = smp_processor_id();
 	dev_hold(dev);
-	list_add_tail(&dev->poll_list, &softnet_data[cpu].poll_list);
+	list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
 	if (dev->quota < 0)
 		dev->quota += dev->weight;
 	else
@@ -798,13 +796,11 @@
 {
 	if (netif_rx_schedule_prep(dev)) {
 		unsigned long flags;
-		int cpu;
 
 		dev->quota += undo;
 
 		local_irq_save(flags);
-		cpu = smp_processor_id();
-		list_add_tail(&dev->poll_list, &softnet_data[cpu].poll_list);
+		list_add_tail(&dev->poll_list, &__get_cpu_var(softnet_data).poll_list);
 		__raise_softirq_irqoff(NET_RX_SOFTIRQ);
 		local_irq_restore(flags);
 		return 1;
diff -Nru a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
--- a/include/linux/nfs_fs.h	Sat Jul 19 12:54:24 2003
+++ b/include/linux/nfs_fs.h	Sat Jul 19 12:54:24 2003
@@ -172,6 +172,7 @@
 #define NFS_INO_ADVISE_RDPLUS   0x0002          /* advise readdirplus */
 #define NFS_INO_REVALIDATING	0x0004		/* revalidating attrs */
 #define NFS_INO_FLUSH		0x0008		/* inode is due for flushing */
+#define NFS_INO_FAKE_ROOT	0x0080		/* root inode placeholder */
 
 static inline struct nfs_inode *NFS_I(struct inode *inode)
 {
@@ -207,6 +208,7 @@
 #define NFS_FLAGS(inode)		(NFS_I(inode)->flags)
 #define NFS_REVALIDATING(inode)		(NFS_FLAGS(inode) & NFS_INO_REVALIDATING)
 #define NFS_STALE(inode)		(NFS_FLAGS(inode) & NFS_INO_STALE)
+#define NFS_FAKE_ROOT(inode)		(NFS_FLAGS(inode) & NFS_INO_FAKE_ROOT)
 
 #define NFS_FILEID(inode)		(NFS_I(inode)->fileid)
 
diff -Nru a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
--- a/include/linux/nfs_fs_sb.h	Sat Jul 19 12:54:30 2003
+++ b/include/linux/nfs_fs_sb.h	Sat Jul 19 12:54:30 2003
@@ -9,6 +9,7 @@
  */
 struct nfs_server {
 	struct rpc_clnt *	client;		/* RPC client handle */
+	struct rpc_clnt *	client_sys;	/* 2nd handle for FSINFO */
 	struct nfs_rpc_ops *	rpc_ops;	/* NFS protocol vector */
 	struct backing_dev_info	backing_dev_info;
 	int			flags;		/* various flags */
diff -Nru a/include/linux/nfs_mount.h b/include/linux/nfs_mount.h
--- a/include/linux/nfs_mount.h	Sat Jul 19 12:54:21 2003
+++ b/include/linux/nfs_mount.h	Sat Jul 19 12:54:21 2003
@@ -20,7 +20,7 @@
  * mount-to-kernel version compatibility.  Some of these aren't used yet
  * but here they are anyway.
  */
-#define NFS_MOUNT_VERSION	4
+#define NFS_MOUNT_VERSION	5
 
 struct nfs_mount_data {
 	int		version;		/* 1 */
@@ -40,7 +40,7 @@
 	int		namlen;			/* 2 */
 	unsigned int	bsize;			/* 3 */
 	struct nfs3_fh	root;			/* 4 */
-	int		pseudoflavor;		/* 4 */
+	int		pseudoflavor;		/* 5 */
 };
 
 /* bits in the flags field */
@@ -57,7 +57,7 @@
 #define NFS_MOUNT_NONLM		0x0200	/* 3 */
 #define NFS_MOUNT_BROKEN_SUID	0x0400	/* 4 */
 #define NFS_MOUNT_STRICTLOCK	0x1000	/* reserved for NFSv4 */
-#define NFS_MOUNT_SECFLAVOUR	0x2000	/* reserved */
+#define NFS_MOUNT_SECFLAVOUR	0x2000	/* 5 */
 #define NFS_MOUNT_FLAGMASK	0xFFFF
 
 #endif
diff -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h	Sat Jul 19 12:54:25 2003
+++ b/include/linux/pci.h	Sat Jul 19 12:54:25 2003
@@ -715,7 +715,6 @@
 static inline int pci_assign_resource(struct pci_dev *dev, int i) { return -EBUSY;}
 static inline int pci_register_driver(struct pci_driver *drv) { return 0;}
 static inline void pci_unregister_driver(struct pci_driver *drv) { }
-static inline int scsi_to_pci_dma_dir(unsigned char scsi_dir) { return scsi_dir; }
 static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; }
 static inline const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { return NULL; }
 
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	Sat Jul 19 12:54:22 2003
+++ b/include/linux/sched.h	Sat Jul 19 12:54:22 2003
@@ -52,6 +52,7 @@
 #define CLONE_DETACHED		0x00400000	/* parent wants no child-exit signal */
 #define CLONE_UNTRACED		0x00800000	/* set if the tracing process can't force CLONE_PTRACE on this clone */
 #define CLONE_CHILD_SETTID	0x01000000	/* set the TID in the child */
+#define CLONE_STOPPED		0x02000000	/* Start in stopped state */
 
 /*
  * List of flags we want to share for kernel threads,
diff -Nru a/include/linux/serial_core.h b/include/linux/serial_core.h
--- a/include/linux/serial_core.h	Sat Jul 19 12:54:23 2003
+++ b/include/linux/serial_core.h	Sat Jul 19 12:54:23 2003
@@ -57,7 +57,7 @@
 #define PORT_SUNSAB	39
 
 /* NEC v850.  */
-#define PORT_NB85E_UART	40
+#define PORT_V850E_UART	40
 
 /* NEC PC-9800 */
 #define PORT_8251_PC98	41
diff -Nru a/include/linux/times.h b/include/linux/times.h
--- a/include/linux/times.h	Sat Jul 19 12:54:22 2003
+++ b/include/linux/times.h	Sat Jul 19 12:54:22 2003
@@ -11,6 +11,26 @@
 # define jiffies_to_clock_t(x) ((clock_t) jiffies_64_to_clock_t((u64) x))
 #endif
 
+static inline unsigned long clock_t_to_jiffies(unsigned long x)
+{
+#if (HZ % USER_HZ)==0
+	if (x >= ~0UL / (HZ / USER_HZ))
+		return ~0UL;
+	return x * (HZ / USER_HZ);
+#else
+	u64 jif;
+
+	/* Don't worry about loss of precision here .. */
+	if (x >= ~0UL / HZ * USER_HZ)
+		return ~0UL;
+
+	/* .. but do try to contain it here */
+	jif = x * (u64) HZ;
+	do_div(jif, USER_HZ);
+	return jif;
+#endif
+}
+
 static inline u64 jiffies_64_to_clock_t(u64 x)
 {
 #if (HZ % USER_HZ)==0
diff -Nru a/include/linux/tty.h b/include/linux/tty.h
--- a/include/linux/tty.h	Sat Jul 19 12:54:25 2003
+++ b/include/linux/tty.h	Sat Jul 19 12:54:25 2003
@@ -57,40 +57,40 @@
  */
 
 struct screen_info {
-	unsigned char  orig_x;			/* 0x00 */
-	unsigned char  orig_y;			/* 0x01 */
-	unsigned short dontuse1;		/* 0x02 -- EXT_MEM_K sits here */
-	unsigned short orig_video_page;		/* 0x04 */
-	unsigned char  orig_video_mode;		/* 0x06 */
-	unsigned char  orig_video_cols;		/* 0x07 */
-	unsigned short unused2;			/* 0x08 */
-	unsigned short orig_video_ega_bx;	/* 0x0a */
-	unsigned short unused3;			/* 0x0c */
-	unsigned char  orig_video_lines;	/* 0x0e */
-	unsigned char  orig_video_isVGA;	/* 0x0f */
-	unsigned short orig_video_points;	/* 0x10 */
+	u8  orig_x;		/* 0x00 */
+	u8  orig_y;		/* 0x01 */
+	u16 dontuse1;		/* 0x02 -- EXT_MEM_K sits here */
+	u16 orig_video_page;	/* 0x04 */
+	u8  orig_video_mode;	/* 0x06 */
+	u8  orig_video_cols;	/* 0x07 */
+	u16 unused2;		/* 0x08 */
+	u16 orig_video_ega_bx;	/* 0x0a */
+	u16 unused3;		/* 0x0c */
+	u8  orig_video_lines;	/* 0x0e */
+	u8  orig_video_isVGA;	/* 0x0f */
+	u16 orig_video_points;	/* 0x10 */
 
 	/* VESA graphic mode -- linear frame buffer */
-	unsigned short lfb_width;		/* 0x12 */
-	unsigned short lfb_height;		/* 0x14 */
-	unsigned short lfb_depth;		/* 0x16 */
-	unsigned long  lfb_base;		/* 0x18 */
-	unsigned long  lfb_size;		/* 0x1c */
-	unsigned short dontuse2, dontuse3;	/* 0x20 -- CL_MAGIC and CL_OFFSET here */
-	unsigned short lfb_linelength;		/* 0x24 */
-	unsigned char  red_size;		/* 0x26 */
-	unsigned char  red_pos;			/* 0x27 */
-	unsigned char  green_size;		/* 0x28 */
-	unsigned char  green_pos;		/* 0x29 */
-	unsigned char  blue_size;		/* 0x2a */
-	unsigned char  blue_pos;		/* 0x2b */
-	unsigned char  rsvd_size;		/* 0x2c */
-	unsigned char  rsvd_pos;		/* 0x2d */
-	unsigned short vesapm_seg;		/* 0x2e */
-	unsigned short vesapm_off;		/* 0x30 */
-	unsigned short pages;			/* 0x32 */
-	unsigned short vesa_attributes;		/* 0x34 */
-						/* 0x36 -- 0x3f reserved for future expansion */
+	u16 lfb_width;		/* 0x12 */
+	u16 lfb_height;		/* 0x14 */
+	u16 lfb_depth;		/* 0x16 */
+	u32 lfb_base;		/* 0x18 */
+	u32 lfb_size;		/* 0x1c */
+	u16 dontuse2, dontuse3;	/* 0x20 -- CL_MAGIC and CL_OFFSET here */
+	u16 lfb_linelength;	/* 0x24 */
+	u8  red_size;		/* 0x26 */
+	u8  red_pos;		/* 0x27 */
+	u8  green_size;		/* 0x28 */
+	u8  green_pos;		/* 0x29 */
+	u8  blue_size;		/* 0x2a */
+	u8  blue_pos;		/* 0x2b */
+	u8  rsvd_size;		/* 0x2c */
+	u8  rsvd_pos;		/* 0x2d */
+	u16 vesapm_seg;		/* 0x2e */
+	u16 vesapm_off;		/* 0x30 */
+	u16 pages;		/* 0x32 */
+	u16 vesa_attributes;	/* 0x34 */
+				/* 0x36 -- 0x3f reserved for future expansion */
 };
 
 extern struct screen_info screen_info;
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h	Sat Jul 19 12:54:24 2003
+++ b/include/linux/usb.h	Sat Jul 19 12:54:24 2003
@@ -80,7 +80,8 @@
  * @act_altsetting: index of current altsetting.  this number is always
  *	less than num_altsetting.  after the device is configured, each
  *	interface uses its default setting of zero.
- * @max_altsetting:
+ * @max_altsetting: the max number of altsettings for this interface.
+ * @driver: the USB driver that is bound to this interface.
  * @minor: the minor number assigned to this interface, if this
  *	interface is bound to a driver that uses the USB major number.
  *	If this interface does not use the USB major, this field should
@@ -409,7 +410,11 @@
  *	do (or don't) show up otherwise in the filesystem.
  * @id_table: USB drivers use ID table to support hotplugging.
  *	Export this with MODULE_DEVICE_TABLE(usb,...).  This must be set
- *	or your driver's probe function will never get called. 
+ *	or your driver's probe function will never get called.
+ * @driver: the driver model core driver structure.
+ * @serialize: a semaphore used to serialize access to this driver.  Used
+ * 	in the probe and disconnect functions.  Only the USB core should use
+ * 	this lock.
  *
  * USB drivers must provide a name, probe() and disconnect() methods,
  * and an id_table.  Other driver fields are optional.
@@ -575,6 +580,8 @@
  *	it likes with the URB, including resubmitting or freeing it.
  * @iso_frame_desc: Used to provide arrays of ISO transfer buffers and to 
  *	collect the transfer status for each buffer.
+ * @timeout: If set to zero, the urb will never timeout.  Otherwise this is
+ *	the time in jiffies that this urb will timeout in.
  *
  * This structure identifies USB transfer requests.  URBs must be allocated by
  * calling usb_alloc_urb() and freed with a call to usb_free_urb().
@@ -677,10 +684,14 @@
  */
 struct urb
 {
+	/* private, usb core and host controller only fields in the urb */
 	spinlock_t lock;		/* lock for the URB */
 	atomic_t count;			/* reference count of the URB */
 	void *hcpriv;			/* private data for host controller */
 	struct list_head urb_list;	/* list pointer to all active urbs */
+	int bandwidth;			/* bandwidth for INT/ISO request */
+
+	/* public, documented fields in the urb that can be used by drivers */
 	struct usb_device *dev; 	/* (in) pointer to associated device */
 	unsigned int pipe;		/* (in) pipe information */
 	int status;			/* (return) non-ISO status */
@@ -689,7 +700,6 @@
 	dma_addr_t transfer_dma;	/* (in) dma addr for transfer_buffer */
 	int transfer_buffer_length;	/* (in) data buffer length */
 	int actual_length;		/* (return) actual transfer length */
-	int bandwidth;			/* bandwidth for INT/ISO request */
 	unsigned char *setup_packet;	/* (in) setup packet (control only) */
 	dma_addr_t setup_dma;		/* (in) dma addr for setup_packet */
 	int start_frame;		/* (modify) start frame (INT/ISO) */
@@ -891,8 +901,10 @@
 	int			status;
 	size_t			bytes;
 
-	// members not documented above are private to usbcore,
-	// and are not provided for driver access!
+	/* 
+	 * members below are private to usbcore,
+	 * and are not provided for driver access!
+	 */
 	spinlock_t		lock;
 
 	struct usb_device	*dev;
diff -Nru a/include/media/saa7146.h b/include/media/saa7146.h
--- a/include/media/saa7146.h	Sat Jul 19 12:54:21 2003
+++ b/include/media/saa7146.h	Sat Jul 19 12:54:21 2003
@@ -89,8 +89,6 @@
 #define SAA7146_USE_I2C_IRQ	0x1
 	int	flags;
 	
-	struct saa7146_ext_vv	*ext_vv_data;
-	
 	/* pairs of subvendor and subdevice ids for
 	   supported devices, last entry 0xffff, 0xfff */
 	struct module *module;
@@ -134,6 +132,7 @@
 	/* extension handling */
 	struct saa7146_extension	*ext;		/* indicates if handled by extension */
 	void				*ext_priv;	/* pointer for extension private use (most likely some private data) */
+	struct saa7146_ext_vv		*ext_vv_data;
 
 	/* per device video/vbi informations (if available) */
 	struct saa7146_vv	*vv_data;
diff -Nru a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h
--- a/include/media/saa7146_vv.h	Sat Jul 19 12:54:22 2003
+++ b/include/media/saa7146_vv.h	Sat Jul 19 12:54:22 2003
@@ -10,12 +10,10 @@
 #define BUFFER_TIMEOUT     (HZ/2)  /* 0.5 seconds */
 
 #define WRITE_RPS0(x) do { \
-	static int count = 0;	\
 	dev->d_rps0.cpu_addr[ count++ ] = cpu_to_le32(x); \
 	} while (0);
 
 #define WRITE_RPS1(x) do { \
-	static int count = 0;	\
 	dev->d_rps1.cpu_addr[ count++ ] = cpu_to_le32(x); \
 	} while (0);
 
@@ -41,13 +39,13 @@
 	char          *name;
 	v4l2_std_id   id;
 
-	int v_offset;
-	int v_field;
-	int v_calc;
+	int v_offset;	/* number of lines of vertical offset before processing */
+	int v_field;	/* number of lines in a field for HPS to process */
+	int v_calc;	/* number of vertical active lines */
 	
-	int h_offset;
-	int h_pixels;
-	int h_calc;
+	int h_offset;	/* horizontal offset of processing window */
+	int h_pixels;	/* number of horizontal pixels to process */
+	int h_calc;	/* number of horizontal active pixels */
 	
 	int v_max_out;
 	int h_max_out;
@@ -122,6 +120,7 @@
 	/* video capture */
 	struct saa7146_dmaqueue		video_q;
 	struct saa7146_fh		*streaming;
+	enum v4l2_field			last_field;
 
 	/* common: fixme? shouldn't this be in saa7146_fh?
 	   (this leads to a more complicated question: shall the driver
@@ -166,7 +165,7 @@
 	int (*std_callback)(struct saa7146_dev*, struct saa7146_standard *);
 		
 	struct saa7146_extension_ioctls *ioctls;
-	int (*ioctl)(struct saa7146_dev*, unsigned int cmd, void *arg);
+	int (*ioctl)(struct saa7146_fh*, unsigned int cmd, void *arg);
 };
 
 struct saa7146_use_ops  {
@@ -188,7 +187,7 @@
 void saa7146_buffer_timeout(unsigned long data);
 void saa7146_dma_free(struct saa7146_dev *dev,struct saa7146_buf *buf);
 
-int saa7146_vv_init(struct saa7146_dev* dev);
+int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv);
 int saa7146_vv_release(struct saa7146_dev* dev);
 
 
@@ -201,6 +200,8 @@
 
 /* from saa7146_video.c */
 extern struct saa7146_use_ops saa7146_video_uops;
+int saa7146_start_preview(struct saa7146_fh *fh);
+int saa7146_stop_preview(struct saa7146_fh *fh);
 
 /* from saa7146_vbi.c */
 extern struct saa7146_use_ops saa7146_vbi_uops;
@@ -214,35 +215,6 @@
 /* sync inputs */
 #define SAA7146_HPS_SYNC_PORT_A		0x00
 #define SAA7146_HPS_SYNC_PORT_B		0x01
-
-/* number of vertical active lines */
-#define V_ACTIVE_LINES_PAL	576
-#define V_ACTIVE_LINES_NTSC	480
-#define V_ACTIVE_LINES_SECAM	576
-
-/* number of lines in a field for HPS to process */
-#define V_FIELD_PAL	288
-#define V_FIELD_NTSC	240
-#define V_FIELD_SECAM	288
-
-/* number of lines of vertical offset before processing */
-#define V_OFFSET_PAL	0x17
-#define V_OFFSET_NTSC	0x16
-#define V_OFFSET_SECAM	0x14
-
-/* number of horizontal pixels to process */
-#define H_PIXELS_PAL	680
-#define H_PIXELS_NTSC	708
-#define H_PIXELS_SECAM	720
-
-/* horizontal offset of processing window */
-#define H_OFFSET_PAL	0x14
-#define H_OFFSET_NTSC	0x06
-#define H_OFFSET_SECAM	0x14
-
-#define SAA7146_PAL_VALUES 	V_OFFSET_PAL, V_FIELD_PAL, V_ACTIVE_LINES_PAL, H_OFFSET_PAL, H_PIXELS_PAL, H_PIXELS_PAL+1, V_ACTIVE_LINES_PAL, 768
-#define SAA7146_NTSC_VALUES	V_OFFSET_NTSC, V_FIELD_NTSC, V_ACTIVE_LINES_NTSC, H_OFFSET_NTSC, H_PIXELS_NTSC, H_PIXELS_NTSC+1, V_ACTIVE_LINES_NTSC, 640
-#define SAA7146_SECAM_VALUES	V_OFFSET_SECAM, V_FIELD_SECAM, V_ACTIVE_LINES_SECAM, H_OFFSET_SECAM, H_PIXELS_SECAM, H_PIXELS_SECAM+1, V_ACTIVE_LINES_SECAM, 768
 
 /* some memory sizes */
 #define SAA7146_CLIPPING_MEM	(14*PAGE_SIZE)
diff -Nru a/include/net/ip_vs.h b/include/net/ip_vs.h
--- a/include/net/ip_vs.h	Sat Jul 19 12:54:21 2003
+++ b/include/net/ip_vs.h	Sat Jul 19 12:54:21 2003
@@ -887,7 +887,6 @@
 extern int sysctl_ip_vs_expire_nodest_conn;
 extern int sysctl_ip_vs_sync_threshold[2];
 extern int sysctl_ip_vs_nat_icmp_send;
-extern atomic_t ip_vs_dropentry;
 extern struct ip_vs_stats ip_vs_stats;
 
 extern struct ip_vs_service *
@@ -902,7 +901,6 @@
 ip_vs_lookup_real_service(__u16 protocol, __u32 daddr, __u16 dport);
 extern int ip_vs_use_count_inc(void);
 extern void ip_vs_use_count_dec(void);
-extern void update_defense_level(void);
 extern int ip_vs_control_init(void);
 extern void ip_vs_control_cleanup(void);
 
diff -Nru a/include/pcmcia/ss.h b/include/pcmcia/ss.h
--- a/include/pcmcia/ss.h	Sat Jul 19 12:54:29 2003
+++ b/include/pcmcia/ss.h	Sat Jul 19 12:54:29 2003
@@ -51,6 +51,7 @@
 #define SS_3VCARD	0x1000
 #define SS_XVCARD	0x2000
 #define SS_PENDING	0x4000
+#define SS_ZVCARD	0x8000
 
 /* InquireSocket capabilities */
 #define SS_CAP_PAGE_REGS	0x0001
@@ -209,6 +210,10 @@
 	/* socket operations */
 	struct pccard_operations *	ops;
 
+	/* Zoom video behaviour is so chip specific its not worth adding
+	   this to _ops */
+	void 				(*zoom_video)(struct pcmcia_socket *, int);
+                           
 	/* state thread */
 	struct semaphore		skt_sem;	/* protects socket h/w state */
 
diff -Nru a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
--- a/include/scsi/scsi_device.h	Sat Jul 19 12:54:21 2003
+++ b/include/scsi/scsi_device.h	Sat Jul 19 12:54:21 2003
@@ -11,8 +11,6 @@
 
 
 struct scsi_device {
-	struct class_device	sdev_classdev;
-
 	struct list_head    siblings;   /* list of all devices on this host */
 	struct list_head    same_target_siblings; /* just the devices sharing same target id */
 	struct Scsi_Host *host;
@@ -86,10 +84,11 @@
 	unsigned int max_device_blocked; /* what device_blocked counts down from  */
 #define SCSI_DEFAULT_DEVICE_BLOCKED	3
 
-	struct device sdev_driverfs_dev;
+	struct device		sdev_gendev;
+	struct class_device	sdev_classdev;
 };
 #define	to_scsi_device(d)	\
-	container_of(d, struct scsi_device, sdev_driverfs_dev)
+	container_of(d, struct scsi_device, sdev_gendev)
 
 extern struct scsi_device *scsi_add_device(struct Scsi_Host *,
 		uint, uint, uint);
diff -Nru a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
--- a/include/scsi/scsi_host.h	Sat Jul 19 12:54:23 2003
+++ b/include/scsi/scsi_host.h	Sat Jul 19 12:54:23 2003
@@ -329,12 +329,12 @@
 #define SCSI_DEFAULT_HOST_BLOCKED	7
 
 	/*
-	 * Pointer to the sysfs class properties for this host
+	 * Pointer to the sysfs class properties for this host, NULL terminated.
 	 */
 	struct class_device_attribute **shost_attrs;
 
 	/*
-	 * Pointer to the SCSI device properties for this host
+	 * Pointer to the SCSI device properties for this host, NULL terminated.
 	 */
 	struct device_attribute **sdev_attrs;
 
@@ -442,12 +442,6 @@
 	 */
 	unsigned int max_host_blocked;
 
-	/* 
-	 * Support for sysfs
-	 */
-	struct device host_gendev;
-	struct class_device class_dev;
-
 	/* legacy crap */
 	unsigned long base;
 	unsigned long io_port;
@@ -455,6 +449,9 @@
 	unsigned char dma_channel;
 	unsigned int  irq;
 
+	/* ldm bits */
+	struct device		shost_gendev;
+	struct class_device	shost_classdev;
 
 	/*
 	 * List of hosts per template.
@@ -474,12 +471,13 @@
 		__attribute__ ((aligned (sizeof(unsigned long))));
 };
 #define		dev_to_shost(d)		\
-	container_of(d, struct Scsi_Host, host_gendev)
+	container_of(d, struct Scsi_Host, shost_gendev)
 #define		class_to_shost(d)	\
-	container_of(d, struct Scsi_Host, class_dev)
+	container_of(d, struct Scsi_Host, shost_classdev)
 
 extern struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *, int);
 extern int scsi_add_host(struct Scsi_Host *, struct device *);
+extern void scsi_scan_host(struct Scsi_Host *);
 extern int scsi_remove_host(struct Scsi_Host *);
 extern void scsi_host_get(struct Scsi_Host *);
 extern void scsi_host_put(struct Scsi_Host *t);
@@ -495,15 +493,13 @@
 static inline void scsi_set_device(struct Scsi_Host *shost,
                                    struct device *dev)
 {
-        shost->host_gendev.parent = dev;
+        shost->shost_gendev.parent = dev;
 }
 
 static inline struct device *scsi_get_device(struct Scsi_Host *shost)
 {
-        return shost->host_gendev.parent;
+        return shost->shost_gendev.parent;
 }
-
-extern void scsi_sysfs_release_attributes(struct scsi_host_template *);
 
 extern void scsi_unblock_requests(struct Scsi_Host *);
 extern void scsi_block_requests(struct Scsi_Host *);
diff -Nru a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h
--- a/include/scsi/scsi_request.h	Sat Jul 19 12:54:30 2003
+++ b/include/scsi/scsi_request.h	Sat Jul 19 12:54:30 2003
@@ -56,7 +56,7 @@
 			int timeout, int retries);
 
 struct scsi_mode_data {
-	__u16	length;
+	__u32	length;
 	__u16	block_descriptor_length;
 	__u8	medium_type;
 	__u8	device_specific;
diff -Nru a/init/do_mounts.h b/init/do_mounts.h
--- a/init/do_mounts.h	Sat Jul 19 12:54:26 2003
+++ b/init/do_mounts.h	Sat Jul 19 12:54:26 2003
@@ -6,7 +6,7 @@
 #include <linux/unistd.h>
 #include <linux/slab.h>
 #include <linux/mount.h>
-#include <linux/blk.h>
+#include <linux/major.h>
 #include <linux/root_dev.h>
 
 asmlinkage long sys_unlink(const char *name);
diff -Nru a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
--- a/init/do_mounts_initrd.c	Sat Jul 19 12:54:22 2003
+++ b/init/do_mounts_initrd.c	Sat Jul 19 12:54:22 2003
@@ -5,6 +5,7 @@
 #include <linux/ext2_fs.h>
 #include <linux/romfs_fs.h>
 #include <linux/initrd.h>
+#include <linux/sched.h>
 
 #include "do_mounts.h"
 
diff -Nru a/init/do_mounts_rd.c b/init/do_mounts_rd.c
--- a/init/do_mounts_rd.c	Sat Jul 19 12:54:26 2003
+++ b/init/do_mounts_rd.c	Sat Jul 19 12:54:26 2003
@@ -5,6 +5,7 @@
 #include <linux/ext2_fs.h>
 #include <linux/romfs_fs.h>
 #include <linux/initrd.h>
+#include <linux/string.h>
 
 #include "do_mounts.h"
 
diff -Nru a/init/main.c b/init/main.c
--- a/init/main.c	Sat Jul 19 12:54:23 2003
+++ b/init/main.c	Sat Jul 19 12:54:23 2003
@@ -23,7 +23,6 @@
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
-#include <linux/blk.h>
 #include <linux/initrd.h>
 #include <linux/hdreg.h>
 #include <linux/bootmem.h>
diff -Nru a/kernel/compat.c b/kernel/compat.c
--- a/kernel/compat.c	Sat Jul 19 12:54:25 2003
+++ b/kernel/compat.c	Sat Jul 19 12:54:25 2003
@@ -425,9 +425,11 @@
 				    &kernel_mask);
 	set_fs(old_fs);
 
-	if (ret > 0)
+	if (ret > 0) {
+		ret = sizeof(compat_ulong_t);
 		if (put_user(kernel_mask, user_mask_ptr))
 			return -EFAULT;
+	}
 
 	return ret;
 }
diff -Nru a/kernel/extable.c b/kernel/extable.c
--- a/kernel/extable.c	Sat Jul 19 12:54:24 2003
+++ b/kernel/extable.c	Sat Jul 19 12:54:24 2003
@@ -17,10 +17,10 @@
 */
 #include <linux/module.h>
 #include <asm/uaccess.h>
+#include <asm/sections.h>
 
 extern const struct exception_table_entry __start___ex_table[];
 extern const struct exception_table_entry __stop___ex_table[];
-extern char _stext[], _etext[], _sinittext[], _einittext[];
 
 /* Given an address, look for it in the exception tables. */
 const struct exception_table_entry *search_exception_tables(unsigned long addr)
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	Sat Jul 19 12:54:22 2003
+++ b/kernel/fork.c	Sat Jul 19 12:54:22 2003
@@ -53,13 +53,6 @@
 
 rwlock_t tasklist_lock __cacheline_aligned = RW_LOCK_UNLOCKED;  /* outer */
 
-/*
- * A per-CPU task cache - this relies on the fact that
- * the very last portion of sys_exit() is executed with
- * preemption turned off.
- */
-static task_t *task_cache[NR_CPUS] __cacheline_aligned;
-
 int nr_processes(void)
 {
 	int cpu;
@@ -80,26 +73,8 @@
 
 static void free_task(struct task_struct *tsk)
 {
-	/*
-	 * The task cache is effectively disabled right now.
-	 * Do we want it? The slab cache already has per-cpu
-	 * stuff, but the thread info (usually a order-1 page
-	 * allocation) doesn't.
-	 */
-	if (tsk != current) {
-		free_thread_info(tsk->thread_info);
-		free_task_struct(tsk);
-	} else {
-		int cpu = get_cpu();
-
-		tsk = task_cache[cpu];
-		if (tsk) {
-			free_thread_info(tsk->thread_info);
-			free_task_struct(tsk);
-		}
-		task_cache[cpu] = current;
-		put_cpu();
-	}
+	free_thread_info(tsk->thread_info);
+	free_task_struct(tsk);
 }
 
 void __put_task_struct(struct task_struct *tsk)
@@ -220,25 +195,18 @@
 {
 	struct task_struct *tsk;
 	struct thread_info *ti;
-	int cpu = get_cpu();
 
 	prepare_to_copy(orig);
 
-	tsk = task_cache[cpu];
-	task_cache[cpu] = NULL;
-	put_cpu();
-	if (!tsk) {
-		tsk = alloc_task_struct();
-		if (!tsk)
-			return NULL;
-
-		ti = alloc_thread_info(tsk);
-		if (!ti) {
-			free_task_struct(tsk);
-			return NULL;
-		}
-	} else
-		ti = tsk->thread_info;
+	tsk = alloc_task_struct();
+	if (!tsk)
+		return NULL;
+
+	ti = alloc_thread_info(tsk);
+	if (!ti) {
+		free_task_struct(tsk);
+		return NULL;
+	}
 
 	*ti = *orig->thread_info;
 	*tsk = *orig;
@@ -791,8 +759,10 @@
 		goto fork_out;
 
 	retval = -EAGAIN;
-	if (atomic_read(&p->user->processes) >= p->rlim[RLIMIT_NPROC].rlim_cur) {
-		if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE))
+	if (atomic_read(&p->user->processes) >=
+			p->rlim[RLIMIT_NPROC].rlim_cur) {
+		if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
+				p->user != &root_user)
 			goto bad_fork_free;
 	}
 
@@ -1106,7 +1076,7 @@
 			init_completion(&vfork);
 		}
 
-		if (p->ptrace & PT_PTRACED) {
+		if ((p->ptrace & PT_PTRACED) || (clone_flags & CLONE_STOPPED)) {
 			/*
 			 * We'll start up with an immediate SIGSTOP.
 			 */
@@ -1114,7 +1084,9 @@
 			set_tsk_thread_flag(p, TIF_SIGPENDING);
 		}
 
-		wake_up_forked_process(p);		/* do this last */
+		p->state = TASK_STOPPED;
+		if (!(clone_flags & CLONE_STOPPED))
+			wake_up_forked_process(p);	/* do this last */
 		++total_forks;
 
 		if (unlikely (trace)) {
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c	Sat Jul 19 12:54:21 2003
+++ b/kernel/ksyms.c	Sat Jul 19 12:54:21 2003
@@ -605,6 +605,9 @@
 EXPORT_SYMBOL(__per_cpu_offset);
 #endif
 
+EXPORT_SYMBOL(set_fs_pwd);
+EXPORT_SYMBOL(set_fs_root);
+
 /* debug */
 EXPORT_SYMBOL(dump_stack);
 EXPORT_SYMBOL(ptrace_notify);
diff -Nru a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c	Sat Jul 19 12:54:26 2003
+++ b/kernel/module.c	Sat Jul 19 12:54:26 2003
@@ -98,6 +98,17 @@
 }
 EXPORT_SYMBOL(init_module);
 
+/* A thread that wants to hold a reference to a module only while it
+ * is running can call ths to safely exit.
+ * nfsd and lockd use this.
+ */
+void __module_put_and_exit(struct module *mod, long code)
+{
+	module_put(mod);
+	do_exit(code);
+}
+EXPORT_SYMBOL(__module_put_and_exit);
+	
 /* Find a module section: 0 means not found. */
 static unsigned int find_sec(Elf_Ehdr *hdr,
 			     Elf_Shdr *sechdrs,
@@ -374,9 +385,9 @@
 
 	INIT_LIST_HEAD(&mod->modules_which_use_me);
 	for (i = 0; i < NR_CPUS; i++)
-		atomic_set(&mod->ref[i].count, 0);
+		local_set(&mod->ref[i].count, 0);
 	/* Hold reference count during initialization. */
-	atomic_set(&mod->ref[smp_processor_id()].count, 1);
+	local_set(&mod->ref[smp_processor_id()].count, 1);
 	/* Backwards compatibility macros put refcount during init. */
 	mod->waiter = current;
 }
@@ -599,7 +610,7 @@
 	unsigned int i, total = 0;
 
 	for (i = 0; i < NR_CPUS; i++)
-		total += atomic_read(&mod->ref[i].count);
+		total += local_read(&mod->ref[i].count);
 	return total;
 }
 EXPORT_SYMBOL(module_refcount);
@@ -610,7 +621,10 @@
 #ifdef CONFIG_MODULE_FORCE_UNLOAD
 static inline int try_force(unsigned int flags)
 {
-	return (flags & O_TRUNC);
+	int ret = (flags & O_TRUNC);
+	if (ret)
+		tainted |= TAINT_FORCED_MODULE;
+	return ret;
 }
 #else
 static inline int try_force(unsigned int flags)
diff -Nru a/kernel/profile.c b/kernel/profile.c
--- a/kernel/profile.c	Sat Jul 19 12:54:29 2003
+++ b/kernel/profile.c	Sat Jul 19 12:54:29 2003
@@ -8,8 +8,7 @@
 #include <linux/bootmem.h>
 #include <linux/notifier.h>
 #include <linux/mm.h>
-
-extern char _stext, _etext;
+#include <asm/sections.h>
 
 unsigned int * prof_buffer;
 unsigned long prof_len;
@@ -36,7 +35,7 @@
 		return;
  
 	/* only text is profiled */
-	prof_len = (unsigned long) &_etext - (unsigned long) &_stext;
+	prof_len = _etext - _stext;
 	prof_len >>= prof_shift;
 		
 	size = prof_len * sizeof(unsigned int) + PAGE_SIZE - 1;
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	Sat Jul 19 12:54:27 2003
+++ b/kernel/sched.c	Sat Jul 19 12:54:27 2003
@@ -2080,7 +2080,7 @@
 }
 
 /**
- * sys_sched_get_priority_mix - return minimum RT priority.
+ * sys_sched_get_priority_min - return minimum RT priority.
  * @policy: scheduling class.
  *
  * this syscall returns the minimum rt_priority that can be used
@@ -2541,7 +2541,7 @@
 		if (time_before(jiffies, prev_jiffy + HZ))
 			return;
 		prev_jiffy = jiffies;
-		printk(KERN_ERR "Debug: sleeping function called from illegal"
+		printk(KERN_ERR "Debug: sleeping function called from invalid"
 				" context at %s:%d\n", file, line);
 		dump_stack();
 	}
diff -Nru a/kernel/suspend.c b/kernel/suspend.c
--- a/kernel/suspend.c	Sat Jul 19 12:54:23 2003
+++ b/kernel/suspend.c	Sat Jul 19 12:54:23 2003
@@ -52,7 +52,6 @@
 #include <linux/genhd.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/blk.h>
 #include <linux/swap.h>
 #include <linux/pm.h>
 #include <linux/device.h>
diff -Nru a/kernel/sys.c b/kernel/sys.c
--- a/kernel/sys.c	Sat Jul 19 12:54:22 2003
+++ b/kernel/sys.c	Sat Jul 19 12:54:22 2003
@@ -601,6 +601,14 @@
 	new_user = alloc_uid(new_ruid);
 	if (!new_user)
 		return -EAGAIN;
+
+	if (atomic_read(&new_user->processes) >=
+				current->rlim[RLIMIT_NPROC].rlim_cur &&
+			new_user != &root_user) {
+		free_uid(new_user);
+		return -EAGAIN;
+	}
+
 	switch_uid(new_user);
 
 	if(dumpclear)
@@ -1159,6 +1167,7 @@
 asmlinkage long sys_sethostname(char __user *name, int len)
 {
 	int errno;
+	char tmp[__NEW_UTS_LEN];
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
@@ -1166,7 +1175,8 @@
 		return -EINVAL;
 	down_write(&uts_sem);
 	errno = -EFAULT;
-	if (!copy_from_user(system_utsname.nodename, name, len)) {
+	if (!copy_from_user(tmp, name, len)) {
+		memcpy(system_utsname.nodename, tmp, len);
 		system_utsname.nodename[len] = 0;
 		errno = 0;
 	}
@@ -1198,6 +1208,7 @@
 asmlinkage long sys_setdomainname(char __user *name, int len)
 {
 	int errno;
+	char tmp[__NEW_UTS_LEN];
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
@@ -1206,9 +1217,10 @@
 
 	down_write(&uts_sem);
 	errno = -EFAULT;
-	if (!copy_from_user(system_utsname.domainname, name, len)) {
-		errno = 0;
+	if (!copy_from_user(tmp, name, len)) {
+		memcpy(system_utsname.domainname, tmp, len);
 		system_utsname.domainname[len] = 0;
+		errno = 0;
 	}
 	up_write(&uts_sem);
 	return errno;
diff -Nru a/kernel/time.c b/kernel/time.c
--- a/kernel/time.c	Sat Jul 19 12:54:23 2003
+++ b/kernel/time.c	Sat Jul 19 12:54:23 2003
@@ -66,7 +66,7 @@
  * architectures that need it).
  */
  
-asmlinkage long sys_stime(int * tptr)
+asmlinkage long sys_stime(time_t *tptr)
 {
 	struct timespec tv;
 
@@ -160,22 +160,25 @@
 	return 0;
 }
 
-asmlinkage long sys_settimeofday(struct timeval __user *tv, struct timezone __user *tz)
+asmlinkage long sys_settimeofday(struct timeval __user *tv,
+				struct timezone __user *tz)
 {
-	struct timespec	new_tv;
+	struct timeval user_tv;
+	struct timespec	new_ts;
 	struct timezone new_tz;
 
 	if (tv) {
-		if (copy_from_user(&new_tv, tv, sizeof(*tv)))
+		if (copy_from_user(&user_tv, tv, sizeof(*tv)))
 			return -EFAULT;
-		new_tv.tv_nsec *= NSEC_PER_USEC;
+		new_ts.tv_sec = user_tv.tv_sec;
+		new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC;
 	}
 	if (tz) {
 		if (copy_from_user(&new_tz, tz, sizeof(*tz)))
 			return -EFAULT;
 	}
 
-	return do_sys_settimeofday(tv ? &new_tv : NULL, tz ? &new_tz : NULL);
+	return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
 }
 
 long pps_offset;		/* pps time offset (us) */
diff -Nru a/mm/bootmem.c b/mm/bootmem.c
--- a/mm/bootmem.c	Sat Jul 19 12:54:24 2003
+++ b/mm/bootmem.c	Sat Jul 19 12:54:24 2003
@@ -183,7 +183,7 @@
 	for (i = preferred; i < eidx; i += incr) {
 		unsigned long j;
 		i = find_next_zero_bit(bdata->node_bootmem_map, eidx, i);
-		i = (i + incr - 1) & -incr;
+		i = ALIGN(i, incr);
 		if (test_bit(i, bdata->node_bootmem_map))
 			continue;
 		for (j = i + 1; j < i + areasize; ++j) {
@@ -195,7 +195,7 @@
 		start = i;
 		goto found;
 	fail_block:
-		;
+		i = ALIGN(j, incr);
 	}
 
 	if (preferred > offset) {
diff -Nru a/mm/slab.c b/mm/slab.c
--- a/mm/slab.c	Sat Jul 19 12:54:26 2003
+++ b/mm/slab.c	Sat Jul 19 12:54:26 2003
@@ -1628,7 +1628,13 @@
 	kfree_debugcheck(objp);
 	page = virt_to_page(objp);
 
-	BUG_ON(GET_PAGE_CACHE(page) != cachep);
+	if (GET_PAGE_CACHE(page) != cachep) {
+		printk(KERN_ERR "mismatch in kmem_cache_free: expected cache %p, got %p\n",
+				GET_PAGE_CACHE(page),cachep);
+		printk(KERN_ERR "%p is %s.\n", cachep, cachep->name);
+		printk(KERN_ERR "%p is %s.\n", GET_PAGE_CACHE(page), GET_PAGE_CACHE(page)->name);
+		WARN_ON(1);
+	}
 	slabp = GET_PAGE_SLAB(page);
 
 	if (cachep->flags & SLAB_STORE_USER) {
@@ -2482,11 +2488,11 @@
 		seq_puts(m, "slabinfo - version: 2.0\n");
 #endif
 		seq_puts(m, "# name            <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab>");
-		seq_puts(m, " : tunables <batchcount> <limit <sharedfactor>");
+		seq_puts(m, " : tunables <batchcount> <limit> <sharedfactor>");
 		seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
 #if STATS
 		seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped> <error> <maxfreeable> <freelimit>");
-		seq_puts(m, " : cpustat <allochit <allocmiss <freehit <freemiss>");
+		seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit <freemiss>");
 #endif
 		seq_putc(m, '\n');
 	}
diff -Nru a/net/atm/br2684.c b/net/atm/br2684.c
--- a/net/atm/br2684.c	Sat Jul 19 12:54:24 2003
+++ b/net/atm/br2684.c	Sat Jul 19 12:54:24 2003
@@ -16,9 +16,12 @@
 #include <linux/ip.h>
 #include <asm/uaccess.h>
 #include <net/arp.h>
+#include <linux/atm.h>
+#include <linux/atmdev.h>
 
 #include <linux/atmbr2684.h>
 
+#include "common.h"
 #include "ipcommon.h"
 
 /*
@@ -768,8 +771,6 @@
 
 extern struct proc_dir_entry *atm_proc_root;	/* from proc.c */
 
-extern int (*br2684_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
-
 /* the following avoids some spurious warnings from the compiler */
 #define UNUSED __attribute__((unused))
 
@@ -779,14 +780,14 @@
 	if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL)
 		return -ENOMEM;
 	p->proc_fops = &br2684_proc_operations;
-	br2684_ioctl_hook = br2684_ioctl;
+	br2684_ioctl_set(br2684_ioctl);
 	return 0;
 }
 
 static void __exit UNUSED br2684_exit(void)
 {
 	struct br2684_dev *brdev;
-	br2684_ioctl_hook = NULL;
+	br2684_ioctl_set(NULL);
 	remove_proc_entry("br2684", atm_proc_root);
 	while (!list_empty(&br2684_devs)) {
 		brdev = list_entry_brdev(br2684_devs.next);
diff -Nru a/net/atm/clip.c b/net/atm/clip.c
--- a/net/atm/clip.c	Sat Jul 19 12:54:30 2003
+++ b/net/atm/clip.c	Sat Jul 19 12:54:30 2003
@@ -67,7 +67,7 @@
 	ctrl->ip = ip;
 	atm_force_charge(atmarpd,skb->truesize);
 	skb_queue_tail(&atmarpd->sk->sk_receive_queue, skb);
-	wake_up(&atmarpd->sleep);
+	atmarpd->sk->sk_data_ready(atmarpd->sk, skb->len);
 	return 0;
 }
 
diff -Nru a/net/atm/common.c b/net/atm/common.c
--- a/net/atm/common.c	Sat Jul 19 12:54:30 2003
+++ b/net/atm/common.c	Sat Jul 19 12:54:30 2003
@@ -129,14 +129,34 @@
 #endif
 
 #if defined(CONFIG_PPPOATM) || defined(CONFIG_PPPOATM_MODULE)
-int (*pppoatm_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
-EXPORT_SYMBOL(pppoatm_ioctl_hook);
+static DECLARE_MUTEX(pppoatm_ioctl_mutex);
+
+static int (*pppoatm_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
+
+void pppoatm_ioctl_set(int (*hook)(struct atm_vcc *, unsigned int, unsigned long))
+{
+	down(&pppoatm_ioctl_mutex);
+	pppoatm_ioctl_hook = hook;
+	up(&pppoatm_ioctl_mutex);
+}
+#ifdef CONFIG_PPPOATM_MODULE
+EXPORT_SYMBOL(pppoatm_ioctl_set);
+#endif
 #endif
 
 #if defined(CONFIG_ATM_BR2684) || defined(CONFIG_ATM_BR2684_MODULE)
-int (*br2684_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
+static DECLARE_MUTEX(br2684_ioctl_mutex);
+
+static int (*br2684_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
+
+void br2684_ioctl_set(int (*hook)(struct atm_vcc *, unsigned int, unsigned long))
+{
+	down(&br2684_ioctl_mutex);
+	br2684_ioctl_hook = hook;
+	up(&br2684_ioctl_mutex);
+}
 #ifdef CONFIG_ATM_BR2684_MODULE
-EXPORT_SYMBOL(br2684_ioctl_hook);
+EXPORT_SYMBOL(br2684_ioctl_set);
 #endif
 #endif
 
@@ -215,6 +235,37 @@
 
 	kfree(sk->sk_protinfo);
 }
+
+static void vcc_def_wakeup(struct sock *sk)
+{
+	read_lock(&sk->sk_callback_lock);
+	if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+		wake_up(sk->sk_sleep);
+	read_unlock(&sk->sk_callback_lock);
+}
+
+static inline int vcc_writable(struct sock *sk)
+{
+	struct atm_vcc *vcc = atm_sk(sk);
+
+	return (vcc->qos.txtp.max_sdu +
+	        atomic_read(&sk->sk_wmem_alloc)) <= sk->sk_sndbuf;
+}
+
+static void vcc_write_space(struct sock *sk)
+{       
+	read_lock(&sk->sk_callback_lock);
+
+	if (vcc_writable(sk)) {
+		if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+			wake_up_interruptible(sk->sk_sleep);
+
+		sk_wake_async(sk, 2, POLL_OUT);
+	}
+
+	read_unlock(&sk->sk_callback_lock);
+}
+
  
 int vcc_create(struct socket *sock, int protocol, int family)
 {
@@ -227,7 +278,9 @@
 	sk = sk_alloc(family, GFP_KERNEL, 1, NULL);
 	if (!sk)
 		return -ENOMEM;
-	sock_init_data(NULL, sk);
+	sock_init_data(sock, sk);
+	sk->sk_state_change = vcc_def_wakeup;
+	sk->sk_write_space = vcc_write_space;
 
 	vcc = atm_sk(sk) = kmalloc(sizeof(*vcc), GFP_KERNEL);
 	if (!vcc) {
@@ -238,7 +291,6 @@
 	memset(vcc, 0, sizeof(*vcc));
 	vcc->sk = sk;
 	vcc->dev = NULL;
-	vcc->callback = NULL;
 	memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc));
 	memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc));
 	vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */
@@ -249,8 +301,6 @@
 	vcc->push_oam = NULL;
 	vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */
 	vcc->atm_options = vcc->aal_options = 0;
-	init_waitqueue_head(&vcc->sleep);
-	sk->sk_sleep = &vcc->sleep;
 	sk->sk_destruct = vcc_sock_destruct;
 	sock->sk = sk;
 	return 0;
@@ -300,9 +350,9 @@
 void vcc_release_async(struct atm_vcc *vcc, int reply)
 {
 	set_bit(ATM_VF_CLOSE, &vcc->flags);
-	vcc->reply = reply;
 	vcc->sk->sk_err = -reply;
-	wake_up(&vcc->sleep);
+	clear_bit(ATM_VF_WAITING, &vcc->flags);
+	vcc->sk->sk_state_change(vcc->sk);
 }
 
 
@@ -475,7 +525,7 @@
 	vcc = ATM_SD(sock);
 	if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
 	    test_bit(ATM_VF_CLOSE,&vcc->flags))
-		return vcc->reply;
+		return -sk->sk_err;
 	if (!test_bit(ATM_VF_READY, &vcc->flags))
 		return 0;
 
@@ -532,7 +582,7 @@
 	vcc = ATM_SD(sock);
 	if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
 	    test_bit(ATM_VF_CLOSE, &vcc->flags)) {
-		error = vcc->reply;
+		error = -sk->sk_err;
 		goto out;
 	}
 	if (!test_bit(ATM_VF_READY, &vcc->flags)) {
@@ -549,7 +599,7 @@
 	}
 	/* verify_area is done by net/socket.c */
 	eff = (size+3) & ~3; /* align to word boundary */
-	prepare_to_wait(&vcc->sleep, &wait, TASK_INTERRUPTIBLE);
+	prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
 	error = 0;
 	while (!(skb = alloc_tx(vcc,eff))) {
 		if (m->msg_flags & MSG_DONTWAIT) {
@@ -563,16 +613,16 @@
 		}
 		if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
 		    test_bit(ATM_VF_CLOSE,&vcc->flags)) {
-			error = vcc->reply;
+			error = -sk->sk_err;
 			break;
 		}
 		if (!test_bit(ATM_VF_READY,&vcc->flags)) {
 			error = -EPIPE;
 			break;
 		}
-		prepare_to_wait(&vcc->sleep, &wait, TASK_INTERRUPTIBLE);
+		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
 	}
-	finish_wait(&vcc->sleep, &wait);
+	finish_wait(sk->sk_sleep, &wait);
 	if (error)
 		goto out;
 	skb->dev = NULL; /* for paths shared with net_device interfaces */
@@ -591,29 +641,38 @@
 }
 
 
-unsigned int atm_poll(struct file *file,struct socket *sock,poll_table *wait)
+unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait)
 {
+	struct sock *sk = sock->sk;
 	struct atm_vcc *vcc;
 	unsigned int mask;
 
-	vcc = ATM_SD(sock);
-	poll_wait(file,&vcc->sleep,wait);
+	poll_wait(file, sk->sk_sleep, wait);
 	mask = 0;
-	if (skb_peek(&vcc->sk->sk_receive_queue))
-		mask |= POLLIN | POLLRDNORM;
-	if (test_bit(ATM_VF_RELEASED,&vcc->flags) ||
-	    test_bit(ATM_VF_CLOSE,&vcc->flags))
+
+	vcc = ATM_SD(sock);
+
+	/* exceptional events */
+	if (sk->sk_err)
+		mask = POLLERR;
+
+	if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
+	    test_bit(ATM_VF_CLOSE, &vcc->flags))
 		mask |= POLLHUP;
-	if (sock->state != SS_CONNECTING) {
-		if (vcc->qos.txtp.traffic_class != ATM_NONE &&
-		    vcc->qos.txtp.max_sdu +
-		    atomic_read(&vcc->sk->sk_wmem_alloc) <= vcc->sk->sk_sndbuf)
-			mask |= POLLOUT | POLLWRNORM;
-	}
-	else if (vcc->reply != WAITING) {
-			mask |= POLLOUT | POLLWRNORM;
-			if (vcc->reply) mask |= POLLERR;
-		}
+
+	/* readable? */
+	if (!skb_queue_empty(&sk->sk_receive_queue))
+		mask |= POLLIN | POLLRDNORM;
+
+	/* writable? */
+	if (sock->state == SS_CONNECTING &&
+	    test_bit(ATM_VF_WAITING, &vcc->flags))
+		return mask;
+
+	if (vcc->qos.txtp.traffic_class != ATM_NONE &&
+	    vcc_writable(vcc->sk))
+		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
+
 	return mask;
 }
 
@@ -859,19 +918,22 @@
 		default:
 			break;
 	}
+	error = -ENOIOCTLCMD;
 #if defined(CONFIG_PPPOATM) || defined(CONFIG_PPPOATM_MODULE)
-	if (pppoatm_ioctl_hook) {
+	down(&pppoatm_ioctl_mutex);
+	if (pppoatm_ioctl_hook)
 		error = pppoatm_ioctl_hook(vcc, cmd, arg);
-		if (error != -ENOIOCTLCMD)
-			goto done;
-	}
+	up(&pppoatm_ioctl_mutex);
+	if (error != -ENOIOCTLCMD)
+		goto done;
 #endif
 #if defined(CONFIG_ATM_BR2684) || defined(CONFIG_ATM_BR2684_MODULE)
-	if (br2684_ioctl_hook) {
+	down(&br2684_ioctl_mutex);
+	if (br2684_ioctl_hook)
 		error = br2684_ioctl_hook(vcc, cmd, arg);
-		if (error != -ENOIOCTLCMD)
-			goto done;
-	}
+	up(&br2684_ioctl_mutex);
+	if (error != -ENOIOCTLCMD)
+		goto done;
 #endif
 
 	error = atm_dev_ioctl(cmd, arg);
diff -Nru a/net/atm/common.h b/net/atm/common.h
--- a/net/atm/common.h	Sat Jul 19 12:54:26 2003
+++ b/net/atm/common.h	Sat Jul 19 12:54:26 2003
@@ -17,7 +17,7 @@
 		int size, int flags);
 int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
 		int total_len);
-unsigned int atm_poll(struct file *file,struct socket *sock,poll_table *wait);
+unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait);
 int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
 int vcc_setsockopt(struct socket *sock, int level, int optname, char *optval,
 		   int optlen);
@@ -25,6 +25,9 @@
 		   int *optlen);
 
 void atm_shutdown_dev(struct atm_dev *dev);
+
+void pppoatm_ioctl_set(int (*hook)(struct atm_vcc *, unsigned int, unsigned long));
+void br2684_ioctl_set(int (*hook)(struct atm_vcc *, unsigned int, unsigned long));
 
 int atmpvc_init(void);
 void atmpvc_exit(void);
diff -Nru a/net/atm/lec.c b/net/atm/lec.c
--- a/net/atm/lec.c	Sat Jul 19 12:54:25 2003
+++ b/net/atm/lec.c	Sat Jul 19 12:54:25 2003
@@ -134,7 +134,7 @@
                 priv = (struct lec_priv *)dev->priv;
                 atm_force_charge(priv->lecd, skb2->truesize);
                 skb_queue_tail(&priv->lecd->sk->sk_receive_queue, skb2);
-                wake_up(&priv->lecd->sleep);
+                priv->lecd->sk->sk_data_ready(priv->lecd->sk, skb2->len);
         }
 
         return;
@@ -513,7 +513,7 @@
                         memcpy(skb2->data, mesg, sizeof(struct atmlec_msg));
                         atm_force_charge(priv->lecd, skb2->truesize);
                         skb_queue_tail(&priv->lecd->sk->sk_receive_queue, skb2);
-                        wake_up(&priv->lecd->sleep);
+                        priv->lecd->sk->sk_data_ready(priv->lecd->sk, skb2->len);
                 }
                 if (f != NULL) br_fdb_put_hook(f);
 #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
@@ -598,13 +598,13 @@
 
         atm_force_charge(priv->lecd, skb->truesize);
 	skb_queue_tail(&priv->lecd->sk->sk_receive_queue, skb);
-        wake_up(&priv->lecd->sleep);
+        priv->lecd->sk->sk_data_ready(priv->lecd->sk, skb->len);
 
         if (data != NULL) {
                 DPRINTK("lec: about to send %d bytes of data\n", data->len);
                 atm_force_charge(priv->lecd, data->truesize);
                 skb_queue_tail(&priv->lecd->sk->sk_receive_queue, data);
-                wake_up(&priv->lecd->sleep);
+                priv->lecd->sk->sk_data_ready(priv->lecd->sk, skb->len);
         }
 
         return 0;
@@ -686,7 +686,7 @@
         if (memcmp(skb->data, lec_ctrl_magic, 4) ==0) { /* Control frame, to daemon*/
                 DPRINTK("%s: To daemon\n",dev->name);
                 skb_queue_tail(&vcc->sk->sk_receive_queue, skb);
-                wake_up(&vcc->sleep);
+                vcc->sk->sk_data_ready(vcc->sk, skb->len);
         } else { /* Data frame, queue to protocol handlers */
                 unsigned char *dst;
 
diff -Nru a/net/atm/mpc.c b/net/atm/mpc.c
--- a/net/atm/mpc.c	Sat Jul 19 12:54:27 2003
+++ b/net/atm/mpc.c	Sat Jul 19 12:54:27 2003
@@ -669,7 +669,7 @@
 		dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev->name);
 		/* Pass control packets to daemon */
 		skb_queue_tail(&vcc->sk->sk_receive_queue, skb);
-		wake_up(&vcc->sleep);
+		vcc->sk->sk_data_ready(vcc->sk, skb->len);
 		return;
 	}
 
@@ -947,7 +947,7 @@
 	memcpy(skb->data, mesg, sizeof(struct k_message));
 	atm_force_charge(mpc->mpoad_vcc, skb->truesize);
 	skb_queue_tail(&mpc->mpoad_vcc->sk->sk_receive_queue, skb);
-	wake_up(&mpc->mpoad_vcc->sleep);
+	mpc->mpoad_vcc->sk->sk_data_ready(mpc->mpoad_vcc->sk, skb->len);
 
 	return 0;
 }
@@ -1226,7 +1226,7 @@
 
 	atm_force_charge(vcc, skb->truesize);
 	skb_queue_tail(&vcc->sk->sk_receive_queue, skb);
-	wake_up(&vcc->sleep);
+	vcc->sk->sk_data_ready(vcc->sk, skb->len);
 	dprintk("mpoa: purge_egress_shortcut: exiting:\n");
 
 	return;
diff -Nru a/net/atm/pppoatm.c b/net/atm/pppoatm.c
--- a/net/atm/pppoatm.c	Sat Jul 19 12:54:26 2003
+++ b/net/atm/pppoatm.c	Sat Jul 19 12:54:26 2003
@@ -44,6 +44,8 @@
 #include <linux/ppp_channel.h>
 #include <linux/atmppp.h>
 
+#include "common.h"
+
 #if 0
 #define DPRINTK(format, args...) \
 	printk(KERN_DEBUG "pppoatm: " format, ##args)
@@ -344,17 +346,15 @@
 /* the following avoids some spurious warnings from the compiler */
 #define UNUSED __attribute__((unused))
 
-extern int (*pppoatm_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
-
 static int __init UNUSED pppoatm_init(void)
 {
-	pppoatm_ioctl_hook = pppoatm_ioctl;
+	pppoatm_ioctl_set(pppoatm_ioctl);
 	return 0;
 }
 
 static void __exit UNUSED pppoatm_exit(void)
 {
-	pppoatm_ioctl_hook = NULL;
+	pppoatm_ioctl_set(NULL);
 }
 
 module_init(pppoatm_init);
diff -Nru a/net/atm/proc.c b/net/atm/proc.c
--- a/net/atm/proc.c	Sat Jul 19 12:54:24 2003
+++ b/net/atm/proc.c	Sat Jul 19 12:54:24 2003
@@ -224,7 +224,7 @@
 			here += sprintf(here, "%3d", vcc->sk->sk_family);
 	}
 	here += sprintf(here," %04lx  %5d %7d/%7d %7d/%7d\n",vcc->flags,
-	    vcc->reply,
+	    vcc->sk->sk_err,
 	    atomic_read(&vcc->sk->sk_wmem_alloc), vcc->sk->sk_sndbuf,
 	    atomic_read(&vcc->sk->sk_rmem_alloc), vcc->sk->sk_rcvbuf);
 }
diff -Nru a/net/atm/pvc.c b/net/atm/pvc.c
--- a/net/atm/pvc.c	Sat Jul 19 12:54:24 2003
+++ b/net/atm/pvc.c	Sat Jul 19 12:54:24 2003
@@ -111,7 +111,7 @@
 	.socketpair =	sock_no_socketpair,
 	.accept =	sock_no_accept,
 	.getname =	pvc_getname,
-	.poll =		atm_poll,
+	.poll =		vcc_poll,
 	.ioctl =	vcc_ioctl,
 	.listen =	sock_no_listen,
 	.shutdown =	pvc_shutdown,
diff -Nru a/net/atm/raw.c b/net/atm/raw.c
--- a/net/atm/raw.c	Sat Jul 19 12:54:29 2003
+++ b/net/atm/raw.c	Sat Jul 19 12:54:29 2003
@@ -29,7 +29,7 @@
 {
 	if (skb) {
 		skb_queue_tail(&vcc->sk->sk_receive_queue, skb);
-		wake_up(&vcc->sleep);
+		vcc->sk->sk_data_ready(vcc->sk, skb->len);
 	}
 }
 
@@ -40,7 +40,7 @@
 		skb->truesize);
 	atomic_sub(skb->truesize, &vcc->sk->sk_wmem_alloc);
 	dev_kfree_skb_any(skb);
-	wake_up(&vcc->sleep);
+	vcc->sk->sk_write_space(vcc->sk);
 }
 
 
diff -Nru a/net/atm/signaling.c b/net/atm/signaling.c
--- a/net/atm/signaling.c	Sat Jul 19 12:54:26 2003
+++ b/net/atm/signaling.c	Sat Jul 19 12:54:26 2003
@@ -61,7 +61,7 @@
 #endif
 	atm_force_charge(sigd,skb->truesize);
 	skb_queue_tail(&sigd->sk->sk_receive_queue,skb);
-	wake_up(&sigd->sleep);
+	sigd->sk->sk_data_ready(sigd->sk, skb->len);
 }
 
 
@@ -103,7 +103,8 @@
 	vcc = *(struct atm_vcc **) &msg->vcc;
 	switch (msg->type) {
 		case as_okay:
-			vcc->reply = msg->reply;
+			vcc->sk->sk_err = -msg->reply;
+			clear_bit(ATM_VF_WAITING, &vcc->flags);
 			if (!*vcc->local.sas_addr.prv &&
 			    !*vcc->local.sas_addr.pub) {
 				vcc->local.sas_family = AF_ATMSVC;
@@ -123,8 +124,8 @@
 		case as_error:
 			clear_bit(ATM_VF_REGIS,&vcc->flags);
 			clear_bit(ATM_VF_READY,&vcc->flags);
-			vcc->reply = msg->reply;
 			vcc->sk->sk_err = -msg->reply;
+			clear_bit(ATM_VF_WAITING, &vcc->flags);
 			break;
 		case as_indicate:
 			vcc = *(struct atm_vcc **) &msg->listen_vcc;
@@ -137,19 +138,16 @@
 			}
 			vcc->sk->sk_ack_backlog++;
 			skb_queue_tail(&vcc->sk->sk_receive_queue, skb);
-			if (vcc->callback) {
-				DPRINTK("waking vcc->sleep 0x%p\n",
-				    &vcc->sleep);
-				vcc->callback(vcc);
-			}
+			DPRINTK("waking vcc->sk->sk_sleep 0x%p\n", vcc->sk->sk_sleep);
+			vcc->sk->sk_state_change(vcc->sk);
 as_indicate_complete:
 			release_sock(vcc->sk);
 			return 0;
 		case as_close:
 			set_bit(ATM_VF_RELEASED,&vcc->flags);
 			clear_bit(ATM_VF_READY,&vcc->flags);
-			vcc->reply = msg->reply;
 			vcc->sk->sk_err = -msg->reply;
+			clear_bit(ATM_VF_WAITING, &vcc->flags);
 			break;
 		case as_modify:
 			modify_qos(vcc,msg);
@@ -159,7 +157,7 @@
 			    (int) msg->type);
 			return -EINVAL;
 	}
-	if (vcc->callback) vcc->callback(vcc);
+	vcc->sk->sk_state_change(vcc->sk);
 	dev_kfree_skb(skb);
 	return 0;
 }
@@ -205,9 +203,9 @@
 	if (vcc->sk->sk_family == PF_ATMSVC &&
 	    !test_bit(ATM_VF_META,&vcc->flags)) {
 		set_bit(ATM_VF_RELEASED,&vcc->flags);
-		vcc->reply = -EUNATCH;
 		vcc->sk->sk_err = EUNATCH;
-		wake_up(&vcc->sleep);
+		clear_bit(ATM_VF_WAITING, &vcc->flags);
+		vcc->sk->sk_state_change(vcc->sk);
 	}
 }
 
diff -Nru a/net/atm/signaling.h b/net/atm/signaling.h
--- a/net/atm/signaling.h	Sat Jul 19 12:54:21 2003
+++ b/net/atm/signaling.h	Sat Jul 19 12:54:21 2003
@@ -11,9 +11,6 @@
 #include <linux/atmsvc.h>
 
 
-#define WAITING 1 /* for reply: 0: no error, < 0: error, ... */
-
-
 extern struct atm_vcc *sigd; /* needed in svc_release */
 
 
diff -Nru a/net/atm/svc.c b/net/atm/svc.c
--- a/net/atm/svc.c	Sat Jul 19 12:54:26 2003
+++ b/net/atm/svc.c	Sat Jul 19 12:54:26 2003
@@ -43,14 +43,6 @@
  */
 
 
-void svc_callback(struct atm_vcc *vcc)
-{
-	wake_up(&vcc->sleep);
-}
-
-
-
-
 static int svc_shutdown(struct socket *sock,int how)
 {
 	return 0;
@@ -64,13 +56,13 @@
 
 	DPRINTK("svc_disconnect %p\n",vcc);
 	if (test_bit(ATM_VF_REGIS,&vcc->flags)) {
-		prepare_to_wait(&vcc->sleep, &wait, TASK_UNINTERRUPTIBLE);
+		prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
 		sigd_enq(vcc,as_close,NULL,NULL,NULL);
 		while (!test_bit(ATM_VF_RELEASED,&vcc->flags) && sigd) {
 			schedule();
-			prepare_to_wait(&vcc->sleep, &wait, TASK_UNINTERRUPTIBLE);
+			prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
 		}
-		finish_wait(&vcc->sleep, &wait);
+		finish_wait(vcc->sk->sk_sleep, &wait);
 	}
 	/* beware - socket is still in use by atmsigd until the last
 	   as_indicate has been answered */
@@ -145,22 +137,22 @@
 		goto out;
 	}
 	vcc->local = *addr;
-	vcc->reply = WAITING;
-	prepare_to_wait(&vcc->sleep, &wait, TASK_UNINTERRUPTIBLE);
+	set_bit(ATM_VF_WAITING, &vcc->flags);
+	prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
 	sigd_enq(vcc,as_bind,NULL,NULL,&vcc->local);
-	while (vcc->reply == WAITING && sigd) {
+	while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
 		schedule();
-		prepare_to_wait(&vcc->sleep, &wait, TASK_UNINTERRUPTIBLE);
+		prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
 	}
-	finish_wait(&vcc->sleep, &wait);
+	finish_wait(sk->sk_sleep, &wait);
 	clear_bit(ATM_VF_REGIS,&vcc->flags); /* doesn't count */
 	if (!sigd) {
 		error = -EUNATCH;
 		goto out;
 	}
-        if (!vcc->reply)
+        if (!sk->sk_err)
 		set_bit(ATM_VF_BOUND,&vcc->flags);
-	error = vcc->reply;
+	error = -sk->sk_err;
 out:
 	release_sock(sk);
 	return error;
@@ -191,13 +183,13 @@
 		error = -EISCONN;
 		goto out;
 	case SS_CONNECTING:
-		if (vcc->reply == WAITING) {
+		if (test_bit(ATM_VF_WAITING, &vcc->flags)) {
 			error = -EALREADY;
 			goto out;
 		}
 		sock->state = SS_UNCONNECTED;
-		if (vcc->reply) {
-			error = vcc->reply;
+		if (sk->sk_err) {
+			error = -sk->sk_err;
 			goto out;
 		}
 		break;
@@ -226,20 +218,20 @@
 			goto out;
 		}
 		vcc->remote = *addr;
-		vcc->reply = WAITING;
-		prepare_to_wait(&vcc->sleep, &wait, TASK_INTERRUPTIBLE);
+		set_bit(ATM_VF_WAITING, &vcc->flags);
+		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
 		sigd_enq(vcc,as_connect,NULL,NULL,&vcc->remote);
 		if (flags & O_NONBLOCK) {
-			finish_wait(&vcc->sleep, &wait);
+			finish_wait(sk->sk_sleep, &wait);
 			sock->state = SS_CONNECTING;
 			error = -EINPROGRESS;
 			goto out;
 		}
 		error = 0;
-		while (vcc->reply == WAITING && sigd) {
+		while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
 			schedule();
 			if (!signal_pending(current)) {
-				prepare_to_wait(&vcc->sleep, &wait, TASK_INTERRUPTIBLE);
+				prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
 				continue;
 			}
 			DPRINTK("*ABORT*\n");
@@ -256,14 +248,14 @@
 			 *   Kernel <--close--- Demon
 			 */
 			sigd_enq(vcc,as_close,NULL,NULL,NULL);
-			while (vcc->reply == WAITING && sigd) {
-				prepare_to_wait(&vcc->sleep, &wait, TASK_INTERRUPTIBLE);
+			while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
+				prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
 				schedule();
 			}
-			if (!vcc->reply)
+			if (!sk->sk_err)
 				while (!test_bit(ATM_VF_RELEASED,&vcc->flags)
 				    && sigd) {
-					prepare_to_wait(&vcc->sleep, &wait, TASK_INTERRUPTIBLE);
+					prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
 					schedule();
 				}
 			clear_bit(ATM_VF_REGIS,&vcc->flags);
@@ -273,15 +265,15 @@
 			error = -EINTR;
 			break;
 		}
-		finish_wait(&vcc->sleep, &wait);
+		finish_wait(sk->sk_sleep, &wait);
 		if (error)
 			goto out;
 		if (!sigd) {
 			error = -EUNATCH;
 			goto out;
 		}
-		if (vcc->reply) {
-			error = vcc->reply;
+		if (sk->sk_err) {
+			error = -sk->sk_err;
 			goto out;
 		}
 	}
@@ -319,14 +311,14 @@
 		error = -EINVAL;
 		goto out;
 	}
-	vcc->reply = WAITING;
-	prepare_to_wait(&vcc->sleep, &wait, TASK_UNINTERRUPTIBLE);
+	set_bit(ATM_VF_WAITING, &vcc->flags);
+	prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
 	sigd_enq(vcc,as_listen,NULL,NULL,&vcc->local);
-	while (vcc->reply == WAITING && sigd) {
+	while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
 		schedule();
-		prepare_to_wait(&vcc->sleep, &wait, TASK_UNINTERRUPTIBLE);
+		prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
 	}
-	finish_wait(&vcc->sleep, &wait);
+	finish_wait(sk->sk_sleep, &wait);
 	if (!sigd) {
 		error = -EUNATCH;
 		goto out;
@@ -334,7 +326,7 @@
 	set_bit(ATM_VF_LISTEN,&vcc->flags);
 	vcc->sk->sk_max_ack_backlog = backlog > 0 ? backlog :
 						    ATM_BACKLOG_DEFAULT;
-	error = vcc->reply;
+	error = -sk->sk_err;
 out:
 	release_sock(sk);
 	return error;
@@ -362,12 +354,12 @@
 	while (1) {
 		DEFINE_WAIT(wait);
 
-		prepare_to_wait(&old_vcc->sleep, &wait, TASK_INTERRUPTIBLE);
+		prepare_to_wait(old_vcc->sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
 		while (!(skb = skb_dequeue(&old_vcc->sk->sk_receive_queue)) &&
 		       sigd) {
 			if (test_bit(ATM_VF_RELEASED,&old_vcc->flags)) break;
 			if (test_bit(ATM_VF_CLOSE,&old_vcc->flags)) {
-				error = old_vcc->reply;
+				error = -sk->sk_err;
 				break;
 			}
 			if (flags & O_NONBLOCK) {
@@ -381,9 +373,9 @@
 				error = -ERESTARTSYS;
 				break;
 			}
-			prepare_to_wait(&old_vcc->sleep, &wait, TASK_INTERRUPTIBLE);
+			prepare_to_wait(old_vcc->sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
 		}
-		finish_wait(&old_vcc->sleep, &wait);
+		finish_wait(old_vcc->sk->sk_sleep, &wait);
 		if (error)
 			goto out;
 		if (!skb) {
@@ -407,23 +399,24 @@
 			goto out;
 		}
 		/* wait should be short, so we ignore the non-blocking flag */
-		new_vcc->reply = WAITING;
-		prepare_to_wait(&new_vcc->sleep, &wait, TASK_UNINTERRUPTIBLE);
+		set_bit(ATM_VF_WAITING, &new_vcc->flags);
+		prepare_to_wait(new_vcc->sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
 		sigd_enq(new_vcc,as_accept,old_vcc,NULL,NULL);
-		while (new_vcc->reply == WAITING && sigd) {
+		while (test_bit(ATM_VF_WAITING, &new_vcc->flags) && sigd) {
 			release_sock(sk);
 			schedule();
 			lock_sock(sk);
-			prepare_to_wait(&new_vcc->sleep, &wait, TASK_UNINTERRUPTIBLE);
+			prepare_to_wait(new_vcc->sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
 		}
-		finish_wait(&new_vcc->sleep, &wait);
+		finish_wait(new_vcc->sk->sk_sleep, &wait);
 		if (!sigd) {
 			error = -EUNATCH;
 			goto out;
 		}
-		if (!new_vcc->reply) break;
-		if (new_vcc->reply != -ERESTARTSYS) {
-			error = new_vcc->reply;
+		if (!new_vcc->sk->sk_err)
+			break;
+		if (new_vcc->sk->sk_err != ERESTARTSYS) {
+			error = -new_vcc->sk->sk_err;
 			goto out;
 		}
 	}
@@ -451,17 +444,17 @@
 {
 	DEFINE_WAIT(wait);
 
-	vcc->reply = WAITING;
-	prepare_to_wait(&vcc->sleep, &wait, TASK_UNINTERRUPTIBLE);
+	set_bit(ATM_VF_WAITING, &vcc->flags);
+	prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
 	sigd_enq2(vcc,as_modify,NULL,NULL,&vcc->local,qos,0);
-	while (vcc->reply == WAITING && !test_bit(ATM_VF_RELEASED,&vcc->flags)
-	    && sigd) {
+	while (test_bit(ATM_VF_WAITING, &vcc->flags) &&
+	       !test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) {
 		schedule();
-		prepare_to_wait(&vcc->sleep, &wait, TASK_UNINTERRUPTIBLE);
+		prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
 	}
-	finish_wait(&vcc->sleep, &wait);
+	finish_wait(vcc->sk->sk_sleep, &wait);
 	if (!sigd) return -EUNATCH;
-	return vcc->reply;
+	return -vcc->sk->sk_err;
 }
 
 
@@ -527,7 +520,7 @@
 	.socketpair =	sock_no_socketpair,
 	.accept =	svc_accept,
 	.getname =	svc_getname,
-	.poll =		atm_poll,
+	.poll =		vcc_poll,
 	.ioctl =	vcc_ioctl,
 	.listen =	svc_listen,
 	.shutdown =	svc_shutdown,
@@ -547,7 +540,6 @@
 	sock->ops = &svc_proto_ops;
 	error = vcc_create(sock, protocol, AF_ATMSVC);
 	if (error) return error;
-	ATM_SD(sock)->callback = svc_callback;
 	ATM_SD(sock)->local.sas_family = AF_ATMSVC;
 	ATM_SD(sock)->remote.sas_family = AF_ATMSVC;
 	return 0;
diff -Nru a/net/core/dev.c b/net/core/dev.c
--- a/net/core/dev.c	Sat Jul 19 12:54:25 2003
+++ b/net/core/dev.c	Sat Jul 19 12:54:25 2003
@@ -178,7 +178,7 @@
  *	Device drivers call our routines to queue packets here. We empty the
  *	queue in the local softnet handler.
  */
-struct softnet_data softnet_data[NR_CPUS] __cacheline_aligned;
+DEFINE_PER_CPU(struct softnet_data, softnet_data) = { 0, };
 
 #ifdef CONFIG_NET_FASTROUTE
 int netdev_fastroute;
@@ -1280,34 +1280,35 @@
 	unsigned long rd;
 	int rq;
 #endif
-	int blog = softnet_data[cpu].input_pkt_queue.qlen;
-	int avg_blog = softnet_data[cpu].avg_blog;
+	struct softnet_data *sd = &per_cpu(softnet_data, cpu);
+	int blog = sd->input_pkt_queue.qlen;
+	int avg_blog = sd->avg_blog;
 
 	avg_blog = (avg_blog >> 1) + (blog >> 1);
 
 	if (avg_blog > mod_cong) {
 		/* Above moderate congestion levels. */
-		softnet_data[cpu].cng_level = NET_RX_CN_HIGH;
+		sd->cng_level = NET_RX_CN_HIGH;
 #ifdef RAND_LIE
 		rd = net_random();
 		rq = rd % netdev_max_backlog;
 		if (rq < avg_blog) /* unlucky bastard */
-			softnet_data[cpu].cng_level = NET_RX_DROP;
+			sd->cng_level = NET_RX_DROP;
 #endif
 	} else if (avg_blog > lo_cong) {
-		softnet_data[cpu].cng_level = NET_RX_CN_MOD;
+		sd->cng_level = NET_RX_CN_MOD;
 #ifdef RAND_LIE
 		rd = net_random();
 		rq = rd % netdev_max_backlog;
 			if (rq < avg_blog) /* unlucky bastard */
-				softnet_data[cpu].cng_level = NET_RX_CN_HIGH;
+				sd->cng_level = NET_RX_CN_HIGH;
 #endif
 	} else if (avg_blog > no_cong)
-		softnet_data[cpu].cng_level = NET_RX_CN_LOW;
+		sd->cng_level = NET_RX_CN_LOW;
 	else  /* no congestion */
-		softnet_data[cpu].cng_level = NET_RX_SUCCESS;
+		sd->cng_level = NET_RX_SUCCESS;
 
-	softnet_data[cpu].avg_blog = avg_blog;
+	sd->avg_blog = avg_blog;
 }
 
 #ifdef OFFLINE_SAMPLE
@@ -1357,7 +1358,7 @@
 	 */
 	local_irq_save(flags);
 	this_cpu = smp_processor_id();
-	queue = &softnet_data[this_cpu];
+	queue = &__get_cpu_var(softnet_data);
 
 	netdev_rx_stat[this_cpu].total++;
 	if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {
@@ -1445,14 +1446,14 @@
 
 static void net_tx_action(struct softirq_action *h)
 {
-	int cpu = smp_processor_id();
+	struct softnet_data *sd = &__get_cpu_var(softnet_data);
 
-	if (softnet_data[cpu].completion_queue) {
+	if (sd->completion_queue) {
 		struct sk_buff *clist;
 
 		local_irq_disable();
-		clist = softnet_data[cpu].completion_queue;
-		softnet_data[cpu].completion_queue = NULL;
+		clist = sd->completion_queue;
+		sd->completion_queue = NULL;
 		local_irq_enable();
 
 		while (clist) {
@@ -1464,12 +1465,12 @@
 		}
 	}
 
-	if (softnet_data[cpu].output_queue) {
+	if (sd->output_queue) {
 		struct net_device *head;
 
 		local_irq_disable();
-		head = softnet_data[cpu].output_queue;
-		softnet_data[cpu].output_queue = NULL;
+		head = sd->output_queue;
+		sd->output_queue = NULL;
 		local_irq_enable();
 
 		while (head) {
@@ -1611,8 +1612,7 @@
 {
 	int work = 0;
 	int quota = min(backlog_dev->quota, *budget);
-	int this_cpu = smp_processor_id();
-	struct softnet_data *queue = &softnet_data[this_cpu];
+	struct softnet_data *queue = &__get_cpu_var(softnet_data);
 	unsigned long start_time = jiffies;
 
 	for (;;) {
@@ -1673,7 +1673,7 @@
 static void net_rx_action(struct softirq_action *h)
 {
 	int this_cpu = smp_processor_id();
-	struct softnet_data *queue = &softnet_data[this_cpu];
+	struct softnet_data *queue = &__get_cpu_var(softnet_data);
 	unsigned long start_time = jiffies;
 	int budget = netdev_max_backlog;
 
@@ -2979,7 +2979,7 @@
 	for (i = 0; i < NR_CPUS; i++) {
 		struct softnet_data *queue;
 
-		queue = &softnet_data[i];
+		queue = &per_cpu(softnet_data, i);
 		skb_queue_head_init(&queue->input_pkt_queue);
 		queue->throttle = 0;
 		queue->cng_level = 0;
diff -Nru a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
--- a/net/ipv4/ip_gre.c	Sat Jul 19 12:54:26 2003
+++ b/net/ipv4/ip_gre.c	Sat Jul 19 12:54:26 2003
@@ -816,6 +816,7 @@
 			skb_set_owner_w(new_skb, skb->sk);
 		dev_kfree_skb(skb);
 		skb = new_skb;
+		old_iph = skb->nh.iph;
 	}
 
 	skb->nh.raw = skb_push(skb, gre_hlen);
diff -Nru a/net/ipv4/ipip.c b/net/ipv4/ipip.c
--- a/net/ipv4/ipip.c	Sat Jul 19 12:54:30 2003
+++ b/net/ipv4/ipip.c	Sat Jul 19 12:54:30 2003
@@ -616,6 +616,7 @@
 			skb_set_owner_w(new_skb, skb->sk);
 		dev_kfree_skb(skb);
 		skb = new_skb;
+		old_iph = skb->nh.iph;
 	}
 
 	skb->nh.raw = skb_push(skb, sizeof(struct iphdr));
diff -Nru a/net/ipv4/ipvs/Kconfig b/net/ipv4/ipvs/Kconfig
--- a/net/ipv4/ipvs/Kconfig	Sat Jul 19 12:54:24 2003
+++ b/net/ipv4/ipvs/Kconfig	Sat Jul 19 12:54:24 2003
@@ -147,7 +147,7 @@
 	  unsure, say N.
 
 config	IP_VS_LBLC
-	tristate "locality-based least-connection with replication scheduling"
+	tristate "locality-based least-connection scheduling"
         depends on IP_VS
 	---help---
 	  The locality-based least-connection scheduling algorithm is for
@@ -163,7 +163,7 @@
 	  unsure, say N.
 
 config  IP_VS_LBLCR
-	tristate "locality-based least-connection with replication schedulin"
+	tristate "locality-based least-connection with replication scheduling"
         depends on IP_VS
 	---help---
 	  The locality-based least-connection with replication scheduling
diff -Nru a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
--- a/net/ipv4/ipvs/ip_vs_conn.c	Sat Jul 19 12:54:28 2003
+++ b/net/ipv4/ipvs/ip_vs_conn.c	Sat Jul 19 12:54:28 2003
@@ -507,9 +507,6 @@
 	 *	refcnt==1 implies I'm the only one referrer
 	 */
 	if (likely(atomic_read(&cp->refcnt) == 1)) {
-		/* make sure that there is no timer on it now */
-		del_timer_sync(&cp->timer);
-
 		/* does anybody control me? */
 		if (cp->control)
 			ip_vs_control_del(cp);
@@ -517,7 +514,6 @@
 		if (unlikely(cp->app != NULL))
 			ip_vs_unbind_app(cp);
 		ip_vs_unbind_dest(cp);
-		//ip_vs_timeout_detach(cp);
 		if (cp->flags & IP_VS_CONN_F_NO_CPORT)
 			atomic_dec(&ip_vs_conn_no_cport_cnt);
 		atomic_dec(&ip_vs_conn_count);
diff -Nru a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
--- a/net/ipv4/ipvs/ip_vs_ctl.c	Sat Jul 19 12:54:28 2003
+++ b/net/ipv4/ipvs/ip_vs_ctl.c	Sat Jul 19 12:54:28 2003
@@ -93,7 +93,7 @@
 /*
  *	update_defense_level is called from timer bh and from sysctl.
  */
-void update_defense_level(void)
+static void update_defense_level(void)
 {
 	struct sysinfo i;
 	static int old_secure_tcp = 0;
@@ -210,6 +210,22 @@
 }
 
 
+/*
+ *	Timer for checking the defense
+ */
+static struct timer_list defense_timer;
+#define DEFENSE_TIMER_PERIOD	1*HZ
+
+static void defense_timer_handler(unsigned long data)
+{
+	update_defense_level();
+	if (atomic_read(&ip_vs_dropentry))
+		ip_vs_random_dropentry();
+
+	mod_timer(&defense_timer, jiffies + DEFENSE_TIMER_PERIOD);
+}
+
+
 int
 ip_vs_use_count_inc(void)
 {
@@ -2187,6 +2203,12 @@
 	ip_vs_stats.lock = SPIN_LOCK_UNLOCKED;
 	ip_vs_new_estimator(&ip_vs_stats);
 
+	/* Hook the defense timer */
+	init_timer(&defense_timer);
+	defense_timer.function = defense_timer_handler;
+	defense_timer.expires = jiffies + DEFENSE_TIMER_PERIOD;
+	add_timer(&defense_timer);
+
 	LeaveFunction(2);
 	return 0;
 }
@@ -2196,6 +2218,7 @@
 {
 	EnterFunction(2);
 	ip_vs_trash_cleanup();
+	del_timer_sync(&defense_timer);
 	ip_vs_kill_estimator(&ip_vs_stats);
 	unregister_sysctl_table(ipv4_vs_table.sysctl_header);
 	proc_net_remove("ip_vs_stats");
diff -Nru a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c
--- a/net/ipv4/ipvs/ip_vs_xmit.c	Sat Jul 19 12:54:29 2003
+++ b/net/ipv4/ipvs/ip_vs_xmit.c	Sat Jul 19 12:54:29 2003
@@ -78,7 +78,6 @@
 						.daddr = dest->addr,
 						.saddr = 0,
 						.tos = rtos, } },
-				.proto = cp->protocol,
 			};
 
 			if (ip_route_output_key(&rt, &fl)) {
@@ -102,7 +101,6 @@
 					.daddr = dest->addr,
 					.saddr = 0,
 					.tos = rtos, } },
-			.proto = cp->protocol,
 		};
 
 		if (ip_route_output_key(&rt, &fl)) {
diff -Nru a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
--- a/net/ipv4/tcp_input.c	Sat Jul 19 12:54:26 2003
+++ b/net/ipv4/tcp_input.c	Sat Jul 19 12:54:26 2003
@@ -2373,7 +2373,7 @@
 	tcp_schedule_ack(tp);
 
 	sk->sk_shutdown |= RCV_SHUTDOWN;
-	sock_reset_flag(sk, SOCK_DONE);
+	sock_set_flag(sk, SOCK_DONE);
 
 	switch (sk->sk_state) {
 		case TCP_SYN_RECV:
diff -Nru a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
--- a/net/ipv6/addrconf.c	Sat Jul 19 12:54:29 2003
+++ b/net/ipv6/addrconf.c	Sat Jul 19 12:54:29 2003
@@ -368,7 +368,8 @@
 				dev, dev->name);
 			ndev->cnf.use_tempaddr = -1;
 		} else {
-			__ipv6_regen_rndid(ndev);
+			in6_dev_hold(ndev);
+			ipv6_regen_rndid((unsigned long) ndev);
 		}
 #endif
 
@@ -1122,9 +1123,6 @@
 	sg[1].offset = ((long) eui64 & ~PAGE_MASK);
 	sg[1].length = 8;
 
-	if (!del_timer(&idev->regen_timer))
-		in6_dev_hold(idev);
-
 	dev = idev->dev;
 
 	if (ipv6_generate_eui64(eui64, dev)) {
@@ -1137,7 +1135,6 @@
 	spin_lock(&md5_tfm_lock);
 	if (unlikely(md5_tfm == NULL)) {
 		spin_unlock(&md5_tfm_lock);
-		in6_dev_put(idev);
 		return -1;
 	}
 	crypto_digest_init(md5_tfm);
@@ -1170,33 +1167,41 @@
 		if ((idev->rndid[2]|idev->rndid[3]|idev->rndid[4]|idev->rndid[5]|idev->rndid[6]|idev->rndid[7]) == 0x00)
 			goto regen;
 	}
-	
-	idev->regen_timer.expires = jiffies +
-					idev->cnf.temp_prefered_lft * HZ - 
-					idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time - desync_factor;
-	if (time_before(idev->regen_timer.expires, jiffies)) {
-		idev->regen_timer.expires = 0;
-		printk(KERN_WARNING
-			"__ipv6_regen_rndid(): too short regeneration interval; timer disabled for %s.\n",
-			idev->dev->name);
-		in6_dev_put(idev);
-		return -1;
-	}
 
-	add_timer(&idev->regen_timer);
 	return 0;
 }
 
 static void ipv6_regen_rndid(unsigned long data)
 {
 	struct inet6_dev *idev = (struct inet6_dev *) data;
+	unsigned long expires;
 
 	read_lock_bh(&addrconf_lock);
 	write_lock_bh(&idev->lock);
-	if (!idev->dead)
-		__ipv6_regen_rndid(idev);
+
+	if (idev->dead)
+		goto out;
+
+	if (__ipv6_regen_rndid(idev) < 0)
+		goto out;
+	
+	expires = jiffies +
+		idev->cnf.temp_prefered_lft * HZ - 
+		idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time - desync_factor;
+	if (time_before(expires, jiffies)) {
+		printk(KERN_WARNING
+			"ipv6_regen_rndid(): too short regeneration interval; timer disabled for %s.\n",
+			idev->dev->name);
+		goto out;
+	}
+
+	if (!mod_timer(&idev->regen_timer, expires))
+		in6_dev_hold(idev);
+
+out:
 	write_unlock_bh(&idev->lock);
 	read_unlock_bh(&addrconf_lock);
+	in6_dev_put(idev);
 }
 
 static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr) {
@@ -1928,6 +1933,27 @@
 	/* Step 3: clear address list */
 
 	write_lock_bh(&idev->lock);
+#ifdef CONFIG_IPV6_PRIVACY
+	if (how == 1 && del_timer(&idev->regen_timer))
+		in6_dev_put(idev);
+
+	/* clear tempaddr list */
+	while ((ifa = idev->tempaddr_list) != NULL) {
+		idev->tempaddr_list = ifa->tmp_next;
+		ifa->tmp_next = NULL;
+		ifa->dead = 1;
+		write_unlock_bh(&idev->lock);
+		spin_lock_bh(&ifa->lock);
+
+		if (ifa->ifpub) {
+			in6_ifa_put(ifa->ifpub);
+			ifa->ifpub = NULL;
+		}
+		spin_unlock_bh(&ifa->lock);
+		in6_ifa_put(ifa);
+		write_lock_bh(&idev->lock);
+	}
+#endif
 	while ((ifa = idev->addr_list) != NULL) {
 		idev->addr_list = ifa->if_next;
 		ifa->if_next = NULL;
diff -Nru a/net/ipv6/ah6.c b/net/ipv6/ah6.c
--- a/net/ipv6/ah6.c	Sat Jul 19 12:54:26 2003
+++ b/net/ipv6/ah6.c	Sat Jul 19 12:54:26 2003
@@ -19,7 +19,7 @@
  *
  *	Mitsuru KANDA @USAGI       : IPv6 Support 
  * 	Kazunori MIYAZAWA @USAGI   :
- * 	Kunihiro Ishiguro          :
+ * 	Kunihiro Ishiguro <kunihiro@ipinfusion.com>
  * 	
  * 	This file is derived from net/ipv4/ah.c.
  */
diff -Nru a/net/ipv6/esp6.c b/net/ipv6/esp6.c
--- a/net/ipv6/esp6.c	Sat Jul 19 12:54:25 2003
+++ b/net/ipv6/esp6.c	Sat Jul 19 12:54:25 2003
@@ -19,7 +19,7 @@
  *
  *	Mitsuru KANDA @USAGI       : IPv6 Support 
  * 	Kazunori MIYAZAWA @USAGI   :
- * 	Kunihiro Ishiguro          :
+ * 	Kunihiro Ishiguro <kunihiro@ipinfusion.com>
  * 	
  * 	This file is derived from net/ipv4/esp.c
  */
diff -Nru a/net/ipv6/route.c b/net/ipv6/route.c
--- a/net/ipv6/route.c	Sat Jul 19 12:54:26 2003
+++ b/net/ipv6/route.c	Sat Jul 19 12:54:26 2003
@@ -567,6 +567,11 @@
 	if (unlikely(rt == NULL))
 		goto out;
 
+	if (dev)
+		dev_hold(dev);
+	if (neigh)
+		neigh_hold(neigh);
+
 	rt->rt6i_dev	  = dev;
 	rt->rt6i_nexthop  = neigh;
 	rt->rt6i_expires  = 0;
diff -Nru a/net/ipv6/sit.c b/net/ipv6/sit.c
--- a/net/ipv6/sit.c	Sat Jul 19 12:54:29 2003
+++ b/net/ipv6/sit.c	Sat Jul 19 12:54:29 2003
@@ -550,6 +550,7 @@
 			skb_set_owner_w(new_skb, skb->sk);
 		dev_kfree_skb(skb);
 		skb = new_skb;
+		iph6 = skb->nh.ipv6h;
 	}
 
 	skb->nh.raw = skb_push(skb, sizeof(struct iphdr));
diff -Nru a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
--- a/net/ipv6/tcp_ipv6.c	Sat Jul 19 12:54:25 2003
+++ b/net/ipv6/tcp_ipv6.c	Sat Jul 19 12:54:25 2003
@@ -579,7 +579,7 @@
 
 	addr_type = ipv6_addr_type(&usin->sin6_addr);
 
-	if(addr_type & IPV6_ADDR_MULTICAST)
+	if (addr_type & (IPV6_ADDR_ANYCAST | IPV6_ADDR_MULTICAST))
 		return -ENETUNREACH;
 
 	if (addr_type&IPV6_ADDR_LINKLOCAL) {
@@ -967,12 +967,14 @@
 	struct tcphdr *th = skb->h.th, *t1; 
 	struct sk_buff *buff;
 	struct flowi fl;
+	int daddr_type;
 
 	if (th->rst)
 		return;
 
-	if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr))
-		return; 
+	daddr_type = ipv6_addr_type(&skb->nh.ipv6h->daddr);
+	if (daddr_type & (IPV6_ADDR_ANYCAST | IPV6_ADDR_MULTICAST))
+		return;
 
 	/*
 	 * We need to grab some memory, and put together an RST,
@@ -1171,13 +1173,14 @@
 	struct tcp_opt tmptp, *tp = tcp_sk(sk);
 	struct open_request *req = NULL;
 	__u32 isn = TCP_SKB_CB(skb)->when;
+	int daddr_type;
 
 	if (skb->protocol == htons(ETH_P_IP))
 		return tcp_v4_conn_request(sk, skb);
 
-	/* FIXME: do the same check for anycast */
-	if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr))
-		goto drop; 
+	daddr_type = ipv6_addr_type(&skb->nh.ipv6h->daddr);
+	if (daddr_type & (IPV6_ADDR_ANYCAST | IPV6_ADDR_MULTICAST))
+		goto drop;
 
 	/*
 	 *	There are no SYN attacks on IPv6, yet...	
diff -Nru a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
--- a/net/ipv6/xfrm6_input.c	Sat Jul 19 12:54:30 2003
+++ b/net/ipv6/xfrm6_input.c	Sat Jul 19 12:54:30 2003
@@ -4,7 +4,7 @@
  * Authors:
  *	Mitsuru KANDA @USAGI
  * 	Kazunori MIYAZAWA @USAGI
- * 	Kunihiro Ishiguro
+ * 	Kunihiro Ishiguro <kunihiro@ipinfusion.com>
  *	YOSHIFUJI Hideaki @USAGI
  *		IPv6 support
  */
diff -Nru a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
--- a/net/ipv6/xfrm6_policy.c	Sat Jul 19 12:54:23 2003
+++ b/net/ipv6/xfrm6_policy.c	Sat Jul 19 12:54:23 2003
@@ -4,7 +4,7 @@
  * Authors:
  *	Mitsuru KANDA @USAGI
  * 	Kazunori MIYAZAWA @USAGI
- * 	Kunihiro Ishiguro
+ * 	Kunihiro Ishiguro <kunihiro@ipinfusion.com>
  * 		IPv6 support
  * 	YOSHIFUJI Hideaki
  * 		Split up af-specific portion
diff -Nru a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
--- a/net/ipv6/xfrm6_state.c	Sat Jul 19 12:54:24 2003
+++ b/net/ipv6/xfrm6_state.c	Sat Jul 19 12:54:24 2003
@@ -4,7 +4,7 @@
  * Authors:
  *	Mitsuru KANDA @USAGI
  * 	Kazunori MIYAZAWA @USAGI
- * 	Kunihiro Ishiguro
+ * 	Kunihiro Ishiguro <kunihiro@ipinfusion.com>
  * 		IPv6 support
  * 	YOSHIFUJI Hideaki @USAGI
  * 		Split up af-specific portion
diff -Nru a/net/netsyms.c b/net/netsyms.c
--- a/net/netsyms.c	Sat Jul 19 12:54:24 2003
+++ b/net/netsyms.c	Sat Jul 19 12:54:24 2003
@@ -685,7 +685,7 @@
 
 EXPORT_SYMBOL(register_gifconf);
 
-EXPORT_SYMBOL(softnet_data);
+EXPORT_PER_CPU_SYMBOL(softnet_data);
 
 #ifdef CONFIG_NET_RADIO
 #include <net/iw_handler.h>		/* Wireless Extensions driver API */
diff -Nru a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
--- a/net/sunrpc/auth_gss/auth_gss.c	Sat Jul 19 12:54:25 2003
+++ b/net/sunrpc/auth_gss/auth_gss.c	Sat Jul 19 12:54:25 2003
@@ -235,7 +235,7 @@
 		goto err;
 	}
 	ctx->gc_proc = RPC_GSS_PROC_DATA;
-	ctx->gc_seq = 0;
+	ctx->gc_seq = 1;	/* NetApp 6.4R1 doesn't accept seq. no. 0 */
 	spin_lock_init(&ctx->gc_seq_lock);
 	atomic_set(&ctx->count,1);
 
diff -Nru a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
--- a/net/sunrpc/clnt.c	Sat Jul 19 12:54:24 2003
+++ b/net/sunrpc/clnt.c	Sat Jul 19 12:54:24 2003
@@ -385,7 +385,8 @@
 	xprt->rcvsize = 0;
 	if (rcvsize)
 		xprt->rcvsize = rcvsize + RPC_SLACK_SPACE;
-	xprt_sock_setbufsize(xprt);
+	if (xprt_connected(xprt))
+		xprt_sock_setbufsize(xprt);
 }
 
 /*
diff -Nru a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
--- a/net/sunrpc/xprt.c	Sat Jul 19 12:54:26 2003
+++ b/net/sunrpc/xprt.c	Sat Jul 19 12:54:26 2003
@@ -436,6 +436,7 @@
 		goto out_write;
 	}
 	xprt_bind_socket(xprt, sock);
+	xprt_sock_setbufsize(xprt);
 
 	if (!xprt->stream)
 		goto out_write;
diff -Nru a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c
--- a/net/wanrouter/wanmain.c	Sat Jul 19 12:54:26 2003
+++ b/net/wanrouter/wanmain.c	Sat Jul 19 12:54:26 2003
@@ -668,7 +668,7 @@
 static int wanrouter_device_new_if(struct wan_device *wandev,
 				   wanif_conf_t *u_conf)
 {
-	wanif_conf_t conf;
+	wanif_conf_t *cnf;
 	struct net_device *dev = NULL;
 #ifdef CONFIG_WANPIPE_MULTPPP
 	struct ppp_device *pppdev=NULL;
@@ -678,38 +678,47 @@
 	if ((wandev->state == WAN_UNCONFIGURED) || (wandev->new_if == NULL))
 		return -ENODEV;
 
-	if (copy_from_user(&conf, u_conf, sizeof(wanif_conf_t)))
-		return -EFAULT;
+	cnf = kmalloc(sizeof(wanif_conf_t), GFP_KERNEL);
+	if (!cnf)
+		return -ENOBUFS;
+
+	err = -EFAULT;
+	if (copy_from_user(cnf, u_conf, sizeof(wanif_conf_t)))
+		goto out;
+
+	err = -EINVAL;
+	if (cnf->magic != ROUTER_MAGIC)
+		goto out;
 
-	if (conf.magic != ROUTER_MAGIC)
-		return -EINVAL;
-
-	if (conf.config_id == WANCONFIG_MPPP) {
+	if (cnf->config_id == WANCONFIG_MPPP) {
 #ifdef CONFIG_WANPIPE_MULTPPP
 		pppdev = kmalloc(sizeof(struct ppp_device), GFP_KERNEL);
+		err = -ENOBUFS;
 		if (pppdev == NULL)
-			return -ENOBUFS;
+			goto out;
 		memset(pppdev, 0, sizeof(struct ppp_device));
 		pppdev->dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
 		if (pppdev->dev == NULL) {
 			kfree(pppdev);
-			return -ENOBUFS;
+			err = -ENOBUFS;
+			goto out;
 		}
 		memset(pppdev->dev, 0, sizeof(struct net_device));
-		err = wandev->new_if(wandev,
-				     (struct net_device *)pppdev, &conf);
+		err = wandev->new_if(wandev, (struct net_device *)pppdev, cnf);
 		dev = pppdev->dev;
 #else
 		printk(KERN_INFO "%s: Wanpipe Mulit-Port PPP support has not been compiled in!\n",
 				wandev->name);
-		return -EPROTONOSUPPORT;
+		err = -EPROTONOSUPPORT;
+		goto out;
 #endif
 	} else {
 		dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
+		err = -ENOBUFS;
 		if (dev == NULL)
-			return -ENOBUFS;
+			goto out;
 		memset(dev, 0, sizeof(struct net_device));
-		err = wandev->new_if(wandev, dev, &conf);
+		err = wandev->new_if(wandev, dev, cnf);
 	}
 
 	if (!err) {
@@ -748,7 +757,8 @@
 				++wandev->ndev;
 
 				unlock_adapter_irq(&wandev->lock, &smp_flags);
-				return 0;	/* done !!! */
+				err = 0;	/* done !!! */
+				goto out;
 			}
 		}
 		if (wandev->del_if)
@@ -761,18 +771,19 @@
 		dev->priv = NULL;
 	}
 
-
 #ifdef CONFIG_WANPIPE_MULTPPP
-	if (conf.config_id == WANCONFIG_MPPP)
+	if (cnf->config_id == WANCONFIG_MPPP)
 		kfree(pppdev);
 	else
 		kfree(dev);
 #else
 	/* Sync PPP is disabled */
-	if (conf.config_id != WANCONFIG_MPPP)
+	if (cnf->config_id != WANCONFIG_MPPP)
 		kfree(dev);
 #endif
 
+out:
+	kfree(cnf);
 	return err;
 }
 
diff -Nru a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
--- a/net/xfrm/xfrm_policy.c	Sat Jul 19 12:54:25 2003
+++ b/net/xfrm/xfrm_policy.c	Sat Jul 19 12:54:25 2003
@@ -4,7 +4,7 @@
  * Changes:
  *	Mitsuru KANDA @USAGI
  * 	Kazunori MIYAZAWA @USAGI
- * 	Kunihiro Ishiguro
+ * 	Kunihiro Ishiguro <kunihiro@ipinfusion.com>
  * 		IPv6 support
  * 	Kazunori MIYAZAWA @USAGI
  * 	YOSHIFUJI Hideaki
diff -Nru a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
--- a/net/xfrm/xfrm_state.c	Sat Jul 19 12:54:26 2003
+++ b/net/xfrm/xfrm_state.c	Sat Jul 19 12:54:26 2003
@@ -4,7 +4,7 @@
  * Changes:
  *	Mitsuru KANDA @USAGI
  * 	Kazunori MIYAZAWA @USAGI
- * 	Kunihiro Ishiguro
+ * 	Kunihiro Ishiguro <kunihiro@ipinfusion.com>
  * 		IPv6 support
  * 	YOSHIFUJI Hideaki @USAGI
  * 		Split up af-specific functions
diff -Nru a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
--- a/net/xfrm/xfrm_user.c	Sat Jul 19 12:54:25 2003
+++ b/net/xfrm/xfrm_user.c	Sat Jul 19 12:54:25 2003
@@ -5,7 +5,7 @@
  * Changes:
  *	Mitsuru KANDA @USAGI
  * 	Kazunori MIYAZAWA @USAGI
- * 	Kunihiro Ishiguro
+ * 	Kunihiro Ishiguro <kunihiro@ipinfusion.com>
  * 		IPv6 support
  * 	
  */
diff -Nru a/scripts/ver_linux b/scripts/ver_linux
--- a/scripts/ver_linux	Sat Jul 19 12:54:25 2003
+++ b/scripts/ver_linux	Sat Jul 19 12:54:25 2003
@@ -54,11 +54,14 @@
 isdnctrl 2>&1 | grep version | awk \
 'NR==1{print "isdn4k-utils          ", $NF}'
 
+showmount --version 2>&1 | grep nfs-utils | awk \
+'NR==1{print "nfs-utils             ", $NF}'
+
 ls -l `ldd /bin/sh | awk '/libc/{print $3}'` | sed \
 -e 's/\.so$//' | awk -F'[.-]'   '{print "Linux C Library        " \
 $(NF-2)"."$(NF-1)"."$NF}'
 
-ldd -v > /dev/null 2>&1 && ldd -v || ldd --version |head -1 | awk \
+ldd -v > /dev/null 2>&1 && ldd -v || ldd --version |head -n 1 | awk \
 'NR==1{print "Dynamic linker (ldd)  ", $NF}'
 
 ls -l /usr/lib/lib{g,stdc}++.so  2>/dev/null | awk -F. \
diff -Nru a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
--- a/sound/isa/cmi8330.c	Sat Jul 19 12:54:23 2003
+++ b/sound/isa/cmi8330.c	Sat Jul 19 12:54:23 2003
@@ -293,7 +293,7 @@
 				     const struct pnp_card_device_id *id)
 {
 	struct pnp_dev *pdev;
-	struct pnp_resource_table * cfg = kmalloc(GFP_ATOMIC, sizeof(struct pnp_resource_table));
+	struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_ATOMIC);
 	int err;
 
 	acard->cap = pnp_request_card_device(card, id->devs[0].id, NULL);
diff -Nru a/sound/isa/es18xx.c b/sound/isa/es18xx.c
--- a/sound/isa/es18xx.c	Sat Jul 19 12:54:24 2003
+++ b/sound/isa/es18xx.c	Sat Jul 19 12:54:24 2003
@@ -1966,7 +1966,7 @@
 					const struct pnp_card_device_id *id)
 {
 	struct pnp_dev *pdev;
-	struct pnp_resource_table * cfg = kmalloc(GFP_ATOMIC, sizeof(struct pnp_resource_table));
+	struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_ATOMIC);
 	int err;
 
 	if (!cfg)
diff -Nru a/sound/oss/Kconfig b/sound/oss/Kconfig
--- a/sound/oss/Kconfig	Sat Jul 19 12:54:27 2003
+++ b/sound/oss/Kconfig	Sat Jul 19 12:54:27 2003
@@ -233,6 +233,10 @@
 	  Support for integral audio in Intel's I/O Controller Hub (ICH)
 	  chipset, as used on the 810/820/840 motherboards.
 
+config SOUND_HARMONY
+	tristate "PA Harmony audio driver"
+	depends on GSC_LASI && SOUND
+
 config SOUND_RME96XX
 	tristate "RME Hammerfall (RME96XX) support (EXPERIMENTAL)"
 	depends on SOUND_PRIME!=n && SOUND && PCI && EXPERIMENTAL
@@ -260,6 +264,10 @@
 	  <file:Documentation/sound/oss/vwsnd> for more info on this driver's
 	  capabilities.
 
+config SOUND_HAL2
+	tristate "SGI HAL2 sound (EXPERIMENTAL)"
+	depends on SGI_IP22 && SOUND && EXPERIMENTAL
+
 config SOUND_VRC5477
 	tristate "NEC Vrc5477 AC97 sound"
 	depends on SOUND_PRIME!=n && DDB5477 && SOUND
@@ -1125,4 +1133,24 @@
 	help
 	  Support for audio mixer facilities on the BT848 TV frame-grabber
 	  card.
+
+config SOUND_KAHLUA
+	tristate "XpressAudio Sound Blaster emulation"
+	depends on SOUND_SB
+
+config SOUND_ALI5455
+	tristate "ALi5455 audio support"
+	depends on SOUND_PRIME!=n && PCI
+
+config SOUND_FORTE
+	tristate "ForteMedia FM801 driver"
+	depends on SOUND_PRIME!=n && PCI
+
+config SOUND_RME96XX
+	tristate "RME Hammerfall (RME96XX) support"
+	depends on SOUND_PRIME!=n && PCI
+
+config SOUND_AD1980
+	tristate "AD1980 front/back switch plugin"
+	depends on SOUND_PRIME!=n
 
diff -Nru a/sound/oss/Makefile b/sound/oss/Makefile
--- a/sound/oss/Makefile	Sat Jul 19 12:54:24 2003
+++ b/sound/oss/Makefile	Sat Jul 19 12:54:24 2003
@@ -10,6 +10,7 @@
 
 # Please leave it as is, cause the link order is significant !
 
+obj-$(CONFIG_SOUND_HAL2)	+= hal2.o
 obj-$(CONFIG_SOUND_AEDSP16)	+= aedsp16.o
 obj-$(CONFIG_SOUND_PSS)		+= pss.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_TRIX)	+= trix.o ad1848.o sb_lib.o uart401.o
@@ -21,6 +22,7 @@
 obj-$(CONFIG_SOUND_OPL3SA2)	+= opl3sa2.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_PAS)		+= pas2.o sb.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_SB)		+= sb.o sb_lib.o uart401.o
+obj-$(CONFIG_SOUND_KAHLUA)	+= kahlua.o
 obj-$(CONFIG_SOUND_WAVEFRONT)	+= wavefront.o
 obj-$(CONFIG_SOUND_MAUI)	+= maui.o mpu401.o
 obj-$(CONFIG_SOUND_MPU401)	+= mpu401.o
@@ -60,10 +62,16 @@
 obj-$(CONFIG_SOUND_MAESTRO)	+= maestro.o
 obj-$(CONFIG_SOUND_MAESTRO3)	+= maestro3.o ac97_codec.o
 obj-$(CONFIG_SOUND_TRIDENT)	+= trident.o ac97_codec.o
+obj-$(CONFIG_SOUND_HARMONY)	+= harmony.o
 obj-$(CONFIG_SOUND_EMU10K1)	+= ac97_codec.o
 obj-$(CONFIG_SOUND_RME96XX)     += rme96xx.o
 obj-$(CONFIG_SOUND_BT878)	+= btaudio.o
+obj-$(CONFIG_SOUND_ALI5455)	+= ali5455.o ac97_codec.o
 obj-$(CONFIG_SOUND_IT8172)	+= ite8172.o ac97_codec.o
+obj-$(CONFIG_SOUND_FORTE)	+= forte.o
+
+obj-$(CONFIG_SOUND_AD1980)	+= ac97_plugin_ad1980.o
+obj-$(CONFIG_SOUND_WM97XX)	+= ac97_plugin_wm97xx.o
 
 ifeq ($(CONFIG_MIDI_EMU10K1),y)
   obj-$(CONFIG_SOUND_EMU10K1)	+= sound.o
diff -Nru a/sound/oss/ac97_plugin_ad1980.c b/sound/oss/ac97_plugin_ad1980.c
--- a/sound/oss/ac97_plugin_ad1980.c	Sat Jul 19 12:54:21 2003
+++ b/sound/oss/ac97_plugin_ad1980.c	Sat Jul 19 12:54:21 2003
@@ -17,7 +17,7 @@
    the provisions above, a recipient may use your version of this
    file under either the OSL or the GPL.
    
-   Authors: 	Arjan van de Ven <arjanv@redhat.com>
+   Authors: 	Alan Cox <alan@redhat.com>
 
    This is an example codec plugin. This one switches the connections
    around to match the setups some vendors use with audio switched to
diff -Nru a/sound/oss/ad1816.c b/sound/oss/ad1816.c
--- a/sound/oss/ad1816.c	Sat Jul 19 12:54:28 2003
+++ b/sound/oss/ad1816.c	Sat Jul 19 12:54:28 2003
@@ -1,15 +1,15 @@
 /*
  *
- * AD1816 lowlevel sound driver for Linux 2.2.0 and above
+ * AD1816 lowlevel sound driver for Linux 2.6.0 and above
  *
- * Copyright (C) 1998 by Thorsten Knabe <tek@rbg.informatik.tu-darmstadt.de>
+ * Copyright (C) 1998-2003 by Thorsten Knabe <linux@thorsten-knabe.de>
  *
  * Based on the CS4232/AD1848 driver Copyright (C) by Hannu Savolainen 1993-1996
  *
  *
- * version: 1.3.1
- * status: experimental
- * date: 1999/4/18
+ * version: 1.5
+ * status: beta
+ * date: 2003/07/15
  *
  * Changes:
  *	Oleg Drokin: Some cleanup of load/unload functions.	1998/11/24
@@ -30,8 +30,17 @@
  *	Christoph Hellwig: Added isapnp support			2000/03/15
  *
  *	Arnaldo Carvalho de Melo: get rid of check_region	2001/10/07
+ *      
+ *      Thorsten Knabe: Compiling with CONFIG_PNP enabled
+ *	works again. It is now possible to use more than one 
+ *	AD1816 sound card. Sample rate now may be changed during
+ *	playback/capture. printk() uses log levels everywhere.
+ *	SMP fixes. DMA handling fixes.
+ *	Other minor code cleanup.				2003/07/15
+ *
  */
 
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -42,9 +51,6 @@
 #include "sound_config.h"
 
 #define DEBUGNOISE(x)
-#define DEBUGINFO(x)
-#define DEBUGLOG(x)
-#define DEBUGWARN(x)
 
 #define CHECK_FOR_POWER { int timeout=100; \
   while (timeout > 0 && (inb(devc->base)&0x80)!= 0x80) {\
@@ -63,21 +69,21 @@
 	int            dma_playback;
         int            dma_capture;
   
-        int            speed;         /* open */
+	int            opened;         /* open */
+        int            speed;	
 	int            channels;
 	int            audio_format;
-	unsigned char  format_bits;
         int            audio_mode; 
-	int            opened;
   
         int            recmask;        /* setup */
+	unsigned char  format_bits;
 	int            supported_devices;
 	int            supported_rec_devices;
 	unsigned short levels[SOUND_MIXER_NRDEVICES];
+					/* misc */
+	struct pnp_dev *pnpdev;	 /* configured via pnp */
         int            dev_no;   /* this is the # in audio_devs and NOT 
 				    in ad1816_info */
-	int            irq_ok;
-	int            *osp;
 	spinlock_t	lock;  
 } ad1816_info;
 
@@ -85,12 +91,6 @@
 static int ad1816_clockfreq = 33000;
 static int options;
 
-/* for backward mapping of irq to sound device */
-
-static volatile char irq2dev[17] = {-1, -1, -1, -1, -1, -1, -1, -1,
-				    -1, -1, -1, -1, -1, -1, -1, -1, -1};
-
-
 /* supported audio formats */
 static int  ad_format_mask =
 AFMT_U8 | AFMT_S16_LE | AFMT_S16_BE | AFMT_MU_LAW | AFMT_A_LAW;
@@ -105,33 +105,22 @@
 
 static int ad_read (ad1816_info * devc, int reg)
 {
-	unsigned long   flags;
 	int result;
 	
 	CHECK_FOR_POWER;
-
-	spin_lock_irqsave(&devc->lock,flags); /* make register access atomic */
 	outb ((unsigned char) (reg & 0x3f), devc->base+0);
 	result = inb(devc->base+2);
 	result+= inb(devc->base+3)<<8;
-	spin_unlock_irqrestore(&devc->lock,flags);
-	
 	return (result);
 }
 
 
 static void ad_write (ad1816_info * devc, int reg, int data)
 {
-	unsigned long flags;
-	
 	CHECK_FOR_POWER;
-	
-	spin_lock_irqsave(&devc->lock,flags); /* make register access atomic */
 	outb ((unsigned char) (reg & 0xff), devc->base+0);
 	outb ((unsigned char) (data & 0xff),devc->base+2);
 	outb ((unsigned char) ((data>>8)&0xff),devc->base+3);
-	spin_unlock_irqrestore(&devc->lock,flags);
-
 }
 
 /* ------------------------------------------------------------------- */
@@ -144,7 +133,7 @@
 	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
 	unsigned char buffer;
 	
-	DEBUGINFO (printk("ad1816: halt_input called\n"));
+	DEBUGNOISE(printk(KERN_DEBUG "ad1816: halt_input called\n"));
 	
 	spin_lock_irqsave(&devc->lock,flags); 
 	
@@ -176,7 +165,7 @@
 	
 	unsigned char buffer;
 
-	DEBUGINFO (printk("ad1816: halt_output called!\n"));
+	DEBUGNOISE(printk(KERN_DEBUG "ad1816: halt_output called!\n"));
 
 	spin_lock_irqsave(&devc->lock,flags); 
 	/* Mute pcm output */
@@ -210,7 +199,7 @@
 	unsigned long cnt;
 	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
 	
-	DEBUGINFO(printk("ad1816: output_block called buf=%ld count=%d flags=%d\n",buf,count,intrflag));
+	DEBUGNOISE(printk(KERN_DEBUG "ad1816: output_block called buf=%ld count=%d flags=%d\n",buf,count,intrflag));
   
 	cnt = count/4 - 1;
   
@@ -231,7 +220,7 @@
 	unsigned long  cnt;
 	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
 	
-	DEBUGINFO(printk("ad1816: start_input called buf=%ld count=%d flags=%d\n",buf,count,intrflag));
+	DEBUGNOISE(printk(KERN_DEBUG "ad1816: start_input called buf=%ld count=%d flags=%d\n",buf,count,intrflag));
 
 	cnt = count/4 - 1;
 
@@ -239,7 +228,6 @@
 
 	/* set transfer count */
 	ad_write (devc, 10, cnt & 0xffff); 
-
 	devc->audio_mode |= PCM_ENABLE_INPUT;
 	spin_unlock_irqrestore(&devc->lock,flags);
 }
@@ -251,33 +239,19 @@
 	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
 	unsigned char fmt_bits;
 	
-	DEBUGINFO (printk ("ad1816: prepare_for_input called: bsize=%d bcount=%d\n",bsize,bcount));
+	DEBUGNOISE(printk(KERN_DEBUG "ad1816: prepare_for_input called: bsize=%d bcount=%d\n",bsize,bcount));
 
 	spin_lock_irqsave(&devc->lock,flags);
-	
 	fmt_bits= (devc->format_bits&0x7)<<3;
 	
 	/* set mono/stereo mode */
 	if (devc->channels > 1) {
 		fmt_bits |=0x4;
 	}
-
 	/* set Mono/Stereo in playback/capture register */
 	outb( (inb(devc->base+8) & ~0x3C)|fmt_bits, devc->base+8); 
 	outb( (inb(devc->base+9) & ~0x3C)|fmt_bits, devc->base+9);
-  
-	/* If compiled into kernel, AD1816_CLOCK is defined, so use it */
-#ifdef AD1816_CLOCK 
-	ad1816_clockfreq=AD1816_CLOCK;
-#endif
-
-	/* capture/playback frequency correction for soundcards 
-	   with clock chips != 33MHz (allowed range 5 - 100 kHz) */
 
-	if (ad1816_clockfreq<5000 || ad1816_clockfreq>100000) {
-		ad1816_clockfreq=33000;
-	}
-	
 	freq=((unsigned int)devc->speed*33000)/ad1816_clockfreq; 
 
 	/* write playback/capture speeds */
@@ -297,7 +271,7 @@
 	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
 	unsigned char fmt_bits;
 
-	DEBUGINFO (printk ("ad1816: prepare_for_output called: bsize=%d bcount=%d\n",bsize,bcount));
+	DEBUGNOISE(printk(KERN_DEBUG "ad1816: prepare_for_output called: bsize=%d bcount=%d\n",bsize,bcount));
 
 	spin_lock_irqsave(&devc->lock,flags);
 
@@ -311,17 +285,6 @@
 	outb( (inb(devc->base+8) & ~0x3C)|fmt_bits, devc->base+8); 
 	outb( (inb(devc->base+9) & ~0x3C)|fmt_bits, devc->base+9);
   
-#ifdef AD1816_CLOCK 
-	ad1816_clockfreq=AD1816_CLOCK;
-#endif
-
-	/* capture/playback frequency correction for soundcards 
-	   with clock chips != 33MHz (allowed range 5 - 100 kHz)*/
-
-	if (ad1816_clockfreq<5000 || ad1816_clockfreq>100000) {
-		ad1816_clockfreq=33000;
-	}
-  
 	freq=((unsigned int)devc->speed*33000)/ad1816_clockfreq; 
 	
 	/* write playback/capture speeds */
@@ -340,7 +303,7 @@
 	unsigned long flags;
 	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
 
-	DEBUGINFO (printk("ad1816: trigger called! (devc=%d,devc->base=%d\n", devc, devc->base));
+	DEBUGNOISE(printk(KERN_DEBUG "ad1816: trigger called! (devc=%d,devc->base=%d\n", devc, devc->base));
 
 	/* mode may have changed */
 
@@ -388,10 +351,17 @@
 /* set playback speed */
 static int ad1816_set_speed (int dev, int arg)
 {
+	unsigned long flags;
+	unsigned int freq;
+	int ret;
+
 	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
 	
+	spin_lock_irqsave(&devc->lock, flags);
 	if (arg == 0) {
-		return devc->speed;
+		ret = devc->speed;
+		spin_unlock_irqrestore(&devc->lock, flags);
+		return ret;
 	}
 	/* range checking */
 	if (arg < 4000) {
@@ -400,14 +370,23 @@
 	if (arg > 55000) {
 		arg = 55000;
 	}
-
 	devc->speed = arg;
-	return devc->speed;
+
+	/* change speed during playback */
+	freq=((unsigned int)devc->speed*33000)/ad1816_clockfreq; 
+	/* write playback/capture speeds */
+	ad_write (devc, 2, freq & 0xffff);	
+	ad_write (devc, 3, freq & 0xffff);	
+
+	ret = devc->speed;
+	spin_unlock_irqrestore(&devc->lock, flags);
+	return ret;
 
 }
 
 static unsigned int ad1816_set_bits (int dev, unsigned int arg)
 {
+	unsigned long flags;
 	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
 	
 	static struct format_tbl {
@@ -428,10 +407,13 @@
 
 	int  i, n = sizeof (format2bits) / sizeof (struct format_tbl);
 
+	spin_lock_irqsave(&devc->lock, flags);
 	/* return current format */
-	if (arg == 0)
-		return devc->audio_format;
-	
+	if (arg == 0) {
+	  	arg = devc->audio_format;
+		spin_unlock_irqrestore(&devc->lock, flags);
+		return arg;
+	}
 	devc->audio_format = arg;
 
 	/* search matching format bits */
@@ -439,12 +421,15 @@
 		if (format2bits[i].format == arg) {
 			devc->format_bits = format2bits[i].bits;
 			devc->audio_format = arg;
+			spin_unlock_irqrestore(&devc->lock, flags);
 			return arg;
 		}
 
 	/* Still hanging here. Something must be terribly wrong */
 	devc->format_bits = 0;
-	return devc->audio_format = AFMT_U8;
+	devc->audio_format = AFMT_U8;
+	spin_unlock_irqrestore(&devc->lock, flags);
+	return(AFMT_U8); 
 }
 
 static short ad1816_set_channels (int dev, short arg)
@@ -486,9 +471,8 @@
 	devc->speed = 8000;
 	devc->audio_format=AFMT_U8;
 	devc->channels=1;
-
-	ad1816_reset(devc->dev_no); /* halt all pending output */
 	spin_unlock_irqrestore(&devc->lock,flags);
+	ad1816_reset(devc->dev_no); /* halt all pending output */
 	return 0;
 }
 
@@ -497,17 +481,15 @@
 	unsigned long flags;
 	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
 
-	spin_lock_irqsave(&devc->lock,flags);
-
 	/* halt all pending output */
 	ad1816_reset(devc->dev_no); 
-	
+
+	spin_lock_irqsave(&devc->lock,flags);
 	devc->opened = 0;
 	devc->audio_mode = 0;
 	devc->speed = 8000;
 	devc->audio_format=AFMT_U8;
 	devc->format_bits = 0;
-
 	spin_unlock_irqrestore(&devc->lock,flags);
 }
 
@@ -543,25 +525,13 @@
 static irqreturn_t ad1816_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
 {
 	unsigned char	status;
-	ad1816_info	*devc;
-	int		dev;
-
+	ad1816_info	*devc = (ad1816_info *)dev_id;
 	
 	if (irq < 0 || irq > 15) {
 	        printk(KERN_WARNING "ad1816: Got bogus interrupt %d\n", irq);
 		return IRQ_NONE;
 	}
 
-	dev = irq2dev[irq];
-	
-	if (dev < 0 || dev >= num_audiodevs) {
-	        printk(KERN_WARNING "ad1816: IRQ2AD1816-mapping failed for "
-				    "irq %d device %d\n", irq,dev);
-		return IRQ_NONE;
-	}
-
-	devc = (ad1816_info *) audio_devs[dev]->devc;
-	
 	spin_lock(&devc->lock);
 
 	/* read interrupt register */
@@ -569,18 +539,19 @@
 	/* Clear all interrupt  */
 	outb (~status, devc->base+1);	
 
-	DEBUGNOISE (printk("ad1816: Got interrupt subclass %d\n",status));
-	
-	devc->irq_ok=1;
+	DEBUGNOISE(printk(KERN_DEBUG "ad1816: Got interrupt subclass %d\n",status));
 
-	if (status == 0)
-		DEBUGWARN(printk ("ad1816: interrupt: Got interrupt, but no reason?\n"));
+	if (status == 0) {
+		DEBUGNOISE(printk(KERN_DEBUG "ad1816: interrupt: Got interrupt, but no source.\n"));
+		spin_unlock(&devc->lock);
+		return IRQ_NONE;
+	}
 
 	if (devc->opened && (devc->audio_mode & PCM_ENABLE_INPUT) && (status&64))
-		DMAbuf_inputintr (dev);
+		DMAbuf_inputintr (devc->dev_no);
 
 	if (devc->opened && (devc->audio_mode & PCM_ENABLE_OUTPUT) && (status & 128))
-		DMAbuf_outputintr (dev, 1);
+		DMAbuf_outputintr (devc->dev_no, 1);
 
 	spin_unlock(&devc->lock);
 	return IRQ_HANDLED;
@@ -671,9 +642,11 @@
 static int
 ad1816_set_recmask (ad1816_info * devc, int mask)
 {
+  	unsigned long 	flags;
 	unsigned char   recdev;
 	int             i, n;
 	
+	spin_lock_irqsave(&devc->lock, flags);
 	mask &= devc->supported_rec_devices;
 	
 	n = 0;
@@ -733,6 +706,7 @@
 		  (ad_read (devc, 20) & 0x8f8f) | recdev | (recdev<<8));
 
 	devc->recmask = mask;
+	spin_unlock_irqrestore(&devc->lock, flags);
 	return mask;
 }
 
@@ -760,7 +734,7 @@
 static int
 ad1816_mixer_get (ad1816_info * devc, int dev)
 {
-	DEBUGINFO(printk("ad1816: mixer_get called!\n"));
+	DEBUGNOISE(printk(KERN_DEBUG "ad1816: mixer_get called!\n"));
 	
 	/* range check + supported mixer check */
 	if (dev < 0 || dev >= SOUND_MIXER_NRDEVICES )
@@ -781,8 +755,9 @@
 	int   regoffs;
 	int   val;
 	int   valmute;
+	unsigned long flags;
 
-	DEBUGINFO(printk("ad1816: mixer_set called!\n"));
+	DEBUGNOISE(printk(KERN_DEBUG "ad1816: mixer_set called!\n"));
 	
 	if (dev < 0 || dev >= SOUND_MIXER_NRDEVICES )
 		return -(EINVAL);
@@ -813,6 +788,7 @@
 	/* sanity check */
 	if (mix_devices[dev][LEFT_CHN].nbits == 0)
 		return -(EINVAL);
+	spin_lock_irqsave(&devc->lock, flags);
 
 	/* keep precise volume internal */
 	devc->levels[dev] = retvol;
@@ -840,8 +816,10 @@
 	 */
  
 	/* Was just a mono channel */
-	if (mix_devices[dev][RIGHT_CHN].nbits == 0)
+	if (mix_devices[dev][RIGHT_CHN].nbits == 0) {
+		spin_unlock_irqrestore(&devc->lock, flags);
 		return retvol;		
+	}
 
 	regoffs = mix_devices[dev][RIGHT_CHN].regno;
 	val = ad_read (devc, regoffs);
@@ -857,7 +835,7 @@
 			valmute &= ~0x80;
 	}
 	ad_write (devc, regoffs, valmute); /* mute */
-	
+	spin_unlock_irqrestore(&devc->lock, flags);
        	return retvol;
 }
 
@@ -901,7 +879,7 @@
 	ad1816_info    *devc = mixer_devs[dev]->devc;
 	int val;
   
-	DEBUGINFO(printk("ad1816: mixer_ioctl called!\n"));
+	DEBUGNOISE(printk(KERN_DEBUG "ad1816: mixer_ioctl called!\n"));
   
 	/* Mixer ioctl */
 	if (((cmd >> 8) & 0xff) == 'M') { 
@@ -980,83 +958,91 @@
 
 /* ------------------------------------------------------------------- */
 
-/* stuff for card recognition, init and unloading */
+/* stuff for card recognition, init and unloading PNP ...*/
 
 
-/* replace with probe routine */
-static int __init probe_ad1816 ( struct address_info *hw_config )
+/* check if AD1816 present at specified hw_config and register device with OS 
+ * return 1 if initialization was successful, 0 otherwise
+ */
+static int __init ad1816_init_card (struct address_info *hw_config, 
+	struct pnp_dev *pnp)
 {
-	ad1816_info    *devc = &dev_info[nr_ad1816_devs];
-	int io_base=hw_config->io_base;
-	int *osp=hw_config->osp;
+	ad1816_info    *devc = NULL;
 	int tmp;
+	int oss_devno = -1;
 
-	printk(KERN_INFO "ad1816: AD1816 sounddriver "
-			 "Copyright (C) 1998 by Thorsten Knabe\n");
-	printk(KERN_INFO "ad1816: io=0x%x, irq=%d, dma=%d, dma2=%d, "
-			 "clockfreq=%d, options=%d isadmabug=%d\n",
+	printk(KERN_INFO "ad1816: initializing card: io=0x%x, irq=%d, dma=%d, "
+			 "dma2=%d, clockfreq=%d, options=%d isadmabug=%d "
+			 "%s\n",
 	       hw_config->io_base,
 	       hw_config->irq,
 	       hw_config->dma,
 	       hw_config->dma2,
 	       ad1816_clockfreq,
 	       options,
-	       isa_dma_bridge_buggy);
-
-	if (!request_region(io_base, 16, "AD1816 Sound")) {
-		printk(KERN_WARNING "ad1816: I/O port 0x%03x not free\n",
-				    io_base);
-		goto err;
-	}
+	       isa_dma_bridge_buggy,
+	       pnp?"(PNP)":"");
 
-	DEBUGLOG(printk ("ad1816: detect(%x)\n", io_base));
-	
+	/* ad1816_info structure remaining ? */
 	if (nr_ad1816_devs >= MAX_AUDIO_DEV) {
-		printk(KERN_WARNING "ad1816: detect error - step 0\n");
-		goto out_release_region;
+		printk(KERN_WARNING "ad1816: no more ad1816_info structures "
+			"left\n");
+		goto out;
 	}
 
-	devc->base = io_base;
-	devc->irq_ok = 0;
-	devc->irq = 0;
+	devc = &dev_info[nr_ad1816_devs];
+	devc->base = hw_config->io_base;
+	devc->irq = hw_config->irq;
+	devc->dma_playback=hw_config->dma;
+	devc->dma_capture=hw_config->dma2;
 	devc->opened = 0;
-	devc->osp = osp;
+	devc->pnpdev = pnp;
 	spin_lock_init(&devc->lock);
 
+	if (!request_region(devc->base, 16, "AD1816 Sound")) {
+		printk(KERN_WARNING "ad1816: I/O port 0x%03x not free\n",
+				    devc->base);
+		goto out;
+	}
+
+	printk(KERN_INFO "ad1816: Examining AD1816 at address 0x%03x.\n", 
+		devc->base);
+	
+
+	/* tests for ad1816 */
 	/* base+0: bit 1 must be set but not 255 */
 	tmp=inb(devc->base);
 	if ( (tmp&0x80)==0 || tmp==255 ) {
-		DEBUGLOG (printk ("ad1816: Chip is not an AD1816 or chip is not active (Test 0)\n"));
+		printk (KERN_INFO "ad1816: Chip is not an AD1816 or chip "
+			"is not active (Test 0)\n");
 		goto out_release_region;
 	}
 
-
 	/* writes to ireg 8 are copied to ireg 9 */
 	ad_write(devc,8,12345); 
 	if (ad_read(devc,9)!=12345) {
-		DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 1)\n"));
+		printk(KERN_INFO "ad1816: Chip is not an AD1816 (Test 1)\n");
 		goto out_release_region;
 	}
   
 	/* writes to ireg 8 are copied to ireg 9 */
 	ad_write(devc,8,54321); 
 	if (ad_read(devc,9)!=54321) {
-		DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 2)\n"));
+		printk(KERN_INFO "ad1816: Chip is not an AD1816 (Test 2)\n");
 		goto out_release_region;
 	}
 
-
 	/* writes to ireg 10 are copied to ireg 11 */
 	ad_write(devc,10,54321); 
 	if (ad_read(devc,11)!=54321) {
-		DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 3)\n"));
+		printk (KERN_INFO "ad1816: Chip is not an AD1816 (Test 3)\n");
 		goto out_release_region;
 	}
 
 	/* writes to ireg 10 are copied to ireg 11 */
 	ad_write(devc,10,12345); 
 	if (ad_read(devc,11)!=12345) {
-		DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 4)\n"));
+		printk (KERN_INFO "ad1816: Chip is not an AD1816 (Test 4)\n");
 		goto out_release_region;
 	}
 
@@ -1064,35 +1050,12 @@
 	tmp=inb(devc->base+1);
 	outb(0xff,devc->base+1); 
 	if (inb(devc->base+1)!=tmp) {
-		DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 5)\n"));
+		printk(KERN_INFO "ad1816: Chip is not an AD1816 (Test 5)\n");
 		goto out_release_region;
 	}
-
   
-	DEBUGLOG (printk ("ad1816: detect() - Detected OK\n"));
-	DEBUGLOG (printk ("ad1816: AD1816 Version: %d\n",ad_read(devc,45)));
-
-	/* detection was successful */
-	return 1; 
-out_release_region:
-	release_region(io_base, 16);
-	/* detection was NOT successful */
-err:	return 0;
-}
-
-
-/* allocate resources from the kernel. If any allocation fails, free
-   all allocated resources and exit attach.
-  
- */
-
-static void __init attach_ad1816 (struct address_info *hw_config)
-{
-	int             my_dev;
-	char            dev_name[100];
-	ad1816_info    *devc = &dev_info[nr_ad1816_devs];
-
-	devc->base = hw_config->io_base;	
+	printk(KERN_INFO "ad1816: AD1816 (version %d) successfully detected!\n",
+		ad_read(devc,45));
 
 	/* disable all interrupts */
 	ad_write(devc,1,0);     
@@ -1101,62 +1064,54 @@
 	outb (0, devc->base+1);	
 
 	/* allocate irq */
-	if (hw_config->irq < 0 || hw_config->irq > 15)
+	if (devc->irq < 0 || devc->irq > 15)
 		goto out_release_region;
-	if (request_irq(hw_config->irq, ad1816_interrupt,0,
-			"SoundPort", hw_config->osp) < 0)	{
+	if (request_irq(devc->irq, ad1816_interrupt,0,
+			"SoundPort", devc) < 0)	{
 	        printk(KERN_WARNING "ad1816: IRQ in use\n");
 		goto out_release_region;
 	}
-	devc->irq=hw_config->irq;
 
 	/* DMA stuff */
-	if (sound_alloc_dma (hw_config->dma, "Sound System")) {
+	if (sound_alloc_dma (devc->dma_playback, "Sound System")) {
 		printk(KERN_WARNING "ad1816: Can't allocate DMA%d\n",
-				    hw_config->dma);
+				    devc->dma_playback);
 		goto out_free_irq;
 	}
-	devc->dma_playback=hw_config->dma;
 	
-	if ( hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma) {
-		if (sound_alloc_dma(hw_config->dma2,
+	if ( devc->dma_capture >= 0 && 
+	  	devc->dma_capture != devc->dma_playback) {
+		if (sound_alloc_dma(devc->dma_capture,
 				    "Sound System (capture)")) {
 			printk(KERN_WARNING "ad1816: Can't allocate DMA%d\n",
-					    hw_config->dma2);
+					    devc->dma_capture);
 			goto out_free_dma;
 		}
-		devc->dma_capture=hw_config->dma2;
 		devc->audio_mode=DMA_AUTOMODE|DMA_DUPLEX;
 	} else {
-	        devc->dma_capture=-1;
+	  	printk(KERN_WARNING "ad1816: Only one DMA channel "
+			"available/configured. No duplex operation possible\n");
 		devc->audio_mode=DMA_AUTOMODE;
 	}
 
-	sprintf (dev_name,"AD1816 audio driver");
-  
-	conf_printf2 (dev_name,
-		      devc->base, devc->irq, hw_config->dma, hw_config->dma2);
+	conf_printf2 ("AD1816 audio driver",
+		      devc->base, devc->irq, devc->dma_playback, 
+		      devc->dma_capture);
 
 	/* register device */
-	if ((my_dev = sound_install_audiodrv (AUDIO_DRIVER_VERSION,
-					      dev_name,
+	if ((oss_devno = sound_install_audiodrv (AUDIO_DRIVER_VERSION,
+					      "AD1816 audio driver",
 					      &ad1816_audio_driver,
 					      sizeof (struct audio_driver),
 					      devc->audio_mode,
 					      ad_format_mask,
 					      devc,
-					      hw_config->dma, 
-					      hw_config->dma2)) < 0) {
+					      devc->dma_playback, 
+					      devc->dma_capture)) < 0) {
 		printk(KERN_WARNING "ad1816: Can't install sound driver\n");
 		goto out_free_dma_2;
 	}
 
-	/* fill rest of structure with reasonable default values */
-	irq2dev[hw_config->irq] = devc->dev_no = my_dev;
-	devc->opened = 0;
-	devc->irq_ok = 0;
-	devc->osp = hw_config->osp;  
-	nr_ad1816_devs++;
 
 	ad_write(devc,32,0x80f0); /* sound system mode */
 	if (options&1) {
@@ -1186,25 +1141,30 @@
 	ad1816_mixer_reset (devc); 
   
 	/* register mixer */
-	if ((audio_devs[my_dev]->mixer_dev=sound_install_mixer(
+	if ((audio_devs[oss_devno]->mixer_dev=sound_install_mixer(
 				       MIXER_DRIVER_VERSION,
-				       dev_name,
+				       "AD1816 audio driver",
 				       &ad1816_mixer_operations,
 				       sizeof (struct mixer_operations),
-				       devc)) >= 0) {
-		audio_devs[my_dev]->min_fragment = 0;
+				       devc)) < 0) {
+	  	printk(KERN_WARNING "Can't install mixer\n");
 	}
-out:	return;
+	/* make ad1816_info active */
+	nr_ad1816_devs++;
+	printk(KERN_INFO "ad1816: card successfully installed!\n");
+	return 1;
+	/* error handling */
 out_free_dma_2:
-	if (devc->dma_capture >= 0)
-	        sound_free_dma(hw_config->dma2);
+	if (devc->dma_capture >= 0 && devc->dma_capture != devc->dma_playback)
+	        sound_free_dma(devc->dma_capture);
 out_free_dma:
-	sound_free_dma(hw_config->dma);
+	sound_free_dma(devc->dma_playback);
 out_free_irq:
-	free_irq(hw_config->irq,hw_config->osp);
+	free_irq(devc->irq, devc);
 out_release_region:
-	release_region(hw_config->io_base, 16);
-	goto out;
+	release_region(devc->base, 16);
+out:
+	return 0;
 }
 
 static void __exit unload_card(ad1816_info *devc)
@@ -1212,7 +1172,7 @@
 	int  mixer, dev = 0;
 	
 	if (devc != NULL) {
-		DEBUGLOG (printk("ad1816: Unloading card at base=%x\n",devc->base));
+		printk("ad1816: Unloading card at address 0x%03x\n",devc->base);
 		
 		dev = devc->dev_no;
 		mixer = audio_devs[dev]->mixer_dev;
@@ -1221,45 +1181,41 @@
 		if(mixer>=0) {
 			sound_unload_mixerdev(mixer);
 		}
+		/* unreg audiodev */
 		sound_unload_audiodev(dev);
 		
 		/* free dma channels */
-		if (devc->dma_capture>=0) {
+		if (devc->dma_capture>=0 && 
+		  	devc->dma_capture != devc->dma_playback) {
 			sound_free_dma(devc->dma_capture);
 		}
-
-		/* card won't get added if resources could not be allocated
-		   thus we need not ckeck if allocation was successful */
 		sound_free_dma (devc->dma_playback);
-		free_irq(devc->irq, devc->osp);
+		/* free irq */
+		free_irq(devc->irq, devc);
+		/* free io */
 		release_region (devc->base, 16);
-		
-		DEBUGLOG (printk("ad1816: Unloading card at base=%x was successful\n",devc->base));
+#ifdef __ISAPNP__
+		if (devc->pnpdev) {
+		  	pnp_disable_dev(devc->pnpdev);
+			pnp_device_detach(devc->pnpdev);
+		}
+#endif
 		
 	} else
 		printk(KERN_WARNING "ad1816: no device/card specified\n");
 }
 
-static struct address_info cfg;
-
 static int __initdata io = -1;
 static int __initdata irq = -1;
 static int __initdata dma = -1;
 static int __initdata dma2 = -1;
 
 #ifdef __ISAPNP__
-struct pci_dev	*ad1816_dev  = NULL;
-
-static int activated	= 1;
-
+/* use isapnp for configuration */
 static int isapnp	= 1;
 static int isapnpjump	= 0;
-
 MODULE_PARM(isapnp, "i");
 MODULE_PARM(isapnpjump, "i");
-
-#else
-static int isapnp = 0;
 #endif
 
 MODULE_PARM(io,"i");
@@ -1270,51 +1226,6 @@
 MODULE_PARM(options,"i");
 
 #ifdef __ISAPNP__
-
-static struct pci_dev *activate_dev(char *devname, char *resname, struct pci_dev *dev)
-{
-	int err;
-	
-	if(dev->active) {
-		activated = 0;
-		return(dev);
-	}
-
-	if((err = dev->activate(dev)) < 0) {
-		printk(KERN_ERR "ad1816: %s %s config failed (out of resources?)[%d]\n",
-			devname, resname, err);
-		dev->deactivate(dev);
-		return(NULL);
-	}
-		
-	return(dev);
-}
-
-static struct pci_dev *ad1816_init_generic(struct pci_bus *bus, struct pci_dev *card,
-	struct address_info *hw_config)
-{
-	if((ad1816_dev = isapnp_find_dev(bus, card->vendor, card->device, NULL))) {
-		ad1816_dev->prepare(ad1816_dev);
-		
-		if((ad1816_dev = activate_dev("Analog Devices 1816(A)", "ad1816", ad1816_dev))) {
-			hw_config->io_base	= ad1816_dev->resource[2].start;
-			hw_config->irq		= ad1816_dev->irq_resource[0].start;
-			hw_config->dma		= ad1816_dev->dma_resource[0].start;
-			hw_config->dma2		= ad1816_dev->dma_resource[1].start;
-		}
-	}
-	
-	return(ad1816_dev);
-}
-
-static struct ad1816_data {
-	struct pci_dev * (*initfunc)(struct pci_bus*, struct pci_dev *, struct address_info *);
-	char *name;
-} ad1816_pnp_data[] __initdata = {
-	{ &ad1816_init_generic, "Analog Devices 1815" },
-	{ &ad1816_init_generic, "Analog Devices 1816A" }
-};
-
 static struct {
 	unsigned short card_vendor, card_device;
 	unsigned short vendor;
@@ -1323,107 +1234,101 @@
 } isapnp_ad1816_list[] __initdata = {
 	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
 		ISAPNP_VENDOR('A','D','S'), ISAPNP_FUNCTION(0x7150), 
-		&ad1816_pnp_data[0] },
+		0 },
 	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
 		ISAPNP_VENDOR('A','D','S'), ISAPNP_FUNCTION(0x7180),
-		&ad1816_pnp_data[1] },
+		0 },
 	{0}
 };
 
 MODULE_DEVICE_TABLE(isapnp, isapnp_ad1816_list);
 
-static int __init ad1816_init_isapnp(struct address_info *hw_config,
-	struct pci_bus *bus, struct pci_dev *card, int slot)
+
+void __init ad1816_config_pnp_card(struct pnp_card *card, unsigned short vendor,
+	unsigned short function)
 {
-	struct pci_dev *idev = NULL;
-	
-	/* You missed the init func? That's bad. */
-	if(isapnp_ad1816_list[slot].data->initfunc) {
-		char *busname = bus->name[0] ? bus->name : isapnp_ad1816_list[slot].data->name;
-		
-		printk(KERN_INFO "ad1816: %s detected\n", busname);
-		
-		/* Initialize this baby. */
-		if((idev = isapnp_ad1816_list[slot].data->initfunc(bus, card, hw_config))) {
-			/* We got it. */
-
-			printk(KERN_NOTICE "ad1816: ISAPnP reports '%s' at i/o %#x, irq %d, dma %d, %d\n",
-				busname,
-				hw_config->io_base, hw_config->irq, hw_config->dma,
-				hw_config->dma2);
-			return 1;
-		} else
-			printk(KERN_INFO "ad1816: Failed to initialize %s\n", busname);
-	} else
-		printk(KERN_ERR "ad1816: Bad entry in ad1816.c PnP table\n");
-	
-	return 0;
+	struct address_info cfg;
+  	struct pnp_dev *card_dev = pnp_find_dev(card, vendor, function, NULL);
+	if (!card_dev) return;
+	if (pnp_device_attach(card_dev) < 0) {
+	  	printk(KERN_WARNING "ad1816: Failed to attach PnP device\n");
+		return;
+	}
+	if (pnp_activate_dev(card_dev) < 0) {
+		printk(KERN_WARNING "ad1816: Failed to activate PnP device\n");
+		pnp_device_detach(card_dev);
+		return;
+	}
+	cfg.io_base = pnp_port_start(card_dev, 2);
+	cfg.irq = pnp_irq(card_dev, 0);
+	cfg.dma = pnp_irq(card_dev, 0);
+	cfg.dma2 = pnp_irq(card_dev, 1);
+	if (!ad1816_init_card(&cfg, card_dev)) {
+	  	pnp_disable_dev(card_dev);
+		pnp_device_detach(card_dev);
+	}
 }
 
-/*
- * Actually this routine will detect and configure only the first card with successful
- * initialization. isapnpjump could be used to jump to a specific entry.
- * Please always add entries at the end of the array.
- * Should this be fixed? - azummo
- */
-
-int __init ad1816_probe_isapnp(struct address_info *hw_config)
+void __init ad1816_config_pnp_cards(void)
 {
+	int nr_pnp_cfg;
 	int i;
 	
 	/* Count entries in isapnp_ad1816_list */
-	for (i = 0; isapnp_ad1816_list[i].vendor != 0; i++)
-		;
+	for (nr_pnp_cfg = 0; isapnp_ad1816_list[nr_pnp_cfg].card_vendor != 0; 
+		nr_pnp_cfg++);
 	/* Check and adjust isapnpjump */
-	if( isapnpjump < 0 || isapnpjump > ( i - 1 ) ) {
-		printk(KERN_ERR "ad1816: Valid range for isapnpjump is 0-%d. Adjusted to 0.\n", i-1);
+	if( isapnpjump < 0 || isapnpjump >= nr_pnp_cfg) {
+		printk(KERN_WARNING 
+			"ad1816: Valid range for isapnpjump is 0-%d. "
+			"Adjusted to 0.\n", nr_pnp_cfg-1);
 		isapnpjump = 0;
 	}
-
-	 for (i = isapnpjump; isapnp_ad1816_list[i].vendor != 0; i++) {
-	 	struct pci_dev *card = NULL;
-		
-		while ((card = isapnp_find_dev(NULL, isapnp_ad1816_list[i].vendor,
-		  isapnp_ad1816_list[i].function, card)))
-			if(ad1816_init_isapnp(hw_config, card->bus, card, i))
-				return 0;
+	for (i = isapnpjump; isapnp_ad1816_list[i].card_vendor != 0; i++) {
+	 	struct pnp_card *card = NULL;
+		/* iterate over all pnp cards */		
+		while ((card = pnp_find_card(isapnp_ad1816_list[i].card_vendor,
+		              	isapnp_ad1816_list[i].card_device, card))) 
+			ad1816_config_pnp_card(card, 
+				isapnp_ad1816_list[i].vendor,
+				isapnp_ad1816_list[i].function);
 	}
-
-	return -ENODEV;
 }
 #endif
 
+/* module initialization */
 static int __init init_ad1816(void)
 {
-
-#ifdef __ISAPNP__
-	if(isapnp && (ad1816_probe_isapnp(&cfg) < 0) ) {
-		printk(KERN_NOTICE "ad1816: No ISAPnP cards found, trying standard ones...\n");
-		isapnp = 0;
-	}
+	printk(KERN_INFO "ad1816: AD1816 sounddriver "
+			 "Copyright (C) 1998-2003 by Thorsten Knabe and "
+			 "others\n");
+#ifdef AD1816_CLOCK 
+	/* set ad1816_clockfreq if set during compilation */
+	ad1816_clockfreq=AD1816_CLOCK;
 #endif
-
-	if( isapnp == 0) {
-		cfg.io_base	= io;
-		cfg.irq		= irq;
-		cfg.dma		= dma;
-		cfg.dma2	= dma2;
-	}
-
-	if (cfg.io_base == -1 || cfg.irq == -1 || cfg.dma == -1 || cfg.dma2 == -1) {
-		printk(KERN_INFO "ad1816: dma, dma2, irq and io must be set.\n");
-		return -EINVAL;
+	if (ad1816_clockfreq<5000 || ad1816_clockfreq>100000) {
+		ad1816_clockfreq=33000;
 	}
 
-	if (probe_ad1816(&cfg) == 0) {
-		return -ENODEV;
+#ifdef __ISAPNP__
+	/* configure PnP cards */
+	if(isapnp) ad1816_config_pnp_cards();
+#endif
+	/* configure card by module params */
+	if (io != -1 && irq != -1 && dma != -1) {
+		struct address_info cfg;
+		cfg.io_base = io;
+		cfg.irq = irq;
+		cfg.dma = dma;
+		cfg.dma2 = dma2;
+		ad1816_init_card(&cfg, NULL);
 	}
-
-	attach_ad1816(&cfg);
-
+	if (nr_ad1816_devs <= 0)
+	  	return -ENODEV;
 	return 0;
 }
 
+/* module cleanup */
 static void __exit cleanup_ad1816 (void)
 {
 	int          i;
@@ -1435,18 +1340,14 @@
 		unload_card(devc);
 	}     
 	nr_ad1816_devs=0;
-
-#ifdef __ISAPNP__
-	if(activated)
-		if(ad1816_dev)
-			ad1816_dev->deactivate(ad1816_dev);
-#endif
+	printk(KERN_INFO "ad1816: driver unloaded!\n");
 }
 
 module_init(init_ad1816);
 module_exit(cleanup_ad1816);
 
 #ifndef MODULE
+/* kernel command line parameter evaluation */
 static int __init setup_ad1816(char *str)
 {
 	/* io, irq, dma, dma2 */
@@ -1458,7 +1359,6 @@
 	irq	= ints[2];
 	dma	= ints[3];
 	dma2	= ints[4];
-
 	return 1;
 }
 
diff -Nru a/sound/oss/ad1889.c b/sound/oss/ad1889.c
--- a/sound/oss/ad1889.c	Sat Jul 19 12:54:24 2003
+++ b/sound/oss/ad1889.c	Sat Jul 19 12:54:24 2003
@@ -245,7 +245,6 @@
 		dmabuf->ready = 0;
 		dmabuf->rate = 44100;
 	}
-out:
 	return dev;
 
 err_free_dmabuf:
diff -Nru a/sound/oss/btaudio.c b/sound/oss/btaudio.c
--- a/sound/oss/btaudio.c	Sat Jul 19 12:54:23 2003
+++ b/sound/oss/btaudio.c	Sat Jul 19 12:54:23 2003
@@ -328,8 +328,8 @@
 	if (cmd == SOUND_MIXER_INFO) {
 		mixer_info info;
 		memset(&info,0,sizeof(info));
-                strncpy(info.id,"bt878",sizeof(info.id));
-                strncpy(info.name,"Brooktree Bt878 audio",sizeof(info.name));
+                strlcpy(info.id,"bt878",sizeof(info.id));
+                strlcpy(info.name,"Brooktree Bt878 audio",sizeof(info.name));
                 info.modify_counter = bta->mixcount;
                 if (copy_to_user((void *)arg, &info, sizeof(info)))
                         return -EFAULT;
@@ -338,8 +338,8 @@
 	if (cmd == SOUND_OLD_MIXER_INFO) {
 		_old_mixer_info info;
 		memset(&info,0,sizeof(info));
-                strncpy(info.id,"bt878",sizeof(info.id)-1);
-                strncpy(info.name,"Brooktree Bt878 audio",sizeof(info.name));
+                strlcpy(info.id,"bt878",sizeof(info.id)-1);
+                strlcpy(info.name,"Brooktree Bt878 audio",sizeof(info.name));
                 if (copy_to_user((void *)arg, &info, sizeof(info)))
                         return -EFAULT;
 		return 0;
diff -Nru a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c
--- a/sound/oss/dmasound/dmasound_core.c	Sat Jul 19 12:54:23 2003
+++ b/sound/oss/dmasound/dmasound_core.c	Sat Jul 19 12:54:23 2003
@@ -1660,13 +1660,13 @@
 #ifdef HAS_RECORD
         case 5:
                 if ((ints[5] < 0) || (ints[5] > MAX_CATCH_RADIUS))
-                        printk("dmasound_setup: illegal catch radius, using default = %d\n", catchRadius);
+                        printk("dmasound_setup: invalid catch radius, using default = %d\n", catchRadius);
                 else
                         catchRadius = ints[5];
                 /* fall through */
         case 4:
                 if (ints[4] < MIN_BUFFERS)
-                        printk("dmasound_setup: illegal number of read buffers, using default = %d\n",
+                        printk("dmasound_setup: invalid number of read buffers, using default = %d\n",
                                  numReadBufs);
                 else
                         numReadBufs = ints[4];
@@ -1675,21 +1675,21 @@
 		if ((size = ints[3]) < 256)  /* check for small buffer specs */
 			size <<= 10 ;
                 if (size < MIN_BUFSIZE || size > MAX_BUFSIZE)
-                        printk("dmasound_setup: illegal read buffer size, using default = %d\n", readBufSize);
+                        printk("dmasound_setup: invalid read buffer size, using default = %d\n", readBufSize);
                 else
                         readBufSize = size;
                 /* fall through */
 #else
 	case 3:
 		if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS))
-			printk("dmasound_setup: illegal catch radius, using default = %d\n", catchRadius);
+			printk("dmasound_setup: invalid catch radius, using default = %d\n", catchRadius);
 		else
 			catchRadius = ints[3];
 		/* fall through */
 #endif
 	case 2:
 		if (ints[1] < MIN_BUFFERS)
-			printk("dmasound_setup: illegal number of buffers, using default = %d\n", numWriteBufs);
+			printk("dmasound_setup: invalid number of buffers, using default = %d\n", numWriteBufs);
 		else
 			numWriteBufs = ints[1];
 		/* fall through */
@@ -1697,13 +1697,13 @@
 		if ((size = ints[2]) < 256) /* check for small buffer specs */
 			size <<= 10 ;
                 if (size < MIN_BUFSIZE || size > MAX_BUFSIZE)
-                        printk("dmasound_setup: illegal write buffer size, using default = %d\n", writeBufSize);
+                        printk("dmasound_setup: invalid write buffer size, using default = %d\n", writeBufSize);
                 else
                         writeBufSize = size;
 	case 0:
 		break;
 	default:
-		printk("dmasound_setup: illegal number of arguments\n");
+		printk("dmasound_setup: invalid number of arguments\n");
 		return 0;
 	}
 	return 1;
diff -Nru a/sound/oss/emu10k1/8010.h b/sound/oss/emu10k1/8010.h
--- a/sound/oss/emu10k1/8010.h	Sat Jul 19 12:54:21 2003
+++ b/sound/oss/emu10k1/8010.h	Sat Jul 19 12:54:21 2003
@@ -1,7 +1,7 @@
 /*
  **********************************************************************
  *     8010.h
- *     Copyright 1999, 2000 Creative Labs, Inc.
+ *     Copyright 1999-2001 Creative Labs, Inc.
  *
  **********************************************************************
  *
@@ -11,6 +11,8 @@
  *     November 2, 1999     Alan Cox	    Cleaned of 8bit chars, DOS
  *					    line endings
  *     December 8, 1999     Jon Taylor	    Added lots of new register info
+ *     May 16, 2001         Daniel Bertrand Added unofficial DBG register info
+ *     Oct-Nov 2001         D.B.            Added unofficial Audigy registers 
  *
  **********************************************************************
  *
@@ -39,6 +41,14 @@
 
 #include <linux/types.h>
 
+// Driver version:
+#define MAJOR_VER 0
+#define MINOR_VER 20
+#define DRIVER_VERSION "0.20a"
+
+
+// Audigy specify registers are prefixed with 'A_'
+
 /************************************************************************************************/
 /* PCI function 0 registers, address = <val> + PCIBASE0						*/
 /************************************************************************************************/
@@ -57,6 +67,11 @@
 #define IPR			0x08		/* Global interrupt pending register		*/
 						/* Clear pending interrupts by writing a 1 to	*/
 						/* the relevant bits and zero to the other bits	*/
+
+/* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1)			*/
+#define A_IPR_MIDITRANSBUFEMPTY2	0x10000000	/* MIDI UART transmit buffer empty		*/
+#define A_IPR_MIDIRECVBUFEMPTY2	0x08000000	/* MIDI UART receive buffer empty		*/
+
 #define IPR_SAMPLERATETRACKER	0x01000000	/* Sample rate tracker lock status change	*/
 #define IPR_FXDSP		0x00800000	/* Enable FX DSP interrupts			*/
 #define IPR_FORCEINT		0x00400000	/* Force Sound Blaster interrupt		*/
@@ -81,6 +96,10 @@
 						/* IP is written with CL set, the bit in CLIPL	*/
 						/* or CLIPH corresponding to the CIN value 	*/
 						/* written will be cleared.			*/
+#define A_IPR_MIDITRANSBUFEMPTY1	IPR_MIDITRANSBUFEMPTY	/* MIDI UART transmit buffer empty		*/
+#define A_IPR_MIDIRECVBUFEMPTY1	IPR_MIDIRECVBUFEMPTY	/* MIDI UART receive buffer empty		*/
+
+
 
 #define INTE			0x0c		/* Interrupt enable register			*/
 #define INTE_VIRTUALSB_MASK	0xc0000000	/* Virtual Soundblaster I/O port capture	*/
@@ -108,6 +127,11 @@
 						/* behavior and possibly random segfaults and	*/
 						/* lockups if enabled.				*/
 
+/* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1)			*/
+#define A_INTE_MIDITXENABLE2	0x00020000	/* Enable MIDI transmit-buffer-empty interrupts	*/
+#define A_INTE_MIDIRXENABLE2	0x00010000	/* Enable MIDI receive-buffer-empty interrupts	*/
+
+
 #define INTE_SAMPLERATETRACKER	0x00002000	/* Enable sample rate tracker interrupts	*/
 						/* NOTE: This bit must always be enabled       	*/
 #define INTE_FXDSPENABLE	0x00001000	/* Enable FX DSP interrupts			*/
@@ -124,6 +148,10 @@
 #define INTE_MIDITXENABLE	0x00000002	/* Enable MIDI transmit-buffer-empty interrupts	*/
 #define INTE_MIDIRXENABLE	0x00000001	/* Enable MIDI receive-buffer-empty interrupts	*/
 
+/* The next two interrupts are for the midi port on the Audigy (A_MPU2)	*/
+#define A_INTE_MIDITXENABLE1  	INTE_MIDITXENABLE
+#define A_INTE_MIDIRXENABLE1	INTE_MIDIRXENABLE
+
 #define WC			0x10		/* Wall Clock register				*/
 #define WC_SAMPLECOUNTER_MASK	0x03FFFFC0	/* Sample periods elapsed since reset		*/
 #define WC_SAMPLECOUNTER	0x14060010
@@ -186,6 +214,8 @@
 						/* Should be set to 1 when the EMU10K1 is	*/
 						/* completely initialized.			*/
 
+//For Audigy, MPU port move to 0x70-0x74 ptr register
+
 #define MUDATA			0x18		/* MPU401 data register (8 bits)       		*/
 
 #define MUCMD			0x19		/* MPU401 command register (8 bits)    		*/
@@ -197,13 +227,16 @@
 #define MUSTAT_IRDYN		0x80		/* 0 = MIDI data or command ACK			*/
 #define MUSTAT_ORDYN		0x40		/* 0 = MUDATA can accept a command or data	*/
 
-#define TIMER			0x1a		/* Timer terminal count register		*/
+#define A_IOCFG			0x18		/* GPIO on Audigy card (16bits)			*/
+#define A_GPINPUT_MASK		0xff00
+#define A_GPOUTPUT_MASK		0x00ff
+
+#define TIMER			0x1a		/* Timer terminal count register (16-bit)	*/
 						/* NOTE: After the rate is changed, a maximum	*/
 						/* of 1024 sample periods should be allowed	*/
 						/* before the new rate is guaranteed accurate.	*/
-#define TIMER_RATE_MASK		0x000003ff	/* Timer interrupt rate in sample periods	*/
+#define TIMER_RATE_MASK		0x03ff		/* Timer interrupt rate in sample periods	*/
 						/* 0 == 1024 periods, [1..4] are not useful	*/
-#define TIMER_RATE		0x0a00001a
 
 #define AC97DATA		0x1c		/* AC97 register set data register (16 bit)	*/
 
@@ -386,6 +419,8 @@
 #define TREMFRQ 		0x1c		/* Tremolo amount and modulation LFO frequency register	*/
 #define TREMFRQ_DEPTH		0x0000ff00	/* Tremolo depth					*/
 						/* Signed 2's complement, with +/- 12dB extremes	*/
+#define TREMFRQ_FREQUENCY	0x000000ff	/* Tremolo LFO frequency				*/
+						/* ??Hz steps, maximum of ?? Hz.			*/
 
 #define FM2FRQ2 		0x1d		/* Vibrato amount and vibrato LFO frequency register	*/
 #define FM2FRQ2_DEPTH		0x0000ff00	/* Vibrato LFO vibrato depth				*/
@@ -426,7 +461,12 @@
 #define ADCCR_LCHANENABLE	0x00000008	/* Enables left channel for writing to the host		*/
 						/* NOTE: To guarantee phase coherency, both channels	*/
 						/* must be disabled prior to enabling both channels.	*/
+#define A_ADCCR_RCHANENABLE	0x00000020
+#define A_ADCCR_LCHANENABLE	0x00000010
+
+#define A_ADCCR_SAMPLERATE_MASK 0x0000000F      /* Audigy sample rate convertor output rate		*/
 #define ADCCR_SAMPLERATE_MASK	0x00000007	/* Sample rate convertor output rate			*/
+
 #define ADCCR_SAMPLERATE_48	0x00000000	/* 48kHz sample rate					*/
 #define ADCCR_SAMPLERATE_44	0x00000001	/* 44.1kHz sample rate					*/
 #define ADCCR_SAMPLERATE_32	0x00000002	/* 32kHz sample rate					*/
@@ -436,10 +476,16 @@
 #define ADCCR_SAMPLERATE_11	0x00000006	/* 11.025kHz sample rate				*/
 #define ADCCR_SAMPLERATE_8	0x00000007	/* 8kHz sample rate					*/
 
+#define A_ADCCR_SAMPLERATE_12	0x00000006	/* 12kHz sample rate					*/
+#define A_ADCCR_SAMPLERATE_11	0x00000007	/* 11.025kHz sample rate				*/
+#define A_ADCCR_SAMPLERATE_8	0x00000008	/* 8kHz sample rate					*/
+
 #define FXWC			0x43		/* FX output write channels register			*/
 						/* When set, each bit enables the writing of the	*/
-						/* corresponding FX output channel into host memory	*/
-
+						/* corresponding FX output channel (internal registers  */
+						/* 0x20-0x3f) into host memory. This mode of recording	*/
+						/* is 16bit, 48KHz only. All 32	channels can be enabled */
+						/* simultaneously.					*/
 #define TCBS			0x44		/* Tank cache buffer size register			*/
 #define TCBS_MASK		0x00000007	/* Tank cache buffer size field				*/
 #define TCBS_BUFFSIZE_16K	0x00000000
@@ -519,6 +565,13 @@
 
 #define REG53			0x53		/* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */
 
+#define A_DBG			 0x53
+#define A_DBG_SINGLE_STEP	 0x00020000	/* Set to zero to start dsp */
+#define A_DBG_ZC		 0x40000000	/* zero tram counter */
+#define A_DBG_STEP_ADDR		 0x000003ff
+#define A_DBG_SATURATION_OCCURED 0x20000000
+#define A_DBG_SATURATION_ADDR	 0x0ffc0000
+
 #define SPCS0			0x54		/* SPDIF output Channel Status 0 register	*/
 
 #define SPCS1			0x55		/* SPDIF output Channel Status 1 register	*/
@@ -582,10 +635,19 @@
 #define SRCS_RATELOCKED		0x01000000	/* Sample rate locked				*/
 #define SRCS_ESTSAMPLERATE	0x0007ffff	/* Do not modify this field.			*/
 
+
+/* Note that these values can vary +/- by a small amount                                        */
+#define SRCS_SPDIFRATE_44	0x0003acd9
+#define SRCS_SPDIFRATE_48	0x00040000
+#define SRCS_SPDIFRATE_96	0x00080000
+
 #define MICIDX                  0x63            /* Microphone recording buffer index register   */
 #define MICIDX_MASK             0x0000ffff      /* 16-bit value                                 */
 #define MICIDX_IDX		0x10000063
 
+#define A_ADCIDX		0x63
+#define A_ADCIDX_IDX		0x10000063
+
 #define ADCIDX			0x64		/* ADC recording buffer index register		*/
 #define ADCIDX_MASK		0x0000ffff	/* 16 bit index field				*/
 #define ADCIDX_IDX		0x10000064
@@ -594,9 +656,50 @@
 #define FXIDX_MASK		0x0000ffff	/* 16-bit value					*/
 #define FXIDX_IDX		0x10000065
 
+/* This is the MPU port on the card (via the game port)						*/
+#define A_MUDATA1		0x70
+#define A_MUCMD1		0x71
+#define A_MUSTAT1		A_MUCMD1
+
+/* This is the MPU port on the Audigy Drive 							*/
+#define A_MUDATA2		0x72
+#define A_MUCMD2		0x73
+#define A_MUSTAT2		A_MUCMD2	
+
+/* The next two are the Audigy equivalent of FXWC						*/
+/* the Audigy can record any output (16bit, 48kHz, up to 64 channel simultaneously) 		*/
+/* Each bit selects a channel for recording */
+#define A_FXWC1			0x74            /* Selects 0x7f-0x60 for FX recording           */
+#define A_FXWC2			0x75		/* Selects 0x9f-0x80 for FX recording           */
+
+#define A_SPDIF_SAMPLERATE	0x76		/* Set the sample rate of SPDIF output		*/
+#define A_SPDIF_48000		0x00000080
+#define A_SPDIF_44100		0x00000000
+#define A_SPDIF_96000		0x00000040
+
+#define A_FXRT2			0x7c
+#define A_FXRT_CHANNELE		0x0000003f	/* Effects send bus number for channel's effects send E	*/
+#define A_FXRT_CHANNELF		0x00003f00	/* Effects send bus number for channel's effects send F	*/
+#define A_FXRT_CHANNELG		0x003f0000	/* Effects send bus number for channel's effects send G	*/
+#define A_FXRT_CHANNELH		0x3f000000	/* Effects send bus number for channel's effects send H	*/
+
+#define A_SENDAMOUNTS		0x7d
+#define A_FXSENDAMOUNT_E_MASK	0xff000000
+#define A_FXSENDAMOUNT_F_MASK	0x00ff0000
+#define A_FXSENDAMOUNT_G_MASK	0x0000ff00
+#define A_FXSENDAMOUNT_H_MASK	0x000000ff
+
+/* The send amounts for this one are the same as used with the emu10k1 */
+#define A_FXRT1			0x7e
+#define A_FXRT_CHANNELA		0x0000003f
+#define A_FXRT_CHANNELB		0x00003f00
+#define A_FXRT_CHANNELC		0x003f0000
+#define A_FXRT_CHANNELD		0x3f000000
+
+
 /* Each FX general purpose register is 32 bits in length, all bits are used			*/
 #define FXGPREGBASE		0x100		/* FX general purpose registers base       	*/
-
+#define A_FXGPREGBASE		0x400		/* Audigy GPRs, 0x400 to 0x5ff			*/
 /* Tank audio data is logarithmically compressed down to 16 bits before writing to TRAM and is	*/
 /* decompressed back to 20 bits on a read.  There are a total of 160 locations, the last 32	*/
 /* locations are for external TRAM. 								*/
@@ -620,5 +723,15 @@
 #define HIWORD_OPCODE_MASK	0x00f00000	/* Instruction opcode				*/
 #define HIWORD_RESULT_MASK	0x000ffc00	/* Instruction result				*/
 #define HIWORD_OPA_MASK		0x000003ff	/* Instruction operand A			*/
+
+
+/* Audigy Soundcard have a different instruction format */
+#define AUDIGY_CODEBASE		0x600
+#define A_LOWORD_OPY_MASK	0x000007ff		
+#define A_LOWORD_OPX_MASK	0x007ff000
+#define A_HIWORD_OPCODE_MASK	0x0f000000
+#define A_HIWORD_RESULT_MASK	0x007ff000
+#define A_HIWORD_OPA_MASK	0x000007ff
+
 
 #endif /* _8010_H */
diff -Nru a/sound/oss/emu10k1/audio.c b/sound/oss/emu10k1/audio.c
--- a/sound/oss/emu10k1/audio.c	Sat Jul 19 12:54:22 2003
+++ b/sound/oss/emu10k1/audio.c	Sat Jul 19 12:54:22 2003
@@ -158,8 +158,8 @@
 		spin_unlock_irqrestore(&woinst->lock, flags);
 		return -ENXIO;
 	}
-
-	if (woinst->format.passthrough) {
+	// This is for emu10k1 revs less than 7, we need to go through tram
+	if (woinst->format.passthrough == 1) {
 		int r;
 		
 		woinst->buffer.ossfragshift = PT_BLOCKSIZE_LOG2;
@@ -350,8 +350,9 @@
 
 	case SNDCTL_DSP_GETCAPS:
 		DPF(2, "SNDCTL_DSP_GETCAPS:\n");
-		return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP | DSP_CAP_COPROC, (int *) arg);
-
+		return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME |
+				DSP_CAP_TRIGGER | DSP_CAP_MMAP |
+				DSP_CAP_COPROC| DSP_CAP_MULTI, (int *) arg);
 	case SNDCTL_DSP_SPEED:
 		DPF(2, "SNDCTL_DSP_SPEED:\n");
 
@@ -528,8 +529,8 @@
 		else if (file->f_mode & FMODE_WRITE) {
 			val = AFMT_S16_LE | AFMT_U8;
 			if (emu10k1_find_control_gpr(&wave_dev->card->mgr,
-			    			     wave_dev->card->pt.patch_name, 
-			    			     wave_dev->card->pt.enable_gpr_name) >= 0)
+						     wave_dev->card->pt.patch_name, 
+						     wave_dev->card->pt.enable_gpr_name) >= 0)
 				val |= AFMT_AC3;
 		}
 		return put_user(val, (int *) arg);
@@ -789,7 +790,7 @@
 				cinfo.blocks = 0;
 			}
 
-			if(wiinst->mmapped)
+			if (wiinst->mmapped)
 				wiinst->buffer.bytestocopy %= wiinst->buffer.fragment_size;
 
 			spin_unlock_irqrestore(&wiinst->lock, flags);
@@ -811,15 +812,17 @@
 			spin_lock_irqsave(&woinst->lock, flags);
 
 			if (woinst->state & WAVE_STATE_OPEN || 
-			    (woinst->format.passthrough && wave_dev->card->pt.state)) {
+			    ((woinst->format.passthrough == 1) && wave_dev->card->pt.state)) {
 				int num_fragments;
-				if (woinst->format.passthrough) {
+
+				if (woinst->format.passthrough == 1) {
 					emu10k1_pt_waveout_update(wave_dev);
 					cinfo.bytes = woinst->total_played;
 				} else {
 					emu10k1_waveout_update(woinst);
 					cinfo.bytes = woinst->total_played;
 				}
+
 				cinfo.ptr = woinst->buffer.hw_pos;
 				num_fragments = cinfo.bytes / woinst->buffer.fragment_size;
 				cinfo.blocks = num_fragments - woinst->blocks;
@@ -899,7 +902,7 @@
 
 		if (file->f_mode & FMODE_WRITE) {
 			/* digital pass-through fragment count and size are fixed values */
-			if (woinst->state & WAVE_STATE_OPEN || woinst->format.passthrough)
+			if (woinst->state & WAVE_STATE_OPEN || (woinst->format.passthrough == 1))
 				return -EINVAL;	/* too late to change */
 
 			woinst->buffer.ossfragshift = val & 0xffff;
@@ -936,19 +939,35 @@
 				kfree (buf);
 				return -EINVAL;
 			}
+
+			if (buf->command == CMD_WRITE) {
+				
 #ifdef DBGEMU
-			if ( (buf->offs < 0) || (buf->offs + buf->len > 0x800) || (buf->len > 1000)) {
+				if ((buf->offs < 0) || (buf->offs + buf->len > 0xe00) || (buf->len > 1000)) {
 #else
-			if ( ((buf->offs < 0x100 ) || (buf->offs + buf->len > 0x800) || (buf->len > 1000))
-			     && !( ( buf->offs == DBG) && (buf->len ==1) )){
-#endif	
-				kfree(buf);
-				return -EINVAL;
-			}
+				if (((buf->offs < 0x100) || (buf->offs + buf->len > (wave_dev->card->is_audigy ? 0xe00 : 0x800)) || (buf->len > 1000)
+				) && !(
+					//any register allowed raw access to users goes here:
+					(buf->offs == DBG ||
+					  buf->offs == A_DBG)
+					&& (buf->len == 1))) {
+#endif		
+					kfree(buf);
+					return -EINVAL;
+				}
+			} else {
+				if ((buf->offs < 0) || (buf->offs + buf->len > 0xe00) || (buf->len > 1000)) {
+					kfree(buf);
+					return -EINVAL;
+				}
+			}			
+				
+			if (((unsigned)buf->flags) > 0x3f)
+				buf->flags = 0;
 
 			if (buf->command == CMD_READ) {
 				for (i = 0; i < buf->len; i++)
-					((u32 *) buf->data)[i] = sblive_readptr(wave_dev->card, buf->offs + i, 0);
+					((u32 *) buf->data)[i] = sblive_readptr(wave_dev->card, buf->offs + i, buf->flags);
 
 				if (copy_to_user((copr_buffer *) arg, buf, sizeof(copr_buffer))) {
 					kfree(buf);
@@ -956,7 +975,7 @@
 				}
 			} else {
 				for (i = 0; i < buf->len; i++)
-					sblive_writeptr(wave_dev->card, buf->offs + i, 0, ((u32 *) buf->data)[i]);
+					sblive_writeptr(wave_dev->card, buf->offs + i, buf->flags, ((u32 *) buf->data)[i]);
 			}
 
 			kfree (buf);
@@ -1244,8 +1263,9 @@
 		struct woinst *woinst = wave_dev->woinst;
 
 		spin_lock_irqsave(&woinst->lock, flags);
-
-		if (woinst->format.passthrough && card->pt.state != PT_STATE_INACTIVE) {
+		if(woinst->format.passthrough==2)
+			card->pt.state=PT_STATE_PLAYING;
+		if (woinst->format.passthrough && card->pt.state != PT_STATE_INACTIVE){
 			spin_lock(&card->pt.lock);
                         emu10k1_pt_stop(card);
 			spin_unlock(&card->pt.lock);
diff -Nru a/sound/oss/emu10k1/cardmi.c b/sound/oss/emu10k1/cardmi.c
--- a/sound/oss/emu10k1/cardmi.c	Sat Jul 19 12:54:25 2003
+++ b/sound/oss/emu10k1/cardmi.c	Sat Jul 19 12:54:25 2003
@@ -113,7 +113,7 @@
 	}
 
 	/* Disable RX interrupt */
-	emu10k1_irq_disable(card, INTE_MIDIRXENABLE);
+	emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDIRXENABLE : INTE_MIDIRXENABLE);
 
 	emu10k1_mpu_release(card);
 
@@ -189,7 +189,7 @@
 		card_mpuin->qhead = 0;
 		card_mpuin->qtail = 0;
 
-		emu10k1_irq_enable(card, INTE_MIDIRXENABLE);
+		emu10k1_irq_enable(card, card->is_audigy ? A_INTE_MIDIRXENABLE : INTE_MIDIRXENABLE);
 	}
 
 	return 0;
@@ -207,7 +207,7 @@
 
 	DPF(2, "emu10k1_mpuin_stop()\n");
 
-	emu10k1_irq_disable(card, INTE_MIDIRXENABLE);
+	emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDIRXENABLE : INTE_MIDIRXENABLE);
 
 	card_mpuin->status &= ~FLAGS_MIDM_STARTED;	/* clear */
 
@@ -246,7 +246,7 @@
 
 	DPF(2, "emu10k1_mpuin_reset()\n");
 
-	emu10k1_irq_disable(card, INTE_MIDIRXENABLE);
+	emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDIRXENABLE : INTE_MIDIRXENABLE);
 
 	while (card_mpuin->firstmidiq) {
 		midiq = card_mpuin->firstmidiq;
diff -Nru a/sound/oss/emu10k1/cardmo.c b/sound/oss/emu10k1/cardmo.c
--- a/sound/oss/emu10k1/cardmo.c	Sat Jul 19 12:54:23 2003
+++ b/sound/oss/emu10k1/cardmo.c	Sat Jul 19 12:54:23 2003
@@ -72,7 +72,7 @@
 
 	DPF(2, "emu10k1_mpuout_close()\n");
 
-	emu10k1_irq_disable(card, INTE_MIDITXENABLE);
+	emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
 
 	spin_lock_irqsave(&card_mpuout->lock, flags);
 
@@ -142,7 +142,7 @@
 
 	card_mpuout->intr = 0;
 
-	emu10k1_irq_enable(card, INTE_MIDITXENABLE);
+	emu10k1_irq_enable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
 
 	spin_unlock_irqrestore(&card_mpuout->lock, flags);
 
@@ -206,7 +206,7 @@
 
 	if ((card_mpuout->firstmidiq != NULL) || cByteSent) {
 		card_mpuout->intr = 0;
-		emu10k1_irq_enable(card, INTE_MIDITXENABLE);
+		emu10k1_irq_enable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
 	}
 
 	spin_unlock_irqrestore(&card_mpuout->lock, flags);
@@ -221,7 +221,7 @@
 	DPF(4, "emu10k1_mpuout_irqhandler\n");
 
 	card_mpuout->intr = 1;
-	emu10k1_irq_disable(card, INTE_MIDITXENABLE);
+	emu10k1_irq_disable(card, card->is_audigy ? A_INTE_MIDITXENABLE : INTE_MIDITXENABLE);
 
 	tasklet_hi_schedule(&card_mpuout->tasklet);
 
diff -Nru a/sound/oss/emu10k1/cardwo.c b/sound/oss/emu10k1/cardwo.c
--- a/sound/oss/emu10k1/cardwo.c	Sat Jul 19 12:54:27 2003
+++ b/sound/oss/emu10k1/cardwo.c	Sat Jul 19 12:54:27 2003
@@ -85,25 +85,36 @@
 		break;
 	}	
 	if (do_passthrough) {
-		i = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.intr_gpr_name);
-		j = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.enable_gpr_name);
 		/* currently only one waveout instance may use pass-through */
-		if (i < 0 || j < 0 || woinst->state != WAVE_STATE_CLOSED || 
+		if (woinst->state != WAVE_STATE_CLOSED || 
 		    card->pt.state != PT_STATE_INACTIVE ||
-		    (wave_fmt->samplingrate != 48000 && !is_ac3) ||
 		    (wave_fmt->samplingrate != 48000 && !is_ac3)) {
 			DPF(2, "unable to set pass-through mode\n");
-		} else {
-			wave_fmt->samplingrate = 48000;
-			wave_fmt->channels = 2;
-			wave_fmt->passthrough = 1;
-			card->pt.intr_gpr = i;
-			card->pt.enable_gpr = j;
-			card->pt.state = PT_STATE_INACTIVE;
-			card->pt.pos_gpr = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.pos_gpr_name);
-			DPD(2, "is_ac3 is %d\n", is_ac3);
-			card->pt.ac3data = is_ac3;
-	                wave_fmt->bitsperchannel = 16;
+		} else if (USE_PT_METHOD1) {
+			i = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.intr_gpr_name);
+			j = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.enable_gpr_name);
+			if (i < 0 || j < 0)
+				DPF(2, "unable to set pass-through mode\n");
+			else {
+				wave_fmt->samplingrate = 48000;
+				wave_fmt->channels = 2;
+				card->pt.pos_gpr = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name,
+									    card->pt.pos_gpr_name);
+				wave_fmt->passthrough = 1;
+				card->pt.intr_gpr = i;
+				card->pt.enable_gpr = j;
+				card->pt.state = PT_STATE_INACTIVE;
+			
+				DPD(2, "is_ac3 is %d\n", is_ac3);
+				card->pt.ac3data = is_ac3;
+				wave_fmt->bitsperchannel = 16;
+			}
+		}else{
+			DPF(2, "Using Passthrough Method 2\n");
+			card->pt.enable_gpr = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name,
+								       card->pt.enable_gpr_name);
+			wave_fmt->passthrough = 2;
+			wave_fmt->bitsperchannel = 16;
 		}
 	}
 
@@ -149,33 +160,37 @@
 	voice->endloop = voice->startloop + woinst->buffer.size / woinst->format.bytespervoicesample;
 	voice->start = voice->startloop;
 
-	if (voice->flags & VOICE_FLAGS_STEREO) {
-		voice->params[0].send_a = card->waveout.send_a[1];
-		voice->params[0].send_b = card->waveout.send_b[1];
-		voice->params[0].send_c = card->waveout.send_c[1];
-		voice->params[0].send_d = card->waveout.send_d[1];
-
-		if (woinst->device)
-			voice->params[0].send_routing = 0x7654;
-		else
-			voice->params[0].send_routing = card->waveout.send_routing[1];
-
-		voice->params[0].volume_target = 0xffff;
-		voice->params[0].initial_fc = 0xff;
-		voice->params[0].initial_attn = 0x00;
-		voice->params[0].byampl_env_sustain = 0x7f;
-		voice->params[0].byampl_env_decay = 0x7f;
-
-		voice->params[1].send_a = card->waveout.send_a[2];
-		voice->params[1].send_b = card->waveout.send_b[2];
-		voice->params[1].send_c = card->waveout.send_c[2];
-		voice->params[1].send_d = card->waveout.send_d[2];
-
-		if (woinst->device)
-			voice->params[1].send_routing = 0x7654;
-		else
-			voice->params[1].send_routing = card->waveout.send_routing[2];
+	
+	voice->params[0].volume_target = 0xffff;
+	voice->params[0].initial_fc = 0xff;
+	voice->params[0].initial_attn = 0x00;
+	voice->params[0].byampl_env_sustain = 0x7f;
+	voice->params[0].byampl_env_decay = 0x7f;
 
+	
+	if (voice->flags & VOICE_FLAGS_STEREO) {
+		if (woinst->format.passthrough == 2) {
+			voice->params[0].send_routing  = voice->params[1].send_routing  = card->waveout.send_routing[ROUTE_PT];
+			voice->params[0].send_routing2 = voice->params[1].send_routing2 = card->waveout.send_routing2[ROUTE_PT];
+			voice->params[0].send_dcba = 0xff;
+			voice->params[1].send_dcba = 0xff00;
+			voice->params[0].send_hgfe = voice->params[1].send_hgfe=0;
+		} else {
+			voice->params[0].send_dcba = card->waveout.send_dcba[SEND_LEFT];
+			voice->params[0].send_hgfe = card->waveout.send_hgfe[SEND_LEFT];
+			voice->params[1].send_dcba = card->waveout.send_dcba[SEND_RIGHT];
+			voice->params[1].send_hgfe = card->waveout.send_hgfe[SEND_RIGHT];
+
+			if (woinst->device) {
+				// /dev/dps1
+				voice->params[0].send_routing  = voice->params[1].send_routing  = card->waveout.send_routing[ROUTE_PCM1];
+				voice->params[0].send_routing2 = voice->params[1].send_routing2 = card->waveout.send_routing2[ROUTE_PCM1];
+			} else {
+				voice->params[0].send_routing  = voice->params[1].send_routing  = card->waveout.send_routing[ROUTE_PCM];
+				voice->params[0].send_routing2 = voice->params[1].send_routing2 = card->waveout.send_routing2[ROUTE_PCM];
+			}
+		}
+		
 		voice->params[1].volume_target = 0xffff;
 		voice->params[1].initial_fc = 0xff;
 		voice->params[1].initial_attn = 0x00;
@@ -183,30 +198,28 @@
 		voice->params[1].byampl_env_decay = 0x7f;
 	} else {
 		if (woinst->num_voices > 1) {
-			voice->params[0].send_a = 0xff;
-			voice->params[0].send_b = 0;
-			voice->params[0].send_c = 0;
-			voice->params[0].send_d = 0;
-
-			voice->params[0].send_routing =
-			 0xfff0 + card->mchannel_fx + voicenum;
+			// Multichannel pcm
+			voice->params[0].send_dcba=0xff;
+			voice->params[0].send_hgfe=0;
+			if (card->is_audigy) {
+				voice->params[0].send_routing = 0x3f3f3f00 + card->mchannel_fx + voicenum;
+				voice->params[0].send_routing2 = 0x3f3f3f3f;
+			} else {
+				voice->params[0].send_routing = 0xfff0 + card->mchannel_fx + voicenum;
+			}
+			
 		} else {
-			voice->params[0].send_a = card->waveout.send_a[0];
-			voice->params[0].send_b = card->waveout.send_b[0];
-			voice->params[0].send_c = card->waveout.send_c[0];
-			voice->params[0].send_d = card->waveout.send_d[0];
-
-			if (woinst->device)
-				voice->params[0].send_routing = 0x7654;
-			else
-				voice->params[0].send_routing = card->waveout.send_routing[0];
-		}	
-
-		voice->params[0].volume_target = 0xffff;
-		voice->params[0].initial_fc = 0xff;
-		voice->params[0].initial_attn = 0x00;
-		voice->params[0].byampl_env_sustain = 0x7f;
-		voice->params[0].byampl_env_decay = 0x7f;
+			voice->params[0].send_dcba = card->waveout.send_dcba[SEND_MONO];
+			voice->params[0].send_hgfe = card->waveout.send_hgfe[SEND_MONO];
+
+			if (woinst->device) {
+				voice->params[0].send_routing = card->waveout.send_routing[ROUTE_PCM1];
+				voice->params[0].send_routing2 = card->waveout.send_routing2[ROUTE_PCM1];
+			} else {
+				voice->params[0].send_routing = card->waveout.send_routing[ROUTE_PCM];
+				voice->params[0].send_routing2 = card->waveout.send_routing2[ROUTE_PCM];
+			}
+		}
 	}
 
 	DPD(2, "voice: startloop=%#x, endloop=%#x\n", voice->startloop, voice->endloop);
@@ -280,8 +293,15 @@
 {
 	struct emu10k1_card *card = wave_dev->card;
 	struct woinst *woinst = wave_dev->woinst;
+	struct pt_data *pt = &card->pt;
 
 	DPF(2, "emu10k1_waveout_start()\n");
+
+	if (woinst->format.passthrough == 2) {
+		emu10k1_pt_setup(wave_dev);
+		sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + pt->enable_gpr, 0, 1);
+		pt->state = PT_STATE_PLAYING;
+	}
 
 	/* Actual start */
 	emu10k1_voices_start(woinst->voice, woinst->num_voices, woinst->total_played);
diff -Nru a/sound/oss/emu10k1/efxmgr.c b/sound/oss/emu10k1/efxmgr.c
--- a/sound/oss/emu10k1/efxmgr.c	Sat Jul 19 12:54:22 2003
+++ b/sound/oss/emu10k1/efxmgr.c	Sat Jul 19 12:54:22 2003
@@ -80,15 +80,20 @@
 	if (addr < 0 || addr >= NUM_GPRS)
 		return;
 
-	if (flag)
-		val += sblive_readptr(card, GPR_BASE + addr, 0);
-
-	if (val > mgr->gpr[addr].max)
-		val = mgr->gpr[addr].max;
-	else if (val < mgr->gpr[addr].min)
-		val = mgr->gpr[addr].min;
-
-	sblive_writeptr(card, GPR_BASE + addr, 0, val);
+	//fixme: once patch manager is up, remember to fix this for the audigy
+	if (card->is_audigy) {
+		sblive_writeptr(card, A_GPR_BASE + addr, 0, val);
+	} else {
+		if (flag)
+			val += sblive_readptr(card, GPR_BASE + addr, 0);
+		if (val > mgr->gpr[addr].max)
+			val = mgr->gpr[addr].max;
+		else if (val < mgr->gpr[addr].min)
+			val = mgr->gpr[addr].min;
+		sblive_writeptr(card, GPR_BASE + addr, 0, val);
+	}
+	
+	
 }
 
 //TODO: make this configurable:
diff -Nru a/sound/oss/emu10k1/efxmgr.h b/sound/oss/emu10k1/efxmgr.h
--- a/sound/oss/emu10k1/efxmgr.h	Sat Jul 19 12:54:30 2003
+++ b/sound/oss/emu10k1/efxmgr.h	Sat Jul 19 12:54:30 2003
@@ -32,16 +32,30 @@
 #ifndef _EFXMGR_H
 #define _EFXMGR_H
 
-#define WRITE_EFX(a, b, c) sblive_writeptr((a), MICROCODEBASE + (b), 0, (c))
+struct emu_efx_info_t{
+	int opcode_shift;
+	int high_operand_shift;
+	int instruction_start;
+	int gpr_base;
+	int output_base;
+};
+
+
+#define WRITE_EFX(a, b, c) sblive_writeptr((a), emu_efx_info[card->is_audigy].instruction_start + (b), 0, (c))
 
 #define OP(op, z, w, x, y) \
-	do { WRITE_EFX(card, (pc) * 2, ((x) << 10) | (y)); \
-	WRITE_EFX(card, (pc) * 2 + 1, ((op) << 20) | ((z) << 10) | (w)); \
+	do { WRITE_EFX(card, (pc) * 2, ((x) << emu_efx_info[card->is_audigy].high_operand_shift) | (y)); \
+	WRITE_EFX(card, (pc) * 2 + 1, ((op) << emu_efx_info[card->is_audigy].opcode_shift ) | ((z) << emu_efx_info[card->is_audigy].high_operand_shift) | (w)); \
 	++pc; } while (0)
 
 #define NUM_INPUTS 0x20
 #define NUM_OUTPUTS 0x20
 #define NUM_GPRS 0x100
+
+#define A_NUM_INPUTS 0x60
+#define A_NUM_OUTPUTS 0x60  //fixme: this may or may not be true
+#define A_NUM_GPRS 0x200
+
 #define GPR_NAME_SIZE   32
 #define PATCH_NAME_SIZE 32
 
@@ -97,6 +111,9 @@
 
 #define GPR_BASE 0x100
 #define OUTPUT_BASE 0x20
+
+#define A_GPR_BASE 0x400
+#define A_OUTPUT_BASE 0x60
 
 #define MAX_PATCHES_PAGES 32
 
diff -Nru a/sound/oss/emu10k1/hwaccess.c b/sound/oss/emu10k1/hwaccess.c
--- a/sound/oss/emu10k1/hwaccess.c	Sat Jul 19 12:54:24 2003
+++ b/sound/oss/emu10k1/hwaccess.c	Sat Jul 19 12:54:24 2003
@@ -160,6 +160,24 @@
 	return;
 }
 
+void emu10k1_writefn0_2(struct emu10k1_card *card, u32 reg, u32 data, int size)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->lock, flags);
+
+	if (size == 32)
+		outl(data, card->iobase + (reg & 0x1F));
+	else if (size == 16)
+		outw(data, card->iobase + (reg & 0x1F));
+	else
+		outb(data, card->iobase + (reg & 0x1F));
+
+	spin_unlock_irqrestore(&card->lock, flags);
+
+	return;
+}
+
 u32 emu10k1_readfn0(struct emu10k1_card * card, u32 reg)
 {
 	u32 val;
@@ -200,12 +218,13 @@
 * write/read Emu10k1 pointer-offset register set, accessed through      *
 *  the PTR and DATA registers                                           *
 *************************************************************************/
+#define A_PTR_ADDRESS_MASK 0x0fff0000
 void sblive_writeptr(struct emu10k1_card *card, u32 reg, u32 channel, u32 data)
 {
 	u32 regptr;
 	unsigned long flags;
 
-	regptr = ((reg << 16) & PTR_ADDRESS_MASK) | (channel & PTR_CHANNELNUM_MASK);
+	regptr = ((reg << 16) & A_PTR_ADDRESS_MASK) | (channel & PTR_CHANNELNUM_MASK);
 
 	if (reg & 0xff000000) {
 		u32 mask;
@@ -242,7 +261,7 @@
 	spin_lock_irqsave(&card->lock, flags);
 	while ((reg = va_arg(args, u32)) != TAGLIST_END) {
 		u32 data = va_arg(args, u32);
-		u32 regptr = (((reg << 16) & PTR_ADDRESS_MASK)
+		u32 regptr = (((reg << 16) & A_PTR_ADDRESS_MASK)
 			      | (channel & PTR_CHANNELNUM_MASK));
 		outl(regptr, card->iobase + PTR);
 		if (reg & 0xff000000) {
@@ -267,7 +286,7 @@
 	u32 regptr, val;
 	unsigned long flags;
 
-	regptr = ((reg << 16) & PTR_ADDRESS_MASK) | (channel & PTR_CHANNELNUM_MASK);
+	regptr = ((reg << 16) & A_PTR_ADDRESS_MASK) | (channel & PTR_CHANNELNUM_MASK);
 
 	if (reg & 0xff000000) {
 		u32 mask;
@@ -389,7 +408,7 @@
 
 	outb(reg, card->iobase + AC97ADDRESS);
 	outw(value, card->iobase + AC97DATA);
-
+	outb( AC97_EXTENDED_ID, card->iobase + AC97ADDRESS); 
 	spin_unlock_irqrestore(&card->lock, flags);
 }
 
@@ -402,15 +421,23 @@
 	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&card->lock, flags);
+	if (card->is_audigy) {
+		if ((sblive_readptr(card, A_MUSTAT,0) & MUSTAT_ORDYN) == 0) {
+			sblive_writeptr(card, A_MUDATA, 0, data);
+			ret = 0;
+		} else
+			ret = -1;
+	} else {
+		spin_lock_irqsave(&card->lock, flags);
 
-	if ((inb(card->iobase + MUSTAT) & MUSTAT_ORDYN) == 0) {
-		outb(data, card->iobase + MUDATA);
-		ret = 0;
-	} else
-		ret = -1;
+		if ((inb(card->iobase + MUSTAT) & MUSTAT_ORDYN) == 0) {
+			outb(data, card->iobase + MUDATA);
+			ret = 0;
+		} else
+			ret = -1;
 
-	spin_unlock_irqrestore(&card->lock, flags);
+		spin_unlock_irqrestore(&card->lock, flags);
+	}
 
 	return ret;
 }
@@ -420,15 +447,23 @@
 	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&card->lock, flags);
+	if (card->is_audigy) {
+		if ((sblive_readptr(card, A_MUSTAT,0) & MUSTAT_IRDYN) == 0) {
+			*data = sblive_readptr(card, A_MUDATA,0);
+			ret = 0;
+		} else
+			ret = -1;
+	} else {
+		spin_lock_irqsave(&card->lock, flags);
 
-	if ((inb(card->iobase + MUSTAT) & MUSTAT_IRDYN) == 0) {
-		*data = inb(card->iobase + MUDATA);
-		ret = 0;
-	} else
-		ret = -1;
+		if ((inb(card->iobase + MUSTAT) & MUSTAT_IRDYN) == 0) {
+			*data = inb(card->iobase + MUDATA);
+			ret = 0;
+		} else
+			ret = -1;
 
-	spin_unlock_irqrestore(&card->lock, flags);
+		spin_unlock_irqrestore(&card->lock, flags);
+	}
 
 	return ret;
 }
@@ -439,37 +474,54 @@
 	unsigned long flags;
 
 	DPF(2, "emu10k1_mpu_reset()\n");
+	if (card->is_audigy) {
+		if (card->mpuacqcount == 0) {
+			sblive_writeptr(card, A_MUCMD, 0, MUCMD_RESET);
+			sblive_wcwait(card, 8);
+			sblive_writeptr(card, A_MUCMD, 0, MUCMD_RESET);
+			sblive_wcwait(card, 8);
+			sblive_writeptr(card, A_MUCMD, 0, MUCMD_ENTERUARTMODE);
+			sblive_wcwait(card, 8);
+			status = sblive_readptr(card, A_MUDATA, 0);
+			if (status == 0xfe)
+				return 0;
+			else
+				return -1;
+		}
 
-	if (card->mpuacqcount == 0) {
-		spin_lock_irqsave(&card->lock, flags);
-		outb(MUCMD_RESET, card->iobase + MUCMD);
-		spin_unlock_irqrestore(&card->lock, flags);
+		return 0;
+	} else {
+		if (card->mpuacqcount == 0) {
+			spin_lock_irqsave(&card->lock, flags);
+			outb(MUCMD_RESET, card->iobase + MUCMD);
+			spin_unlock_irqrestore(&card->lock, flags);
 
-		sblive_wcwait(card, 8);
+			sblive_wcwait(card, 8);
 
-		spin_lock_irqsave(&card->lock, flags);
-		outb(MUCMD_RESET, card->iobase + MUCMD);
-		spin_unlock_irqrestore(&card->lock, flags);
+			spin_lock_irqsave(&card->lock, flags);
+			outb(MUCMD_RESET, card->iobase + MUCMD);
+			spin_unlock_irqrestore(&card->lock, flags);
 
-		sblive_wcwait(card, 8);
+			sblive_wcwait(card, 8);
 
-		spin_lock_irqsave(&card->lock, flags);
-		outb(MUCMD_ENTERUARTMODE, card->iobase + MUCMD);
-		spin_unlock_irqrestore(&card->lock, flags);
+			spin_lock_irqsave(&card->lock, flags);
+			outb(MUCMD_ENTERUARTMODE, card->iobase + MUCMD);
+			spin_unlock_irqrestore(&card->lock, flags);
 
-		sblive_wcwait(card, 8);
+			sblive_wcwait(card, 8);
 
-		spin_lock_irqsave(&card->lock, flags);
-		status = inb(card->iobase + MUDATA);
-		spin_unlock_irqrestore(&card->lock, flags);
+			spin_lock_irqsave(&card->lock, flags);
+			status = inb(card->iobase + MUDATA);
+			spin_unlock_irqrestore(&card->lock, flags);
 
-		if (status == 0xfe)
-			return 0;
-		else
-			return -1;
-	}
+			if (status == 0xfe)
+				return 0;
+			else
+				return -1;
+		}
 
-	return 0;
+		return 0;
+	}
 }
 
 int emu10k1_mpu_acquire(struct emu10k1_card *card)
diff -Nru a/sound/oss/emu10k1/hwaccess.h b/sound/oss/emu10k1/hwaccess.h
--- a/sound/oss/emu10k1/hwaccess.h	Sat Jul 19 12:54:24 2003
+++ b/sound/oss/emu10k1/hwaccess.h	Sat Jul 19 12:54:24 2003
@@ -79,13 +79,21 @@
 
 struct emu10k1_waveout
 {
-	u16 send_routing[3];
-
-	u8 send_a[3];
-	u8 send_b[3];
-	u8 send_c[3];
-	u8 send_d[3];
+	u32 send_routing[3];
+	// audigy only:
+	u32 send_routing2[3];
+
+	u32 send_dcba[3];
+	// audigy only:
+	u32 send_hgfe[3];
 };
+#define ROUTE_PCM 0
+#define ROUTE_PT 1
+#define ROUTE_PCM1 2
+
+#define SEND_MONO 0
+#define SEND_LEFT 1
+#define SEND_RIGHT 2
 
 struct emu10k1_wavein
 {
@@ -129,7 +137,7 @@
 #define CMD_AC97_BOOST		_IOW('D', 20, struct mixer_private_ioctl)
 
 //up this number when breaking compatibility
-#define PRIVATE3_VERSION 1
+#define PRIVATE3_VERSION 2
 
 struct emu10k1_card 
 {
@@ -181,7 +189,7 @@
 	u32	    has_toslink;	       // TOSLink detection
 
 	u8 chiprev;                    /* Chip revision                */
-
+	u8 is_audigy;
 	u8 is_aps;
 
 	struct patch_manager mgr;
@@ -211,6 +219,7 @@
 /* Hardware Abstraction Layer access functions */
 
 void emu10k1_writefn0(struct emu10k1_card *, u32, u32);
+void emu10k1_writefn0_2(struct emu10k1_card *, u32, u32, int);
 u32 emu10k1_readfn0(struct emu10k1_card *, u32);
 
 void emu10k1_timer_set(struct emu10k1_card *, u16);
diff -Nru a/sound/oss/emu10k1/irqmgr.h b/sound/oss/emu10k1/irqmgr.h
--- a/sound/oss/emu10k1/irqmgr.h	Sat Jul 19 12:54:23 2003
+++ b/sound/oss/emu10k1/irqmgr.h	Sat Jul 19 12:54:23 2003
@@ -33,15 +33,15 @@
 #define _IRQ_H
 
 /* EMU Irq Types */
-#define IRQTYPE_PCIBUSERROR         IPR_PCIERROR
-#define IRQTYPE_MIXERBUTTON         (IPR_VOLINCR | IPR_VOLDECR | IPR_MUTE)
-#define IRQTYPE_VOICE               (IPR_CHANNELLOOP | IPR_CHANNELNUMBERMASK)
-#define IRQTYPE_RECORD              (IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL | IPR_MICBUFFULL | IPR_MICBUFHALFFULL | IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL)
-#define IRQTYPE_MPUOUT              IPR_MIDITRANSBUFEMPTY
-#define IRQTYPE_MPUIN               IPR_MIDIRECVBUFEMPTY
-#define IRQTYPE_TIMER               IPR_INTERVALTIMER
-#define IRQTYPE_SPDIF               (IPR_GPSPDIFSTATUSCHANGE | IPR_CDROMSTATUSCHANGE)
-#define IRQTYPE_DSP                 IPR_FXDSP
+#define IRQTYPE_PCIBUSERROR	IPR_PCIERROR
+#define IRQTYPE_MIXERBUTTON	(IPR_VOLINCR | IPR_VOLDECR | IPR_MUTE)
+#define IRQTYPE_VOICE		(IPR_CHANNELLOOP | IPR_CHANNELNUMBERMASK)
+#define IRQTYPE_RECORD		(IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL | IPR_MICBUFFULL | IPR_MICBUFHALFFULL | IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL)
+#define IRQTYPE_MPUOUT		(IPR_MIDITRANSBUFEMPTY | A_IPR_MIDITRANSBUFEMPTY2) 
+#define IRQTYPE_MPUIN		(IPR_MIDIRECVBUFEMPTY | A_IPR_MIDIRECVBUFEMPTY2)
+#define IRQTYPE_TIMER		IPR_INTERVALTIMER
+#define IRQTYPE_SPDIF		(IPR_GPSPDIFSTATUSCHANGE | IPR_CDROMSTATUSCHANGE)
+#define IRQTYPE_DSP		IPR_FXDSP
 
 void emu10k1_timer_irqhandler(struct emu10k1_card *);
 void emu10k1_dsp_irqhandler(struct emu10k1_card *);
diff -Nru a/sound/oss/emu10k1/main.c b/sound/oss/emu10k1/main.c
--- a/sound/oss/emu10k1/main.c	Sat Jul 19 12:54:29 2003
+++ b/sound/oss/emu10k1/main.c	Sat Jul 19 12:54:29 2003
@@ -78,10 +78,11 @@
  *          Cleaned up poll() functions (audio and midi). Don't start input.
  *	    Restrict DMA pages used to 512Mib range.
  *	    New AC97_BOOST mixer ioctl.
- *     0.19 Real fix for kernel with highmem support (cast dma_handle to u32).
+ *    0.19a Added Support for Audigy Cards
+ *	    Real fix for kernel with highmem support (cast dma_handle to u32).
  *	    Fix recording buffering parameters calculation.
  *	    Use unsigned long for variables in bit ops.
- *     0.20 Fixed recording startup
+ *    0.20a Fixed recording startup
  *	    Fixed timer rate setting (it's a 16-bit register)
  *********************************************************************/
 
@@ -114,7 +115,6 @@
 #define SNDCARD_EMU10K1 46
 #endif
  
-#define DRIVER_VERSION "0.20"
 
 /* the emu10k1 _seems_ to only supports 29 bit (512MiB) bit bus master */
 #define EMU10K1_DMA_MASK                0x1fffffff	/* DMA buffer mask for pci_alloc_consist */
@@ -126,20 +126,27 @@
 #ifndef PCI_DEVICE_ID_CREATIVE_EMU10K1
 #define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002
 #endif
+#ifndef PCI_DEVICE_ID_CREATIVE_AUDIGY
+#define PCI_DEVICE_ID_CREATIVE_AUDIGY 0x0004
+#endif
 
 #define EMU_APS_SUBID	0x40011102
  
 enum {
 	EMU10K1 = 0,
+	AUDIGY,
 };
 
 static char *card_names[] __devinitdata = {
 	"EMU10K1",
+	"Audigy",
 };
 
 static struct pci_device_id emu10k1_pci_tbl[] = {
 	{PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_EMU10K1,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, EMU10K1},
+	{PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_AUDIGY,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, AUDIGY},
 	{0,}
 };
 
@@ -161,6 +168,67 @@
 
 static int __devinit emu10k1_audio_init(struct emu10k1_card *card)
 {
+	/* Assign default playback voice parameters */
+	if (card->is_audigy)
+		card->mchannel_fx = 0;
+	else
+		card->mchannel_fx = 8;
+
+
+	if (card->is_audigy) {
+		/* mono voice */
+		card->waveout.send_dcba[SEND_MONO] = 0xffffffff;
+		card->waveout.send_hgfe[SEND_MONO] = 0x0000ffff;
+	
+		/* stereo voice */
+		/* left */
+		card->waveout.send_dcba[SEND_LEFT] = 0x00ff00ff;
+		card->waveout.send_hgfe[SEND_LEFT] = 0x00007f7f;	
+		/* right */
+		card->waveout.send_dcba[SEND_RIGHT] = 0xff00ff00;
+		card->waveout.send_hgfe[SEND_RIGHT] = 0x00007f7f;
+
+		card->waveout.send_routing[ROUTE_PCM] = 0x03020100; // Regular pcm
+		card->waveout.send_routing2[ROUTE_PCM] = 0x07060504;
+
+		card->waveout.send_routing[ROUTE_PT] = 0x3f3f3d3c; // Passthrough
+		card->waveout.send_routing2[ROUTE_PT] = 0x3f3f3f3f;
+		
+		card->waveout.send_routing[ROUTE_PCM1] = 0x03020100; // Spare
+		card->waveout.send_routing2[ROUTE_PCM1] = 0x07060404;
+		
+	} else {
+		/* mono voice */
+		card->waveout.send_dcba[SEND_MONO] = 0x0000ffff;
+	
+		/* stereo voice */
+		/* left */
+		card->waveout.send_dcba[SEND_LEFT] = 0x000000ff;
+		/* right */
+		card->waveout.send_dcba[SEND_RIGHT] = 0x0000ff00;
+
+		card->waveout.send_routing[ROUTE_PCM] = 0x3210; // pcm
+		card->waveout.send_routing[ROUTE_PT] = 0x3210; // passthrough
+		card->waveout.send_routing[ROUTE_PCM1] = 0x7654; // /dev/dsp1
+	}
+
+	/* Assign default recording parameters */
+	/* FIXME */
+	if (card->is_aps)
+		card->wavein.recsrc = WAVERECORD_FX;
+	else
+		card->wavein.recsrc = WAVERECORD_AC97;
+
+	card->wavein.fxwc = 0x0003;
+	return 0;
+}
+
+static void emu10k1_audio_cleanup(struct emu10k1_card *card)
+{
+}
+
+static int __devinit emu10k1_register_devices(struct emu10k1_card *card)
+{
 	card->audio_dev = register_sound_dsp(&emu10k1_audio_fops, -1);
 	if (card->audio_dev < 0) {
 		printk(KERN_ERR "emu10k1: cannot register first audio device!\n");
@@ -173,56 +241,167 @@
 		goto err_dev1;
 	}
 
-	/* Assign default playback voice parameters */
-	card->mchannel_fx = 8;
-	/* mono voice */
-	card->waveout.send_a[0] = 0xff;
-	card->waveout.send_b[0] = 0xff;
-	card->waveout.send_c[0] = 0x00;
-	card->waveout.send_d[0] = 0x00;
-	card->waveout.send_routing[0] = 0x3210;
-
-	/* stereo voice */
-	/* left */
-	card->waveout.send_a[1] = 0xff;
-	card->waveout.send_b[1] = 0x00;
-	card->waveout.send_c[1] = 0x00;
-	card->waveout.send_d[1] = 0x00;
-	card->waveout.send_routing[1] = 0x3210;
-
-	/* right */
-	card->waveout.send_a[2] = 0x00;
-	card->waveout.send_b[2] = 0xff;
-	card->waveout.send_c[2] = 0x00;
-	card->waveout.send_d[2] = 0x00;
-	card->waveout.send_routing[2] = 0x3210;
+	card->ac97->dev_mixer = register_sound_mixer(&emu10k1_mixer_fops, -1);
+	if (card->ac97->dev_mixer < 0) {
+		printk(KERN_ERR "emu10k1: cannot register mixer device\n");
+		goto err_mixer;
+        }
 
-	/* Assign default recording parameters */
-	/* FIXME */
-	if (card->is_aps)
-		card->wavein.recsrc = WAVERECORD_FX;
-	else
-		card->wavein.recsrc = WAVERECORD_AC97;
+	card->midi_dev = register_sound_midi(&emu10k1_midi_fops, -1);
+	if (card->midi_dev < 0) {
+                printk(KERN_ERR "emu10k1: cannot register midi device!\n");
+		goto err_midi;
+        }
 
-	card->wavein.fxwc = 0x0003;
+#ifdef EMU10K1_SEQUENCER
+	card->seq_dev = sound_alloc_mididev();
+	if (card->seq_dev == -1)
+		printk(KERN_WARNING "emu10k1: unable to register sequencer device!");
+	else {
+		std_midi_synth.midi_dev = card->seq_dev;
+		midi_devs[card->seq_dev] = 
+			(struct midi_operations *)
+			kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
+
+		if (midi_devs[card->seq_dev] == NULL) {
+			printk(KERN_ERR "emu10k1: unable to allocate memory!");
+			sound_unload_mididev(card->seq_dev);
+			card->seq_dev = -1;
+			/* return without error */
+		} else {
+			memcpy((char *)midi_devs[card->seq_dev], 
+				(char *)&emu10k1_midi_operations, 
+				sizeof(struct midi_operations));
+			midi_devs[card->seq_dev]->devc = card;
+			sequencer_init();
+			card->seq_mididev = NULL;
+		}
+	}
+#endif
 	return 0;
 
+err_midi:
+	unregister_sound_mixer(card->ac97->dev_mixer);
+err_mixer:
+	unregister_sound_dsp(card->audio_dev);
 err_dev1:
 	unregister_sound_dsp(card->audio_dev);
 err_dev:
 	return -ENODEV;
 }
 
-static void __devinit emu10k1_audio_cleanup(struct emu10k1_card *card)
+static void emu10k1_unregister_devices(struct emu10k1_card *card)
 {
+#ifdef EMU10K1_SEQUENCER
+	if (card->seq_dev > -1) {
+		kfree(midi_devs[card->seq_dev]);
+		midi_devs[card->seq_dev] = NULL;
+		sound_unload_mididev(card->seq_dev);
+		card->seq_dev = -1;
+	}
+#endif
+
+	unregister_sound_midi(card->midi_dev);
+	unregister_sound_mixer(card->ac97->dev_mixer);
 	unregister_sound_dsp(card->audio_dev1);
 	unregister_sound_dsp(card->audio_dev);
 }
 
-static int __devinit emu10k1_mixer_init(struct emu10k1_card *card)
+int emu10k1_info_proc (char *page, char **start, off_t off,
+		    int count, int *eof, void *data)
+{
+	struct emu10k1_card *card = data;
+	int len = 0;
+	
+	if (card == NULL)
+		return -ENODEV;
+
+	len += sprintf (page + len, "Driver Version : %s\n", DRIVER_VERSION);
+	len += sprintf (page + len, "Card type      : %s\n", card->is_aps ? "Aps" : (card->is_audigy ? "Audigy" : "Emu10k1"));
+	len += sprintf (page + len, "Revision       : %d\n", card->chiprev);
+	len += sprintf (page + len, "Model          : %#06x\n", card->model);
+	len += sprintf (page + len, "IO             : %#06lx-%#06lx\n", card->iobase, card->iobase + card->length - 1);
+	len += sprintf (page + len, "IRQ            : %d\n\n", card->irq);
+	
+	len += sprintf (page + len, "Registered /dev Entries:\n");
+	len += sprintf (page + len, "/dev/dsp%d\n", card->audio_dev / 16);
+	len += sprintf (page + len, "/dev/dsp%d\n", card->audio_dev1 / 16);
+	len += sprintf (page + len, "/dev/mixer%d\n", card->ac97->dev_mixer / 16);
+	len += sprintf (page + len, "/dev/midi%d\n", card->midi_dev / 16);
+
+#ifdef EMU10K1_SEQUENCER
+	len += sprintf (page + len, "/dev/sequencer\n");
+#endif
+
+	return len;
+}
+
+static int __devinit emu10k1_proc_init(struct emu10k1_card *card)
+{
+	char s[48];
+
+	if (!proc_mkdir ("driver/emu10k1", 0)) {
+		printk(KERN_ERR "emu10k1: unable to create proc directory driver/emu10k1\n");
+		goto err_out;
+	}
+
+	sprintf(s, "driver/emu10k1/%s", card->pci_dev->slot_name);
+	if (!proc_mkdir (s, 0)) {
+		printk(KERN_ERR "emu10k1: unable to create proc directory %s\n", s);
+		goto err_emu10k1_proc;
+	}
+
+	sprintf(s, "driver/emu10k1/%s/info", card->pci_dev->slot_name);
+	if (!create_proc_read_entry (s, 0, 0, emu10k1_info_proc, card)) {
+		printk(KERN_ERR "emu10k1: unable to create proc entry %s\n", s);
+		goto err_dev_proc;
+	}
+
+	if (!card->is_aps) {
+		sprintf(s, "driver/emu10k1/%s/ac97", card->pci_dev->slot_name);
+		if (!create_proc_read_entry (s, 0, 0, ac97_read_proc, card->ac97)) {
+			printk(KERN_ERR "emu10k1: unable to create proc entry %s\n", s);
+			goto err_proc_ac97;
+		}
+	}
+
+	return 0;
+
+err_proc_ac97:
+	sprintf(s, "driver/emu10k1/%s/info", card->pci_dev->slot_name);
+	remove_proc_entry(s, NULL);
+
+err_dev_proc:
+	sprintf(s, "driver/emu10k1/%s", card->pci_dev->slot_name);
+	remove_proc_entry(s, NULL);
+
+err_emu10k1_proc:
+	remove_proc_entry("driver/emu10k1", NULL);
+
+err_out:
+	return -EIO;
+}
+
+static void emu10k1_proc_cleanup(struct emu10k1_card *card)
 {
-	char s[32];
+	char s[48];
 
+	if (!card->is_aps) {
+		sprintf(s, "driver/emu10k1/%s/ac97", card->pci_dev->slot_name);
+		remove_proc_entry(s, NULL);
+	}
+
+	sprintf(s, "driver/emu10k1/%s/info", card->pci_dev->slot_name);
+	remove_proc_entry(s, NULL);
+
+	sprintf(s, "driver/emu10k1/%s", card->pci_dev->slot_name);
+	remove_proc_entry(s, NULL);
+		
+	remove_proc_entry("driver/emu10k1", NULL);
+}
+
+static int __devinit emu10k1_mixer_init(struct emu10k1_card *card)
+{
 	struct ac97_codec *codec  = ac97_alloc_codec();
 	
 	if(codec == NULL)
@@ -231,15 +410,6 @@
 		return -EIO;
 	}
 	card->ac97 = codec;
-	
-#warning "Initialisation order race. Must register after usable"
-
-	card->ac97->dev_mixer = register_sound_mixer(&emu10k1_mixer_fops, -1);
-	if (card->ac97->dev_mixer < 0) {
-		printk(KERN_ERR "emu10k1: cannot register mixer device\n");
-		goto err_codec;
-        }
-
 	card->ac97->private_data = card;
 
 	if (!card->is_aps) {
@@ -261,23 +431,6 @@
 		// Force 5bit:		    
 		//card->ac97->bit_resolution=5;
 
-		if (!proc_mkdir ("driver/emu10k1", 0)) {
-			printk(KERN_ERR "emu10k1: unable to create proc directory driver/emu10k1\n");
-			goto err_out;
-		}
-
-		sprintf(s, "driver/emu10k1/%s", card->pci_dev->slot_name);
-		if (!proc_mkdir (s, 0)) {
-			printk(KERN_ERR "emu10k1: unable to create proc directory %s\n", s);
-			goto err_emu10k1_proc;
-		}
-	
-		sprintf(s, "driver/emu10k1/%s/ac97", card->pci_dev->slot_name);
-		if (!create_proc_read_entry (s, 0, 0, ac97_read_proc, card->ac97)) {
-			printk(KERN_ERR "emu10k1: unable to create proc entry %s\n", s);
-			goto err_ac97_proc;
-		}
-
 		/* these will store the original values and never be modified */
 		card->ac97_supported_mixers = card->ac97->supported_mixers;
 		card->ac97_stereo_mixers = card->ac97->stereo_mixers;
@@ -285,34 +438,13 @@
 
 	return 0;
 
- err_ac97_proc:
-	sprintf(s, "driver/emu10k1/%s", card->pci_dev->slot_name);
-	remove_proc_entry(s, NULL);
-
- err_emu10k1_proc:
-	remove_proc_entry("driver/emu10k1", NULL);
  err_out:
-	unregister_sound_mixer (card->ac97->dev_mixer);
- err_codec:
  	ac97_release_codec(card->ac97);
 	return -EIO;
 }
 
-static void __devinit emu10k1_mixer_cleanup(struct emu10k1_card *card)
+static void emu10k1_mixer_cleanup(struct emu10k1_card *card)
 {
-	char s[32];
-
-	if (!card->is_aps) {
-		sprintf(s, "driver/emu10k1/%s/ac97", card->pci_dev->slot_name);
-		remove_proc_entry(s, NULL);
-
-		sprintf(s, "driver/emu10k1/%s", card->pci_dev->slot_name);
-		remove_proc_entry(s, NULL);
-
-		remove_proc_entry("driver/emu10k1", NULL);
-	}
-
-	unregister_sound_mixer (card->ac97->dev_mixer);
 	ac97_release_codec(card->ac97);
 }
 
@@ -320,13 +452,6 @@
 {
 	int ret;
 
-	card->midi_dev = register_sound_midi(&emu10k1_midi_fops, -1);
-	if (card->midi_dev < 0) {
-                printk(KERN_ERR "emu10k1: cannot register midi device!\n");
-		return -ENODEV;
-        }
-
-
 	card->mpuout = kmalloc(sizeof(struct emu10k1_mpuout), GFP_KERNEL);
 	if (card->mpuout == NULL) {
 		printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_mpuout: out of memory\n");
@@ -366,31 +491,6 @@
 		goto err_out3;
 	}
 
-#ifdef EMU10K1_SEQUENCER
-	card->seq_dev = sound_alloc_mididev();
-	if (card->seq_dev == -1)
-			printk(KERN_WARNING "emu10k1: unable to register sequencer device!");
-	else {
-			std_midi_synth.midi_dev = card->seq_dev;
-			midi_devs[card->seq_dev] = 
-					(struct midi_operations *)
-					kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
-			
-			if (midi_devs[card->seq_dev] == NULL) {
-				printk(KERN_ERR "emu10k1: unable to allocate memory!");
-				sound_unload_mididev(card->seq_dev);
-				card->seq_dev = -1;
-				return 0;
-			} else {
-				memcpy((char *)midi_devs[card->seq_dev], 
-					(char *)&emu10k1_midi_operations, 
-					sizeof(struct midi_operations));
-				midi_devs[card->seq_dev]->devc = card;
-				sequencer_init();
-			}
-	}
-	card->seq_mididev = 0;
-#endif
 	return 0;
 
 err_out3:
@@ -398,28 +498,16 @@
 err_out2:
 	kfree(card->mpuout);
 err_out1:
-	unregister_sound_midi(card->midi_dev);
 	return ret;
 }
 
-static void __devinit emu10k1_midi_cleanup(struct emu10k1_card *card)
+static void emu10k1_midi_cleanup(struct emu10k1_card *card)
 {
 	tasklet_kill(&card->mpuout->tasklet);
 	kfree(card->mpuout);
 
 	tasklet_kill(&card->mpuin->tasklet);
 	kfree(card->mpuin);
-
-#ifdef EMU10K1_SEQUENCER
-	if (card->seq_dev > -1) {
-		kfree(midi_devs[card->seq_dev]);
-		midi_devs[card->seq_dev] = NULL;
-		sound_unload_mididev(card->seq_dev);
-		card->seq_dev = -1;
-	}
-#endif
-
-	unregister_sound_midi(card->midi_dev);
 }
 
 static void __devinit voice_init(struct emu10k1_card *card)
@@ -450,7 +538,7 @@
 	card->emupagetable[1] = MAXPAGES - 1;
 }
 
-static void __devinit fx_cleanup(struct patch_manager *mgr)
+static void fx_cleanup(struct patch_manager *mgr)
 {
 	int i;
 	for(i = 0; i < mgr->current_pages; i++)
@@ -465,24 +553,25 @@
 	s32 left, right;
 	int i;
 	u32 pc = 0;
-	u32 patch_n;
+	u32 patch_n=0;
+	struct emu_efx_info_t emu_efx_info[2]=
+		{{ 20, 10, 0x400, 0x100, 0x20 },
+		 { 24, 12, 0x600, 0x400, 0x60 },
+		}; 
+			
 
 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
 		mgr->ctrl_gpr[i][0] = -1;
 		mgr->ctrl_gpr[i][1] = -1;
 	}
 
-	for (i = 0; i < 512; i++)
-		OP(6, 0x40, 0x40, 0x40, 0x40);
-
-	for (i = 0; i < 256; i++)
-		sblive_writeptr_tag(card, 0,
-				    FXGPREGBASE + i, 0,
-				    TANKMEMADDRREGBASE + i, 0,
-				    TAGLIST_END);
 
-	/* !! The number bellow must equal the number of patches, currently 11 !! */
-	mgr->current_pages = (11 + PATCHES_PER_PAGE - 1) / PATCHES_PER_PAGE;
+	if (card->is_audigy)
+		mgr->current_pages = (2 + PATCHES_PER_PAGE - 1) / PATCHES_PER_PAGE;
+	else
+		/* !! The number below must equal the number of patches, currently 11 !! */
+		mgr->current_pages = (11 + PATCHES_PER_PAGE - 1) / PATCHES_PER_PAGE;
+	
 	for (i = 0; i < mgr->current_pages; i++) {
 		mgr->patch[i] = (void *)__get_free_page(GFP_KERNEL);
 		if (mgr->patch[i] == NULL) {
@@ -493,215 +582,298 @@
 		memset(mgr->patch[i], 0, PAGE_SIZE);
 	}
 
-	pc = 0;
-	patch_n = 0;
-	//first free GPR = 0x11b
-
-	/* FX volume correction and Volume control*/
-	INPUT_PATCH_START(patch, "Pcm L vol", 0x0, 0);
-	GET_OUTPUT_GPR(patch, 0x100, 0x0);
-	GET_CONTROL_GPR(patch, 0x106, "Vol", 0, 0x7fffffff);
-	GET_DYNAMIC_GPR(patch, 0x112);
-
-	OP(4, 0x112, 0x40, PCM_IN_L, 0x44); //*4
-	OP(0, 0x100, 0x040, 0x112, 0x106);  //*vol
-	INPUT_PATCH_END(patch);
-
-
-	INPUT_PATCH_START(patch, "Pcm R vol", 0x1, 0);
-	GET_OUTPUT_GPR(patch, 0x101, 0x1);
-	GET_CONTROL_GPR(patch, 0x107, "Vol", 0, 0x7fffffff);
-	GET_DYNAMIC_GPR(patch, 0x112);
-
-	OP(4, 0x112, 0x40, PCM_IN_R, 0x44); 
-	OP(0, 0x101, 0x040, 0x112, 0x107);
-
-	INPUT_PATCH_END(patch);
-
-
-	// CD-Digital In Volume control
-	INPUT_PATCH_START(patch, "CD-Digital Vol L", 0x12, 0);
-	GET_OUTPUT_GPR(patch, 0x10c, 0x12);
-	GET_CONTROL_GPR(patch, 0x10d, "Vol", 0, 0x7fffffff);
-
-	OP(0, 0x10c, 0x040, SPDIF_CD_L, 0x10d);
-	INPUT_PATCH_END(patch);
-
-	INPUT_PATCH_START(patch, "CD-Digital Vol R", 0x13, 0);
-	GET_OUTPUT_GPR(patch, 0x10e, 0x13);
-	GET_CONTROL_GPR(patch, 0x10f, "Vol", 0, 0x7fffffff);
-
-	OP(0, 0x10e, 0x040, SPDIF_CD_R, 0x10f);
-	INPUT_PATCH_END(patch);
-
-	//Volume Correction for Multi-channel Inputs
-	INPUT_PATCH_START(patch, "Multi-Channel Gain", 0x08, 0);
-	patch->input=patch->output=0x3F00;
-
-	GET_OUTPUT_GPR(patch, 0x113, MULTI_FRONT_L);
-	GET_OUTPUT_GPR(patch, 0x114, MULTI_FRONT_R);
-	GET_OUTPUT_GPR(patch, 0x115, MULTI_REAR_L);
-	GET_OUTPUT_GPR(patch, 0x116, MULTI_REAR_R);
-	GET_OUTPUT_GPR(patch, 0x117, MULTI_CENTER);
-	GET_OUTPUT_GPR(patch, 0x118, MULTI_LFE);
-
-	OP(4, 0x113, 0x40, MULTI_FRONT_L, 0x44);
-	OP(4, 0x114, 0x40, MULTI_FRONT_R, 0x44);
-	OP(4, 0x115, 0x40, MULTI_REAR_L, 0x44);
-	OP(4, 0x116, 0x40, MULTI_REAR_R, 0x44);
-	OP(4, 0x117, 0x40, MULTI_CENTER, 0x44);
-	OP(4, 0x118, 0x40, MULTI_LFE, 0x44);
-	
-	INPUT_PATCH_END(patch);
-
-
-	//Routing patch start
-	ROUTING_PATCH_START(rpatch, "Routing");
-	GET_INPUT_GPR(rpatch, 0x100, 0x0);
-	GET_INPUT_GPR(rpatch, 0x101, 0x1);
-	GET_INPUT_GPR(rpatch, 0x10c, 0x12);
-	GET_INPUT_GPR(rpatch, 0x10e, 0x13);
-	GET_INPUT_GPR(rpatch, 0x113, MULTI_FRONT_L);
-	GET_INPUT_GPR(rpatch, 0x114, MULTI_FRONT_R);
-	GET_INPUT_GPR(rpatch, 0x115, MULTI_REAR_L);
-	GET_INPUT_GPR(rpatch, 0x116, MULTI_REAR_R);
-	GET_INPUT_GPR(rpatch, 0x117, MULTI_CENTER);
-	GET_INPUT_GPR(rpatch, 0x118, MULTI_LFE);
-
-	GET_DYNAMIC_GPR(rpatch, 0x102);
-	GET_DYNAMIC_GPR(rpatch, 0x103);
-
-	GET_OUTPUT_GPR(rpatch, 0x104, 0x8);
-	GET_OUTPUT_GPR(rpatch, 0x105, 0x9);
-	GET_OUTPUT_GPR(rpatch, 0x10a, 0x2);
-	GET_OUTPUT_GPR(rpatch, 0x10b, 0x3);
-
-
-	/* input buffer */
-	OP(6, 0x102, AC97_IN_L, 0x40, 0x40);
-	OP(6, 0x103, AC97_IN_R, 0x40, 0x40);
-
-
-	/* Digital In + PCM + MULTI_FRONT-> AC97 out (front speakers)*/
-	OP(6, AC97_FRONT_L, 0x100, 0x10c, 0x113);
-
-	CONNECT(MULTI_FRONT_L, AC97_FRONT_L);
-	CONNECT(PCM_IN_L, AC97_FRONT_L);
-	CONNECT(SPDIF_CD_L, AC97_FRONT_L);
-
-	OP(6, AC97_FRONT_R, 0x101, 0x10e, 0x114);
-
-	CONNECT(MULTI_FRONT_R, AC97_FRONT_R);
-	CONNECT(PCM_IN_R, AC97_FRONT_R);
-	CONNECT(SPDIF_CD_R, AC97_FRONT_R);
-
-	/* Digital In + PCM + AC97 In + PCM1 + MULTI_REAR --> Rear Channel */ 
-	OP(6, 0x104, PCM1_IN_L, 0x100, 0x115);
-	OP(6, 0x104, 0x104, 0x10c, 0x102);
-
-	CONNECT(MULTI_REAR_L, ANALOG_REAR_L);
-	CONNECT(AC97_IN_L, ANALOG_REAR_L);
-	CONNECT(PCM_IN_L, ANALOG_REAR_L);
-	CONNECT(SPDIF_CD_L, ANALOG_REAR_L);
-	CONNECT(PCM1_IN_L, ANALOG_REAR_L);
-
-	OP(6, 0x105, PCM1_IN_R, 0x101, 0x116);
-	OP(6, 0x105, 0x105, 0x10e, 0x103);
-
-	CONNECT(MULTI_REAR_R, ANALOG_REAR_R);
-	CONNECT(AC97_IN_R, ANALOG_REAR_R);
-	CONNECT(PCM_IN_R, ANALOG_REAR_R);
-	CONNECT(SPDIF_CD_R, ANALOG_REAR_R);
-	CONNECT(PCM1_IN_R, ANALOG_REAR_R);
-
-	/* Digital In + PCM + AC97 In + MULTI_FRONT --> Digital out */
-	OP(6, 0x10a, 0x100, 0x102, 0x10c);
-	OP(6, 0x10a, 0x10a, 0x113, 0x40);
-
-	CONNECT(MULTI_FRONT_L, DIGITAL_OUT_L);
-	CONNECT(PCM_IN_L, DIGITAL_OUT_L);
-	CONNECT(AC97_IN_L, DIGITAL_OUT_L);
-	CONNECT(SPDIF_CD_L, DIGITAL_OUT_L);
-
-	OP(6, 0x10b, 0x101, 0x103, 0x10e);
-	OP(6, 0x10b, 0x10b, 0x114, 0x40);
-
-	CONNECT(MULTI_FRONT_R, DIGITAL_OUT_R);
-	CONNECT(PCM_IN_R, DIGITAL_OUT_R);
-	CONNECT(AC97_IN_R, DIGITAL_OUT_R);
-	CONNECT(SPDIF_CD_R, DIGITAL_OUT_R);
-
-	/* AC97 In --> ADC Recording Buffer */
-	OP(6, ADC_REC_L, 0x102, 0x40, 0x40);
-
-	CONNECT(AC97_IN_L, ADC_REC_L);
-
-	OP(6, ADC_REC_R, 0x103, 0x40, 0x40);
-
-	CONNECT(AC97_IN_R, ADC_REC_R);
+	if (card->is_audigy) {
+		for (i = 0; i < 1024; i++)
+			OP(0xf, 0x0c0, 0x0c0, 0x0cf, 0x0c0);
+
+		for (i = 0; i < 512 ; i++)
+			sblive_writeptr(card, A_GPR_BASE+i,0,0);
+
+		pc=0;
+
+		//Pcm input volume
+		OP(0, 0x402, 0x0c0, 0x406, 0x000);
+		OP(0, 0x403, 0x0c0, 0x407, 0x001);
+
+		//CD-Digital input Volume
+		OP(0, 0x404, 0x0c0, 0x40d, 0x42);
+		OP(0, 0x405, 0x0c0, 0x40f, 0x43);
+
+		// CD + PCM 
+		OP(6, 0x400, 0x0c0, 0x402, 0x404);
+		OP(6, 0x401, 0x0c0, 0x403, 0x405);
+		
+		// Front Output + Master Volume
+		OP(0, 0x68, 0x0c0, 0x408, 0x400);
+		OP(0, 0x69, 0x0c0, 0x409, 0x401);
+
+		// Add-in analog inputs for other speakers
+		OP(6, 0x400, 0x40, 0x400, 0xc0);
+		OP(6, 0x401, 0x41, 0x401, 0xc0);
+
+		// Digital Front + Master Volume
+		OP(0, 0x60, 0x0c0, 0x408, 0x400);
+		OP(0, 0x61, 0x0c0, 0x409, 0x401);
+
+		// Rear Output + Rear Volume
+		OP(0, 0x06e, 0x0c0, 0x419, 0x400);
+		OP(0, 0x06f, 0x0c0, 0x41a, 0x401);		
+
+		// Digital Rear Output + Rear Volume
+		OP(0, 0x066, 0x0c0, 0x419, 0x400);
+		OP(0, 0x067, 0x0c0, 0x41a, 0x401);		
+
+		// Audigy Drive, Headphone out
+		OP(6, 0x64, 0x0c0, 0x0c0, 0x400);
+		OP(6, 0x65, 0x0c0, 0x0c0, 0x401);
+
+		// ac97 Recording
+		OP(6, 0x76, 0x0c0, 0x0c0, 0x40);
+		OP(6, 0x77, 0x0c0, 0x0c0, 0x41);
+		
+		// Center = sub = Left/2 + Right/2
+		OP(0xe, 0x400, 0x401, 0xcd, 0x400);
+
+		// center/sub  Volume (master)
+		OP(0, 0x06a, 0x0c0, 0x408, 0x400);
+		OP(0, 0x06b, 0x0c0, 0x409, 0x400);
+
+		// Digital center/sub  Volume (master)
+		OP(0, 0x062, 0x0c0, 0x408, 0x400);
+		OP(0, 0x063, 0x0c0, 0x409, 0x400);
+
+		ROUTING_PATCH_START(rpatch, "Routing");
+		ROUTING_PATCH_END(rpatch);
+
+		/* delimiter patch */
+		patch = PATCH(mgr, patch_n);
+		patch->code_size = 0;
 
+	
+		sblive_writeptr(card, 0x53, 0, 0);
+	} else {
+		for (i = 0; i < 512 ; i++)
+			OP(6, 0x40, 0x40, 0x40, 0x40);
+
+		for (i = 0; i < 256; i++)
+			sblive_writeptr_tag(card, 0,
+					    FXGPREGBASE + i, 0,
+					    TANKMEMADDRREGBASE + i, 0,
+					    TAGLIST_END);
 
-	/* fx12:Analog-Center */
-	OP(6, ANALOG_CENTER, 0x117, 0x40, 0x40);
-	CONNECT(MULTI_CENTER, ANALOG_CENTER);
+		
+		pc = 0;
 
-	/* fx11:Analog-LFE */
-	OP(6, ANALOG_LFE, 0x118, 0x40, 0x40);
-	CONNECT(MULTI_LFE, ANALOG_LFE);
+		//first free GPR = 0x11b
+	
+		
+		/* FX volume correction and Volume control*/
+		INPUT_PATCH_START(patch, "Pcm L vol", 0x0, 0);
+		GET_OUTPUT_GPR(patch, 0x100, 0x0);
+		GET_CONTROL_GPR(patch, 0x106, "Vol", 0, 0x7fffffff);
+		GET_DYNAMIC_GPR(patch, 0x112);
+
+		OP(4, 0x112, 0x40, PCM_IN_L, 0x44); //*4	
+		OP(0, 0x100, 0x040, 0x112, 0x106);  //*vol	
+		INPUT_PATCH_END(patch);
+
+
+		INPUT_PATCH_START(patch, "Pcm R vol", 0x1, 0);
+		GET_OUTPUT_GPR(patch, 0x101, 0x1);
+		GET_CONTROL_GPR(patch, 0x107, "Vol", 0, 0x7fffffff);
+		GET_DYNAMIC_GPR(patch, 0x112);
+
+		OP(4, 0x112, 0x40, PCM_IN_R, 0x44); 
+		OP(0, 0x101, 0x040, 0x112, 0x107);
+
+		INPUT_PATCH_END(patch);
+
+
+		// CD-Digital In Volume control	
+		INPUT_PATCH_START(patch, "CD-Digital Vol L", 0x12, 0);
+		GET_OUTPUT_GPR(patch, 0x10c, 0x12);
+		GET_CONTROL_GPR(patch, 0x10d, "Vol", 0, 0x7fffffff);
+
+		OP(0, 0x10c, 0x040, SPDIF_CD_L, 0x10d);
+		INPUT_PATCH_END(patch);
+
+		INPUT_PATCH_START(patch, "CD-Digital Vol R", 0x13, 0);
+		GET_OUTPUT_GPR(patch, 0x10e, 0x13);
+		GET_CONTROL_GPR(patch, 0x10f, "Vol", 0, 0x7fffffff);
+
+		OP(0, 0x10e, 0x040, SPDIF_CD_R, 0x10f);
+		INPUT_PATCH_END(patch);
+
+		//Volume Correction for Multi-channel Inputs	
+		INPUT_PATCH_START(patch, "Multi-Channel Gain", 0x08, 0);
+		patch->input=patch->output=0x3F00;
+
+		GET_OUTPUT_GPR(patch, 0x113, MULTI_FRONT_L);
+		GET_OUTPUT_GPR(patch, 0x114, MULTI_FRONT_R);
+		GET_OUTPUT_GPR(patch, 0x115, MULTI_REAR_L);
+		GET_OUTPUT_GPR(patch, 0x116, MULTI_REAR_R);
+		GET_OUTPUT_GPR(patch, 0x117, MULTI_CENTER);
+		GET_OUTPUT_GPR(patch, 0x118, MULTI_LFE);
+
+		OP(4, 0x113, 0x40, MULTI_FRONT_L, 0x44);
+		OP(4, 0x114, 0x40, MULTI_FRONT_R, 0x44);
+		OP(4, 0x115, 0x40, MULTI_REAR_L, 0x44);
+		OP(4, 0x116, 0x40, MULTI_REAR_R, 0x44);
+		OP(4, 0x117, 0x40, MULTI_CENTER, 0x44);
+		OP(4, 0x118, 0x40, MULTI_LFE, 0x44);
+	
+		INPUT_PATCH_END(patch);
 
-	/* fx12:Digital-Center */
-	OP(6, DIGITAL_CENTER, 0x117, 0x40, 0x40);
-	CONNECT(MULTI_CENTER, DIGITAL_CENTER);
 
-	/* fx11:Analog-LFE */
-	OP(6, DIGITAL_LFE, 0x118, 0x40, 0x40);
-	CONNECT(MULTI_LFE, DIGITAL_LFE);
+		//Routing patch start	
+		ROUTING_PATCH_START(rpatch, "Routing");
+		GET_INPUT_GPR(rpatch, 0x100, 0x0);
+		GET_INPUT_GPR(rpatch, 0x101, 0x1);
+		GET_INPUT_GPR(rpatch, 0x10c, 0x12);
+		GET_INPUT_GPR(rpatch, 0x10e, 0x13);
+		GET_INPUT_GPR(rpatch, 0x113, MULTI_FRONT_L);
+		GET_INPUT_GPR(rpatch, 0x114, MULTI_FRONT_R);
+		GET_INPUT_GPR(rpatch, 0x115, MULTI_REAR_L);
+		GET_INPUT_GPR(rpatch, 0x116, MULTI_REAR_R);
+		GET_INPUT_GPR(rpatch, 0x117, MULTI_CENTER);
+		GET_INPUT_GPR(rpatch, 0x118, MULTI_LFE);
+
+		GET_DYNAMIC_GPR(rpatch, 0x102);
+		GET_DYNAMIC_GPR(rpatch, 0x103);
+
+		GET_OUTPUT_GPR(rpatch, 0x104, 0x8);
+		GET_OUTPUT_GPR(rpatch, 0x105, 0x9);
+		GET_OUTPUT_GPR(rpatch, 0x10a, 0x2);
+		GET_OUTPUT_GPR(rpatch, 0x10b, 0x3);
+		
+		
+		/* input buffer */
+		OP(6, 0x102, AC97_IN_L, 0x40, 0x40);
+		OP(6, 0x103, AC97_IN_R, 0x40, 0x40);
+
+
+		/* Digital In + PCM + MULTI_FRONT-> AC97 out (front speakers)*/
+		OP(6, AC97_FRONT_L, 0x100, 0x10c, 0x113);
+
+		CONNECT(MULTI_FRONT_L, AC97_FRONT_L);
+		CONNECT(PCM_IN_L, AC97_FRONT_L);
+		CONNECT(SPDIF_CD_L, AC97_FRONT_L);
+
+		OP(6, AC97_FRONT_R, 0x101, 0x10e, 0x114);
+
+		CONNECT(MULTI_FRONT_R, AC97_FRONT_R);
+		CONNECT(PCM_IN_R, AC97_FRONT_R);
+		CONNECT(SPDIF_CD_R, AC97_FRONT_R);
+
+		/* Digital In + PCM + AC97 In + PCM1 + MULTI_REAR --> Rear Channel */ 
+		OP(6, 0x104, PCM1_IN_L, 0x100, 0x115);
+		OP(6, 0x104, 0x104, 0x10c, 0x102);
+
+		CONNECT(MULTI_REAR_L, ANALOG_REAR_L);
+		CONNECT(AC97_IN_L, ANALOG_REAR_L);
+		CONNECT(PCM_IN_L, ANALOG_REAR_L);
+		CONNECT(SPDIF_CD_L, ANALOG_REAR_L);
+		CONNECT(PCM1_IN_L, ANALOG_REAR_L);
+
+		OP(6, 0x105, PCM1_IN_R, 0x101, 0x116);
+		OP(6, 0x105, 0x105, 0x10e, 0x103);
+
+		CONNECT(MULTI_REAR_R, ANALOG_REAR_R);
+		CONNECT(AC97_IN_R, ANALOG_REAR_R);
+		CONNECT(PCM_IN_R, ANALOG_REAR_R);
+		CONNECT(SPDIF_CD_R, ANALOG_REAR_R);
+		CONNECT(PCM1_IN_R, ANALOG_REAR_R);
+
+		/* Digital In + PCM + AC97 In + MULTI_FRONT --> Digital out */
+		OP(6, 0x10b, 0x100, 0x102, 0x10c);
+		OP(6, 0x10b, 0x10b, 0x113, 0x40);
+
+		CONNECT(MULTI_FRONT_L, DIGITAL_OUT_L);
+		CONNECT(PCM_IN_L, DIGITAL_OUT_L);
+		CONNECT(AC97_IN_L, DIGITAL_OUT_L);
+		CONNECT(SPDIF_CD_L, DIGITAL_OUT_L);
+
+		OP(6, 0x10a, 0x101, 0x103, 0x10e);
+		OP(6, 0x10b, 0x10b, 0x114, 0x40);
+
+		CONNECT(MULTI_FRONT_R, DIGITAL_OUT_R);
+		CONNECT(PCM_IN_R, DIGITAL_OUT_R);
+		CONNECT(AC97_IN_R, DIGITAL_OUT_R);
+		CONNECT(SPDIF_CD_R, DIGITAL_OUT_R);
+
+		/* AC97 In --> ADC Recording Buffer */
+		OP(6, ADC_REC_L, 0x102, 0x40, 0x40);
+
+		CONNECT(AC97_IN_L, ADC_REC_L);
+
+		OP(6, ADC_REC_R, 0x103, 0x40, 0x40);
+
+		CONNECT(AC97_IN_R, ADC_REC_R);
+
+
+		/* fx12:Analog-Center */
+		OP(6, ANALOG_CENTER, 0x117, 0x40, 0x40);
+		CONNECT(MULTI_CENTER, ANALOG_CENTER);
+
+		/* fx11:Analog-LFE */
+		OP(6, ANALOG_LFE, 0x118, 0x40, 0x40);
+		CONNECT(MULTI_LFE, ANALOG_LFE);
+
+		/* fx12:Digital-Center */
+		OP(6, DIGITAL_CENTER, 0x117, 0x40, 0x40);
+		CONNECT(MULTI_CENTER, DIGITAL_CENTER);
+		
+		/* fx11:Analog-LFE */
+		OP(6, DIGITAL_LFE, 0x118, 0x40, 0x40);
+		CONNECT(MULTI_LFE, DIGITAL_LFE);
 	
-	ROUTING_PATCH_END(rpatch);
+		ROUTING_PATCH_END(rpatch);
 
 
-	// Rear volume control
-	OUTPUT_PATCH_START(patch, "Vol Rear L", 0x8, 0);
-	GET_INPUT_GPR(patch, 0x104, 0x8);
-	GET_CONTROL_GPR(patch, 0x119, "Vol", 0, 0x7fffffff);
+		// Rear volume control	
+		OUTPUT_PATCH_START(patch, "Vol Rear L", 0x8, 0);
+		GET_INPUT_GPR(patch, 0x104, 0x8);
+		GET_CONTROL_GPR(patch, 0x119, "Vol", 0, 0x7fffffff);
 
-	OP(0, ANALOG_REAR_L, 0x040, 0x104, 0x119);
-	OUTPUT_PATCH_END(patch);
+		OP(0, ANALOG_REAR_L, 0x040, 0x104, 0x119);
+		OUTPUT_PATCH_END(patch);
 
+		OUTPUT_PATCH_START(patch, "Vol Rear R", 0x9, 0);
+		GET_INPUT_GPR(patch, 0x105, 0x9);
+		GET_CONTROL_GPR(patch, 0x11a, "Vol", 0, 0x7fffffff);
 
-	OUTPUT_PATCH_START(patch, "Vol Rear R", 0x9, 0);
-	GET_INPUT_GPR(patch, 0x105, 0x9);
-	GET_CONTROL_GPR(patch, 0x11a, "Vol", 0, 0x7fffffff);
+		OP(0, ANALOG_REAR_R, 0x040, 0x105, 0x11a);
+		OUTPUT_PATCH_END(patch);
 
-	OP(0, ANALOG_REAR_R, 0x040, 0x105, 0x11a);
-	OUTPUT_PATCH_END(patch);
 
+		//Master volume control on front-digital	
+		OUTPUT_PATCH_START(patch, "Vol Master L", 0x2, 1);
+		GET_INPUT_GPR(patch, 0x10a, 0x2);
+		GET_CONTROL_GPR(patch, 0x108, "Vol", 0, 0x7fffffff);
 
-	//Master volume control on front-digital
-	OUTPUT_PATCH_START(patch, "Vol Master L", 0x2, 1);
-	GET_INPUT_GPR(patch, 0x10a, 0x2);
-	GET_CONTROL_GPR(patch, 0x108, "Vol", 0, 0x7fffffff);
+		OP(0, DIGITAL_OUT_L, 0x040, 0x10a, 0x108);
+		OUTPUT_PATCH_END(patch);
 
-	OP(0, DIGITAL_OUT_L, 0x040, 0x10a, 0x108);
-	OUTPUT_PATCH_END(patch);
 
+		OUTPUT_PATCH_START(patch, "Vol Master R", 0x3, 1);
+		GET_INPUT_GPR(patch, 0x10b, 0x3);
+		GET_CONTROL_GPR(patch, 0x109, "Vol", 0, 0x7fffffff);
 
-	OUTPUT_PATCH_START(patch, "Vol Master R", 0x3, 1);
-	GET_INPUT_GPR(patch, 0x10b, 0x3);
-	GET_CONTROL_GPR(patch, 0x109, "Vol", 0, 0x7fffffff);
+		OP(0, DIGITAL_OUT_R, 0x040, 0x10b, 0x109);
+		OUTPUT_PATCH_END(patch);
 
-	OP(0, DIGITAL_OUT_R, 0x040, 0x10b, 0x109);
-	OUTPUT_PATCH_END(patch);
 
+		/* delimiter patch */
+		patch = PATCH(mgr, patch_n);
+		patch->code_size = 0;
 
-	/* delimiter patch */
-	patch = PATCH(mgr, patch_n);
-	patch->code_size = 0;
-
-	sblive_writeptr(card, DBG, 0, 0);
+	
+		sblive_writeptr(card, DBG, 0, 0);
+	}
 
 	mgr->lock = SPIN_LOCK_UNLOCKED;
 
+	// Set up Volume controls, try to keep this the same for both Audigy and Live
 
 	//Master volume
 	mgr->ctrl_gpr[SOUND_MIXER_VOLUME][0] = 8;
@@ -749,8 +921,16 @@
 	emu10k1_set_volume_gpr(card, 0xd, left, VOL_5BIT);
 	emu10k1_set_volume_gpr(card, 0xf, right, VOL_5BIT);
 
-	//hard wire the ac97's pcm, we'll do that in dsp code instead.
-	emu10k1_ac97_write(card->ac97, 0x18, 0x0);
+
+	//hard wire the ac97's pcm, pcm volume is done above using dsp code.
+	if (card->is_audigy)
+		//for Audigy, we mute it and use the philips 6 channel DAC instead
+		emu10k1_ac97_write(card->ac97, 0x18, 0x8000);
+	else
+		//For the Live we hardwire it to full volume
+		emu10k1_ac97_write(card->ac97, 0x18, 0x0);
+
+	//remove it from the ac97_codec's control
 	card->ac97_supported_mixers &= ~SOUND_MASK_PCM;
 	card->ac97_stereo_mixers &= ~SOUND_MASK_PCM;
 
@@ -789,6 +969,13 @@
 			    SOLEH, 0,
 			    TAGLIST_END);
 
+	if (card->is_audigy) {
+		sblive_writeptr_tag(card,0,
+				    0x5e,0xf00,
+				    0x5f,0x3,
+				    TAGLIST_END);
+	}
+
 	/* Init envelope engine */
 	for (nCh = 0; nCh < NUM_G; nCh++) {
 		sblive_writeptr_tag(card, nCh,
@@ -824,6 +1011,21 @@
 				    ENVVAL, 0,
                                     TAGLIST_END);
 		sblive_writeptr(card, CPF, nCh, 0);
+		/*
+		  Audigy FXRT initialization
+		  reversed eng'd, may not be accurate.
+		 */
+		if (card->is_audigy) {
+			sblive_writeptr_tag(card,nCh,
+					    0x4c,0x0,
+					    0x4d,0x0,
+					    0x4e,0x0,
+					    0x4f,0x0,
+					    A_FXRT1, 0x3f3f3f3f,
+					    A_FXRT2, 0x3f3f3f3f,
+					    A_SENDAMOUNTS, 0,
+					    TAGLIST_END);
+		}
 	}
 	
 
@@ -858,6 +1060,25 @@
 
 			    TAGLIST_END);
 
+	if (card->is_audigy && (card->chiprev == 4)) {
+		/* Hacks for Alice3 to work independent of haP16V driver */
+		u32 tmp;
+
+		//Setup SRCMulti_I2S SamplingRate
+		tmp = sblive_readptr(card, A_SPDIF_SAMPLERATE, 0);
+		tmp &= 0xfffff1ff;
+		tmp |= (0x2<<9);
+		sblive_writeptr(card, A_SPDIF_SAMPLERATE, 0, tmp);
+
+		/* Setup SRCSel (Enable Spdif,I2S SRCMulti) */
+		emu10k1_writefn0(card, 0x20, 0x600000);
+		emu10k1_writefn0(card, 0x24, 0x14);
+
+		/* Setup SRCMulti Input Audio Enable */
+		emu10k1_writefn0(card, 0x20, 0x6E0000);
+		emu10k1_writefn0(card, 0x24, 0xFF00FF00);
+	}
+
 	ret = fx_init(card);		/* initialize effects engine */
 	if (ret < 0)
 		return ret;
@@ -905,16 +1126,30 @@
 	/* Lock Tank Memory = 1 */
 	/* Lock Sound Memory = 0 */
 	/* Auto Mute = 1 */
-
-	if (card->model == 0x20 || card->model == 0xc400 ||
-	  (card->model == 0x21 && card->chiprev < 6))
-	        emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE);
-	else
-		emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE);
-
+	if (card->is_audigy) {
+		if (card->chiprev == 4)
+			emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_AC3ENABLE_CDSPDIF | HCFG_AC3ENABLE_GPSPDIF | HCFG_AUTOMUTE | HCFG_JOYENABLE);
+		else
+			emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_AUTOMUTE | HCFG_JOYENABLE);
+	} else {
+		if (card->model == 0x20 || card->model == 0xc400 ||
+		 (card->model == 0x21 && card->chiprev < 6))
+	        	emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE);
+		else
+			emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE);
+	}
 	/* Enable Vol_Ctrl irqs */
 	emu10k1_irq_enable(card, INTE_VOLINCRENABLE | INTE_VOLDECRENABLE | INTE_MUTEENABLE | INTE_FXDSPENABLE);
 
+	if (card->is_audigy && (card->chiprev == 4)) {
+		/* Unmute Analog now.  Set GPO6 to 1 for Apollo.
+		 * This has to be done after init ALice3 I2SOut beyond 48KHz.
+		 * So, sequence is important. */
+		u32 tmp = emu10k1_readfn0(card, A_IOCFG);
+		tmp |= 0x0040;
+		emu10k1_writefn0(card, A_IOCFG, tmp);
+	}
+	
 	/* FIXME: TOSLink detection */
 	card->has_toslink = 0;
 
@@ -967,7 +1202,7 @@
 	return 0;
 }
 
-static void __devinit emu10k1_cleanup(struct emu10k1_card *card)
+static void emu10k1_cleanup(struct emu10k1_card *card)
 {
 	int ch;
 
@@ -1012,6 +1247,8 @@
 			    SOLEH, 0,
 			    TAGLIST_END);
 
+	if (card->is_audigy)
+		sblive_writeptr(card, 0, A_DBG,  A_DBG_SINGLE_STEP);
 
 	pci_free_consistent(card->pci_dev, card->virtualpagetable.size, card->virtualpagetable.addr, card->virtualpagetable.dma_handle);
 	pci_free_consistent(card->pci_dev, card->silentpage.size, card->silentpage.addr, card->silentpage.dma_handle);
@@ -1074,6 +1311,9 @@
 		card_names[pci_id->driver_data], card->chiprev, card->model, card->iobase,
 		card->iobase + card->length - 1, card->irq);
 
+	if (pci_id->device == PCI_DEVICE_ID_CREATIVE_AUDIGY)
+		card->is_audigy = 1;
+
 	pci_read_config_dword(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &subsysvid);
 	card->is_aps = (subsysvid == EMU_APS_SUBID);
 
@@ -1083,13 +1323,13 @@
 	init_waitqueue_head(&card->open_wait);
 
 	ret = emu10k1_audio_init(card);
-	if(ret < 0) {
+	if (ret < 0) {
                 printk(KERN_ERR "emu10k1: cannot initialize audio devices\n");
                 goto err_audio;
         }
 
 	ret = emu10k1_mixer_init(card);
-	if(ret < 0) {
+	if (ret < 0) {
 		printk(KERN_ERR "emu10k1: cannot initialize AC97 codec\n");
                 goto err_mixer;
 	}
@@ -1109,10 +1349,28 @@
 	if (card->is_aps)
 		emu10k1_ecard_init(card);
 
+	ret = emu10k1_register_devices(card);
+	if (ret < 0)
+		goto err_register;
+
+	/* proc entries must be created after registering devices, as
+	 * emu10k1_info_proc prints card->audio_dev &co. */
+	ret = emu10k1_proc_init(card);
+	if (ret < 0) {
+		printk(KERN_ERR "emu10k1: cannot initialize proc directory\n");
+                goto err_proc;
+	}
+	
 	list_add(&card->list, &emu10k1_devs);
 
 	return 0;
 
+err_proc:
+	emu10k1_unregister_devices(card);
+
+err_register:
+	emu10k1_cleanup(card);
+	
 err_emu10k1_init:
 	emu10k1_midi_cleanup(card);
 
@@ -1141,9 +1399,11 @@
 
 	list_del(&card->list);
 
+	emu10k1_unregister_devices(card);
 	emu10k1_cleanup(card);
 	emu10k1_midi_cleanup(card);
 	emu10k1_mixer_cleanup(card);
+	emu10k1_proc_cleanup(card);
 	emu10k1_audio_cleanup(card);	
 	free_irq(card->irq, card);
 	release_region(card->iobase, card->length);
diff -Nru a/sound/oss/emu10k1/midi.h b/sound/oss/emu10k1/midi.h
--- a/sound/oss/emu10k1/midi.h	Sat Jul 19 12:54:23 2003
+++ b/sound/oss/emu10k1/midi.h	Sat Jul 19 12:54:23 2003
@@ -52,4 +52,27 @@
 	struct list_head mid_hdrs;
 };
 
+/* uncomment next line to use midi port on Audigy drive */
+//#define USE_AUDIGY_DRIVE_MIDI
+
+#ifdef USE_AUDIGY_DRIVE_MIDI
+#define A_MUDATA	A_MUDATA2
+#define A_MUCMD		A_MUCMD2
+#define A_MUSTAT	A_MUCMD2
+#define A_IPR_MIDITRANSBUFEMPTY	A_IPR_MIDITRANSBUFEMPTY2
+#define A_IPR_MIDIRECVBUFEMPTY	A_IPR_MIDIRECVBUFEMPTY2
+#define A_INTE_MIDITXENABLE	A_INTE_MIDITXENABLE2
+#define A_INTE_MIDIRXENABLE	A_INTE_MIDIRXENABLE2
+#else
+#define A_MUDATA	A_MUDATA1
+#define A_MUCMD		A_MUCMD1
+#define A_MUSTAT	A_MUCMD1
+#define A_IPR_MIDITRANSBUFEMPTY	A_IPR_MIDITRANSBUFEMPTY1
+#define A_IPR_MIDIRECVBUFEMPTY	A_IPR_MIDIRECVBUFEMPTY1
+#define A_INTE_MIDITXENABLE	A_INTE_MIDITXENABLE1
+#define A_INTE_MIDIRXENABLE	A_INTE_MIDIRXENABLE1
+#endif
+
+
 #endif /* _MIDI_H */
+
diff -Nru a/sound/oss/emu10k1/mixer.c b/sound/oss/emu10k1/mixer.c
--- a/sound/oss/emu10k1/mixer.c	Sat Jul 19 12:54:26 2003
+++ b/sound/oss/emu10k1/mixer.c	Sat Jul 19 12:54:26 2003
@@ -136,7 +136,7 @@
 	r = (r * 40 + 50) / 100;
 
 	for (i = 0; i < 5; i++)
-		sblive_writeptr(card, GPR_BASE + card->mgr.ctrl_gpr[SOUND_MIXER_BASS][0] + i, 0, bass_table[l][i]);
+		sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + card->mgr.ctrl_gpr[SOUND_MIXER_BASS][0] + i, 0, bass_table[l][i]);
 }
 
 static void set_treble(struct emu10k1_card *card, int l, int r)
@@ -147,7 +147,7 @@
 	r = (r * 40 + 50) / 100;
 
 	for (i = 0; i < 5; i++)
-		sblive_writeptr(card, GPR_BASE + card->mgr.ctrl_gpr[SOUND_MIXER_TREBLE][0] + i , 0, treble_table[l][i]);
+		sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + card->mgr.ctrl_gpr[SOUND_MIXER_TREBLE][0] + i , 0, treble_table[l][i]);
 }
 
 const char volume_params[SOUND_MIXER_NRDEVICES]= {
@@ -206,22 +206,25 @@
 		switch (ctl->cmd) {
 #ifdef DBGEMU
 		case CMD_WRITEFN0:
-			emu10k1_writefn0(card, ctl->val[0], ctl->val[1]);
+			emu10k1_writefn0_2(card, ctl->val[0], ctl->val[1], ctl->val[2]);
 			break;
-
+#endif
 		case CMD_WRITEPTR:
-			if (ctl->val[1] >= 0x40 || ctl->val[0] > 0xff) {
+#ifdef DBGEMU
+			if (ctl->val[1] >= 0x40 || ctl->val[0] >= 0x1000) {
+#else
+			if (ctl->val[1] >= 0x40 || ctl->val[0] >= 0x1000 || ((ctl->val[0] < 0x100 ) &&
+		    //Any register allowed raw access goes here:
+				     (ctl->val[0] != A_SPDIF_SAMPLERATE) && (ctl->val[0] != A_DBG)
+			)
+				) {
+#endif
 				ret = -EINVAL;
 				break;
 			}
-
-			if ((ctl->val[0] & 0x7ff) > 0x3f)
-				ctl->val[1] = 0x00;
-
 			sblive_writeptr(card, ctl->val[0], ctl->val[1], ctl->val[2]);
-
 			break;
-#endif
+
 		case CMD_READFN0:
 			ctl->val[2] = emu10k1_readfn0(card, ctl->val[0]);
 
@@ -286,16 +289,13 @@
 
 		case CMD_GETVOICEPARAM:
 			ctl->val[0] = card->waveout.send_routing[0];
-			ctl->val[1] = card->waveout.send_a[0] | card->waveout.send_b[0] << 8 |
-			    	      card->waveout.send_c[0] << 16 | card->waveout.send_d[0] << 24;
+			ctl->val[1] = card->waveout.send_dcba[0];
 
 			ctl->val[2] = card->waveout.send_routing[1];
-			ctl->val[3] = card->waveout.send_a[1] | card->waveout.send_b[1] << 8 |
-				      card->waveout.send_c[1] << 16 | card->waveout.send_d[1] << 24;
+			ctl->val[3] = card->waveout.send_dcba[1];
 
 			ctl->val[4] = card->waveout.send_routing[2];
-			ctl->val[5] = card->waveout.send_a[2] | card->waveout.send_b[2] << 8 |
-				     card->waveout.send_c[2] << 16 | card->waveout.send_d[2] << 24;
+			ctl->val[5] = card->waveout.send_dcba[2];
 
 			if (copy_to_user((void *) arg, ctl, sizeof(struct mixer_private_ioctl)))
 				ret = -EFAULT;
@@ -303,23 +303,14 @@
 			break;
 
 		case CMD_SETVOICEPARAM:
-			card->waveout.send_routing[0] = ctl->val[0] & 0xffff;
-			card->waveout.send_a[0] = ctl->val[1] & 0xff;
-			card->waveout.send_b[0] = (ctl->val[1] >> 8) & 0xff;
-			card->waveout.send_c[0] = (ctl->val[1] >> 16) & 0xff;
-			card->waveout.send_d[0] = (ctl->val[1] >> 24) & 0xff;
-
-			card->waveout.send_routing[1] = ctl->val[2] & 0xffff;
-			card->waveout.send_a[1] = ctl->val[3] & 0xff;
-			card->waveout.send_b[1] = (ctl->val[3] >> 8) & 0xff;
-			card->waveout.send_c[1] = (ctl->val[3] >> 16) & 0xff;
-			card->waveout.send_d[1] = (ctl->val[3] >> 24) & 0xff;
-
-			card->waveout.send_routing[2] = ctl->val[4] & 0xffff;
-			card->waveout.send_a[2] = ctl->val[5] & 0xff;
-			card->waveout.send_b[2] = (ctl->val[5] >> 8) & 0xff;
-			card->waveout.send_c[2] = (ctl->val[5] >> 16) & 0xff;
-			card->waveout.send_d[2] = (ctl->val[5] >> 24) & 0xff;
+			card->waveout.send_routing[0] = ctl->val[0];
+			card->waveout.send_dcba[0] = ctl->val[1];
+
+			card->waveout.send_routing[1] = ctl->val[2];
+			card->waveout.send_dcba[1] = ctl->val[3];
+
+			card->waveout.send_routing[2] = ctl->val[4];
+			card->waveout.send_dcba[2] = ctl->val[5];
 
 			break;
 		
@@ -416,12 +407,16 @@
 			break;
 
 		case CMD_SETGPOUT:
-			if (ctl->val[0] > 2 || ctl->val[1] > 1) {
+			if ( ((ctl->val[0] > 2) && (!card->is_audigy))
+			     || (ctl->val[0] > 15) || ctl->val[1] > 1) {
 				ret= -EINVAL;
 				break;
 			}
 
-			emu10k1_writefn0(card, (1 << 24) | (((ctl->val[0]) + 10) << 16) | HCFG, ctl->val[1]);
+			if (card->is_audigy)
+				emu10k1_writefn0(card, (1 << 24) | ((ctl->val[0]) << 16) | A_IOCFG, ctl->val[1]);
+			else
+				emu10k1_writefn0(card, (1 << 24) | (((ctl->val[0]) + 10) << 16) | HCFG, ctl->val[1]);
 			break;
 
 		case CMD_GETGPR2OSS:
@@ -493,13 +488,20 @@
 			break;
 
 		case CMD_PRIVATE3_VERSION:
-			ctl->val[0]=PRIVATE3_VERSION;
+			ctl->val[0] = PRIVATE3_VERSION;	//private3 version
+			ctl->val[1] = MAJOR_VER;	//major driver version
+			ctl->val[2] = MINOR_VER;	//minor driver version
+			ctl->val[3] = card->is_audigy;	//1=card is audigy
+
+			if (card->is_audigy)
+				ctl->val[4]=emu10k1_readfn0(card, 0x18);
+
 			if (copy_to_user((void *) arg, ctl, sizeof(struct mixer_private_ioctl)))
 				ret = -EFAULT;
 			break;
 
 		case CMD_AC97_BOOST:
-			if(ctl->val[0])
+			if (ctl->val[0])
 				emu10k1_ac97_write(card->ac97, 0x18, 0x0);	
 			else
 				emu10k1_ac97_write(card->ac97, 0x18, 0x0808);
@@ -556,7 +558,7 @@
 
 				card->tankmem.size = size;
 
-				sblive_writeptr_tag(card, 0, TCB, (u32) card->tankmem.dma_handle, TCBS, size_reg, TAGLIST_END);
+				sblive_writeptr_tag(card, 0, TCB, (u32) card->tankmem.dma_handle, TCBS,(u32) size_reg, TAGLIST_END);
 
 				emu10k1_writefn0(card, HCFG_LOCKTANKCACHE, 0);
 			}
@@ -623,8 +625,13 @@
 		if (cmd == SOUND_MIXER_INFO) {
 			mixer_info info;
 
-			strncpy(info.id, card->ac97->name, sizeof(info.id));
-			strncpy(info.name, "Creative SBLive - Emu10k1", sizeof(info.name));
+			strlcpy(info.id, card->ac97->name, sizeof(info.id));
+
+			if (card->is_audigy)
+				strlcpy(info.name, "Audigy - Emu10k1", sizeof(info.name));
+			else
+				strlcpy(info.name, "Creative SBLive - Emu10k1", sizeof(info.name));
+				
 			info.modify_counter = card->ac97->modcnt;
 
 			if (copy_to_user((void *)arg, &info, sizeof(info)))
diff -Nru a/sound/oss/emu10k1/passthrough.c b/sound/oss/emu10k1/passthrough.c
--- a/sound/oss/emu10k1/passthrough.c	Sat Jul 19 12:54:25 2003
+++ b/sound/oss/emu10k1/passthrough.c	Sat Jul 19 12:54:25 2003
@@ -109,7 +109,7 @@
 	return 0;
 }
 
-static int pt_setup(struct emu10k1_wavedevice *wave_dev)
+int emu10k1_pt_setup(struct emu10k1_wavedevice *wave_dev)
 {
 	u32 bits;
 	struct emu10k1_card *card = wave_dev->card;
@@ -155,7 +155,7 @@
 		pt->prepend_size = 0;
 		if (pt->buf == NULL)
 			return -ENOMEM;
-		pt_setup(wave_dev);
+		emu10k1_pt_setup(wave_dev);
 	}
 	if (pt->prepend_size) {
 		int needed = PT_BLOCKSIZE - pt->prepend_size;
@@ -208,13 +208,14 @@
 
 	if (pt->state != PT_STATE_INACTIVE) {
 		DPF(2, "digital pass-through stopped\n");
-		sblive_writeptr(card, GPR_BASE + pt->enable_gpr, 0, 0);
+		sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + pt->enable_gpr, 0, 0);
 		for (i = 0; i < 3; i++) {
                         if (pt->spcs_to_use & (1 << i))
 				sblive_writeptr(card, SPCS0 + i, 0, pt->old_spcs[i]);
 		}
 		pt->state = PT_STATE_INACTIVE;
-		kfree(pt->buf);
+		if(pt->buf)
+			kfree(pt->buf);
 	}
 }
 
diff -Nru a/sound/oss/emu10k1/passthrough.h b/sound/oss/emu10k1/passthrough.h
--- a/sound/oss/emu10k1/passthrough.h	Sat Jul 19 12:54:25 2003
+++ b/sound/oss/emu10k1/passthrough.h	Sat Jul 19 12:54:25 2003
@@ -63,7 +63,36 @@
 	spinlock_t lock;
 };
 
+/*
+  Passthrough can be done in two methods:
+
+  Method 1 : tram
+     In original emu10k1, we couldn't bypass the sample rate converters. Even at 48kHz
+     (the internal sample rate of the emu10k1) the samples would get messed up.
+     To over come this, samples are copied into the tram and a special dsp patch copies
+     the samples out and generates interrupts when a block has finnished playing.
+
+  Method 2 : Interpolator bypass
+
+     Creative fixed the sample rate convert problem in emu10k1 rev 7 and higher
+     (including the emu10k2 (audigy)). This allows us to use the regular, and much simpler
+     playback method. 
+
+
+  In both methods, dsp code is used to mux audio and passthrough. This ensures that the spdif
+  doesn't receive audio and pasthrough data at the same time. The spdif flag SPCS_NOTAUDIODATA
+  is set to tell 
+
+ */
+
+// emu10k1 revs greater than or equal to 7 can use method2
+
+#define USE_PT_METHOD2  (card->is_audigy)
+#define USE_PT_METHOD1	!USE_PT_METHOD2
+
 ssize_t emu10k1_pt_write(struct file *file, const char *buf, size_t count);
+
+int emu10k1_pt_setup(struct emu10k1_wavedevice *wave_dev);
 void emu10k1_pt_stop(struct emu10k1_card *card);
 void emu10k1_pt_waveout_update(struct emu10k1_wavedevice *wave_dev);
 
diff -Nru a/sound/oss/emu10k1/recmgr.c b/sound/oss/emu10k1/recmgr.c
--- a/sound/oss/emu10k1/recmgr.c	Sat Jul 19 12:54:30 2003
+++ b/sound/oss/emu10k1/recmgr.c	Sat Jul 19 12:54:30 2003
@@ -74,7 +74,7 @@
 		DPF(2, "recording source: AC97\n");
 		buffer->sizereg = ADCBS;
 		buffer->addrreg = ADCBA;
-		buffer->idxreg = ADCIDX_IDX;
+		buffer->idxreg = card->is_audigy ? A_ADCIDX_IDX : ADCIDX_IDX;
 
 		switch (wiinst->format.samplingrate) {
 		case 0xBB80:
@@ -95,21 +95,27 @@
 		case 0x3E80:
 			buffer->adcctl = ADCCR_SAMPLERATE_16;
 			break;
+		// FIXME: audigy supports 12kHz recording
+		/*
+		case ????:
+			buffer->adcctl = A_ADCCR_SAMPLERATE_12;
+			break;
+		*/
 		case 0x2B11:
-			buffer->adcctl = ADCCR_SAMPLERATE_11;
+			buffer->adcctl = card->is_audigy ? A_ADCCR_SAMPLERATE_11 : ADCCR_SAMPLERATE_11;
 			break;
 		case 0x1F40:
-			buffer->adcctl = ADCCR_SAMPLERATE_8;
+			buffer->adcctl = card->is_audigy ? A_ADCCR_SAMPLERATE_8 : ADCCR_SAMPLERATE_8;
 			break;
 		default:
 			BUG();
 			break;
 		}
 
-		buffer->adcctl |= ADCCR_LCHANENABLE;
+		buffer->adcctl |= card->is_audigy ? A_ADCCR_LCHANENABLE : ADCCR_LCHANENABLE;
 
 		if (wiinst->format.channels == 2)
-			buffer->adcctl |= ADCCR_RCHANENABLE;
+			buffer->adcctl |= card->is_audigy ? A_ADCCR_RCHANENABLE : ADCCR_RCHANENABLE;
 
 		break;
 
diff -Nru a/sound/oss/emu10k1/voicemgr.c b/sound/oss/emu10k1/voicemgr.c
--- a/sound/oss/emu10k1/voicemgr.c	Sat Jul 19 12:54:25 2003
+++ b/sound/oss/emu10k1/voicemgr.c	Sat Jul 19 12:54:25 2003
@@ -32,6 +32,34 @@
 #include "voicemgr.h"
 #include "8010.h"
 
+#define PITCH_48000 0x00004000
+#define PITCH_96000 0x00008000
+#define PITCH_85000 0x00007155
+#define PITCH_80726 0x00006ba2
+#define PITCH_67882 0x00005a82
+#define PITCH_57081 0x00004c1c
+
+u32 emu10k1_select_interprom(struct emu10k1_card *card, struct emu_voice *voice)
+{
+	if(voice->pitch_target==PITCH_48000)
+		return CCCA_INTERPROM_0;
+	else if(voice->pitch_target<PITCH_48000)
+		return CCCA_INTERPROM_1;
+	else  if(voice->pitch_target>=PITCH_96000)
+		return CCCA_INTERPROM_0;
+	else  if(voice->pitch_target>=PITCH_85000)
+		return CCCA_INTERPROM_6;
+	else  if(voice->pitch_target>=PITCH_80726)
+		return CCCA_INTERPROM_5;
+	else  if(voice->pitch_target>=PITCH_67882)
+		return CCCA_INTERPROM_4;
+	else  if(voice->pitch_target>=PITCH_57081)
+		return CCCA_INTERPROM_3;
+	else  
+		return CCCA_INTERPROM_2;
+}
+
+
 /**
  * emu10k1_voice_alloc_buffer -
  *
@@ -216,17 +244,25 @@
 	voice->start += start;
 
 	for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
-		sblive_writeptr(card, FXRT, voice->num + i, voice->params[i].send_routing << 16);
+		if (card->is_audigy) {
+			sblive_writeptr(card, A_FXRT1, voice->num + i, voice->params[i].send_routing);
+			sblive_writeptr(card, A_FXRT2, voice->num + i, voice->params[i].send_routing2);
+			sblive_writeptr(card,  A_SENDAMOUNTS, voice->num + i, voice->params[i].send_hgfe);
+		} else {
+			sblive_writeptr(card, FXRT, voice->num + i, voice->params[i].send_routing << 16);
+		}
 
 		/* Stop CA */
 		/* Assumption that PT is already 0 so no harm overwriting */
-		sblive_writeptr(card, PTRX, voice->num + i, (voice->params[i].send_a << 8) | voice->params[i].send_b);
+		sblive_writeptr(card, PTRX, voice->num + i, ((voice->params[i].send_dcba & 0xff) << 8)
+				| ((voice->params[i].send_dcba & 0xff00) >> 8));
 
 		sblive_writeptr_tag(card, voice->num + i,
 				/* CSL, ST, CA */
-				    DSL, voice->endloop | (voice->params[i].send_d << 24),
-				    PSST, voice->startloop | (voice->params[i].send_c << 24),
-				    CCCA, (voice->start) | CCCA_INTERPROM_0 | ((voice->flags & VOICE_FLAGS_16BIT) ? 0 : CCCA_8BITSELECT),
+				    DSL, voice->endloop | (voice->params[i].send_dcba & 0xff000000),
+				    PSST, voice->startloop | ((voice->params[i].send_dcba & 0x00ff0000) << 8),
+				    CCCA, (voice->start) |  emu10k1_select_interprom(card,voice) |
+				        ((voice->flags & VOICE_FLAGS_16BIT) ? 0 : CCCA_8BITSELECT),
 				    /* Clear filter delay memory */
 				    Z1, 0,
 				    Z2, 0,
diff -Nru a/sound/oss/emu10k1/voicemgr.h b/sound/oss/emu10k1/voicemgr.h
--- a/sound/oss/emu10k1/voicemgr.h	Sat Jul 19 12:54:25 2003
+++ b/sound/oss/emu10k1/voicemgr.h	Sat Jul 19 12:54:25 2003
@@ -48,11 +48,13 @@
 	/* FX bus amount send */
 
 	u32 send_routing;
+	// audigy only:
+	u32 send_routing2;
+
+	u32 send_dcba;
+	// audigy only:
+	u32 send_hgfe;
 
-	u32 send_a;
-	u32 send_b;
-	u32 send_c;
-	u32 send_d;
 
 	u32 initial_fc;
 	u32 fc_target;
diff -Nru a/sound/oss/hal2.c b/sound/oss/hal2.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/sound/oss/hal2.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,1498 @@
+/*
+ *  Driver for HAL2 sound processors
+ *  Copyright (c) 2001, 2002 Ladislav Michl <ladis@psi.cz>
+ *  
+ *  Based on Ulf Carlsson's code.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as 
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Supported devices:
+ *  /dev/dsp    standard dsp device, (mostly) OSS compatible
+ *  /dev/mixer	standard mixer device, (mostly) OSS compatible
+ *
+ *  BUGS:
+ *  + Driver currently supports indigo mode only.
+ *  + Recording doesn't work. I guess that it is caused by PBUS channel
+ *    misconfiguration, but until I get relevant info I'm unable to fix it.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/sound.h>
+#include <linux/soundcard.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/sgi/sgint23.h>
+
+#include "hal2.h"
+
+#if 0
+#define DEBUG(args...)		printk(args)
+#else
+#define DEBUG(args...)
+#endif
+
+#if 0 
+#define DEBUG_MIX(args...)	printk(args)
+#else
+#define DEBUG_MIX(args...)
+#endif
+
+#define H2_INDIRECT_WAIT(regs)	while (regs->isr & H2_ISR_TSTATUS);
+
+#define H2_READ_ADDR(addr)	(addr | (1<<7))
+#define H2_WRITE_ADDR(addr)	(addr)
+
+static char *hal2str = "HAL2 audio";
+static int ibuffers = 32;
+static int obuffers = 32;
+
+/* I doubt anyone has a machine with two HAL2 cards. It's possible to
+ * have two HPC's, so it is probably possible to have two HAL2 cards.
+ * Try to deal with it, but note that it is not tested.
+ */
+#define MAXCARDS	2
+static hal2_card_t* hal2_card[MAXCARDS];
+
+static const struct {
+	unsigned char idx:4, avail:1;
+} mixtable[SOUND_MIXER_NRDEVICES] = {
+	[SOUND_MIXER_PCM] = { H2_MIX_OUTPUT_ATT, 1 },	/* voice */
+	[SOUND_MIXER_MIC] = { H2_MIX_INPUT_GAIN, 1 },	/* mic */
+};
+
+#define H2_SUPPORTED_FORMATS	(AFMT_S16_LE | AFMT_S16_BE)
+
+static inline void hal2_isr_write(hal2_card_t *hal2, u32 val)
+{
+	hal2->ctl_regs->isr = val;
+}
+
+static inline u32 hal2_isr_look(hal2_card_t *hal2)
+{
+	return hal2->ctl_regs->isr;
+}
+
+static inline u32 hal2_rev_look(hal2_card_t *hal2)
+{
+	return hal2->ctl_regs->rev;
+}
+
+#if 0
+static u16 hal2_i_look16(hal2_card_t *hal2, u32 addr)
+{
+	hal2_ctl_regs_t *regs = hal2->ctl_regs;
+
+	regs->iar = H2_READ_ADDR(addr);
+	H2_INDIRECT_WAIT(regs);
+	return (regs->idr0 & 0xffff);
+}
+#endif
+
+static u32 hal2_i_look32(hal2_card_t *hal2, u32 addr)
+{
+	u32 ret;
+	hal2_ctl_regs_t *regs = hal2->ctl_regs;
+
+	regs->iar = H2_READ_ADDR(addr);
+	H2_INDIRECT_WAIT(regs);
+	ret = regs->idr0 & 0xffff;
+	regs->iar = H2_READ_ADDR(addr | 0x1);
+	H2_INDIRECT_WAIT(regs);
+	ret |= (regs->idr0 & 0xffff) << 16;
+	return ret;
+}
+
+static void hal2_i_write16(hal2_card_t *hal2, u32 addr, u16 val)
+{
+	hal2_ctl_regs_t *regs = hal2->ctl_regs;
+
+	regs->idr0 = val;
+	regs->idr1 = 0;
+	regs->idr2 = 0;
+	regs->idr3 = 0;
+	regs->iar = H2_WRITE_ADDR(addr);
+	H2_INDIRECT_WAIT(regs);
+}
+
+static void hal2_i_write32(hal2_card_t *hal2, u32 addr, u32 val)
+{
+	hal2_ctl_regs_t *regs = hal2->ctl_regs;
+
+	regs->idr0 = val & 0xffff;
+	regs->idr1 = val >> 16;
+	regs->idr2 = 0;
+	regs->idr3 = 0;
+	regs->iar = H2_WRITE_ADDR(addr);
+	H2_INDIRECT_WAIT(regs);
+}
+
+static void hal2_i_setbit16(hal2_card_t *hal2, u32 addr, u16 bit)
+{
+	hal2_ctl_regs_t *regs = hal2->ctl_regs;
+
+	regs->iar = H2_READ_ADDR(addr);
+	H2_INDIRECT_WAIT(regs);
+	regs->idr0 = regs->idr0 | bit;
+	regs->idr1 = 0;
+	regs->idr2 = 0;
+	regs->idr3 = 0;
+	regs->iar = H2_WRITE_ADDR(addr);
+	H2_INDIRECT_WAIT(regs);
+}
+
+static void hal2_i_setbit32(hal2_card_t *hal2, u32 addr, u32 bit)
+{
+	u32 tmp;
+	hal2_ctl_regs_t *regs = hal2->ctl_regs;
+
+	regs->iar = H2_READ_ADDR(addr);
+	H2_INDIRECT_WAIT(regs);
+	tmp = regs->idr0 | (regs->idr1 << 16) | bit;
+	regs->idr0 = tmp & 0xffff;
+	regs->idr1 = tmp >> 16;
+	regs->idr2 = 0;
+	regs->idr3 = 0;
+	regs->iar = H2_WRITE_ADDR(addr);
+	H2_INDIRECT_WAIT(regs);
+}
+
+static void hal2_i_clearbit16(hal2_card_t *hal2, u32 addr, u16 bit)
+{
+	hal2_ctl_regs_t *regs = hal2->ctl_regs;
+
+	regs->iar = H2_READ_ADDR(addr);
+	H2_INDIRECT_WAIT(regs);
+	regs->idr0 = regs->idr0 & ~bit;
+	regs->idr1 = 0;
+	regs->idr2 = 0;
+	regs->idr3 = 0;
+	regs->iar = H2_WRITE_ADDR(addr);
+	H2_INDIRECT_WAIT(regs);
+}
+
+#if 0
+static void hal2_i_clearbit32(hal2_card_t *hal2, u32 addr, u32 bit)
+{
+	u32 tmp;
+	hal2_ctl_regs_t *regs = hal2->ctl_regs;
+
+	regs->iar = H2_READ_ADDR(addr);
+	H2_INDIRECT_WAIT(regs);
+	tmp = (regs->idr0 | (regs->idr1 << 16)) & ~bit;
+	regs->idr0 = tmp & 0xffff;
+	regs->idr1 = tmp >> 16;
+	regs->idr2 = 0;
+	regs->idr3 = 0;
+	regs->iar = H2_WRITE_ADDR(addr);
+	H2_INDIRECT_WAIT(regs);
+}
+#endif
+
+#ifdef HAL2_DEBUG
+static void hal2_dump_regs(hal2_card_t *hal2)
+{
+	printk("isr: %08hx ", hal2_isr_look(hal2));
+	printk("rev: %08hx\n", hal2_rev_look(hal2));
+	printk("relay: %04hx\n", hal2_i_look16(hal2, H2I_RELAY_C));
+	printk("port en: %04hx ", hal2_i_look16(hal2, H2I_DMA_PORT_EN));
+	printk("dma end: %04hx ", hal2_i_look16(hal2, H2I_DMA_END));
+	printk("dma drv: %04hx\n", hal2_i_look16(hal2, H2I_DMA_DRV));
+	printk("syn ctl: %04hx ", hal2_i_look16(hal2, H2I_SYNTH_C));
+	printk("aesrx ctl: %04hx ", hal2_i_look16(hal2, H2I_AESRX_C));
+	printk("aestx ctl: %04hx ", hal2_i_look16(hal2, H2I_AESTX_C));
+	printk("dac ctl1: %04hx ", hal2_i_look16(hal2, H2I_ADC_C1));
+	printk("dac ctl2: %08lx ", hal2_i_look32(hal2, H2I_ADC_C2));
+	printk("adc ctl1: %04hx ", hal2_i_look16(hal2, H2I_DAC_C1));
+	printk("adc ctl2: %08lx ", hal2_i_look32(hal2, H2I_DAC_C2));
+	printk("syn map: %04hx\n", hal2_i_look16(hal2, H2I_SYNTH_MAP_C));
+	printk("bres1 ctl1: %04hx ", hal2_i_look16(hal2, H2I_BRES1_C1));
+	printk("bres1 ctl2: %04lx ", hal2_i_look32(hal2, H2I_BRES1_C2));
+	printk("bres2 ctl1: %04hx ", hal2_i_look16(hal2, H2I_BRES2_C1));
+	printk("bres2 ctl2: %04lx ", hal2_i_look32(hal2, H2I_BRES2_C2));
+	printk("bres3 ctl1: %04hx ", hal2_i_look16(hal2, H2I_BRES3_C1));
+	printk("bres3 ctl2: %04lx\n", hal2_i_look32(hal2, H2I_BRES3_C2));
+}
+#endif
+
+static hal2_card_t* hal2_dsp_find_card(int minor)
+{
+	int i;
+
+	for (i = 0; i < MAXCARDS; i++)
+		if (hal2_card[i] != NULL && hal2_card[i]->dev_dsp == minor)
+			return hal2_card[i];
+	return NULL;
+}
+
+static hal2_card_t* hal2_mixer_find_card(int minor)
+{
+	int i;
+
+	for (i = 0; i < MAXCARDS; i++)
+		if (hal2_card[i] != NULL && hal2_card[i]->dev_mixer == minor)
+			return hal2_card[i];
+	return NULL;
+}
+
+
+static void hal2_dac_interrupt(hal2_codec_t *dac)
+{
+	int running;
+
+	spin_lock(&dac->lock);
+	
+	/* if tail buffer contains zero samples DMA stream was already
+	 * stopped */
+	running = dac->tail->info.cnt;
+	dac->tail->info.cnt = 0;
+	dac->tail->info.desc.cntinfo = HPCDMA_XIE | HPCDMA_EOX;
+	dma_cache_wback_inv((unsigned long) dac->tail,
+			    sizeof(struct hpc_dma_desc));
+	/* we just proccessed empty buffer, don't update tail pointer */
+	if (running)
+		dac->tail = dac->tail->info.next;
+
+	spin_unlock(&dac->lock);
+
+	wake_up(&dac->dma_wait);
+}
+
+static void hal2_adc_interrupt(hal2_codec_t *adc)
+{
+	int running;
+	
+	spin_lock(&adc->lock);
+
+	/* if head buffer contains nonzero samples DMA stream was already
+	 * stopped */
+	running = !adc->head->info.cnt;
+	adc->head->info.cnt = H2_BUFFER_SIZE;
+	adc->head->info.desc.cntinfo = HPCDMA_XIE | HPCDMA_EOX;
+	dma_cache_wback_inv((unsigned long) adc->head,
+			    sizeof(struct hpc_dma_desc));
+	/* we just proccessed empty buffer, don't update head pointer */
+	if (running) {
+		dma_cache_inv((unsigned long) adc->head->data, H2_BUFFER_SIZE);
+		adc->head = adc->head->info.next;
+	}
+
+	spin_unlock(&adc->lock);
+
+	wake_up(&adc->dma_wait);
+}
+
+static irqreturn_t hal2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	hal2_card_t *hal2 = (hal2_card_t*)dev_id;
+
+	/* decide what caused this interrupt */
+	if (hal2->dac.pbus.pbus->pbdma_ctrl & HPC3_PDMACTRL_INT)
+		hal2_dac_interrupt(&hal2->dac);
+	if (hal2->adc.pbus.pbus->pbdma_ctrl & HPC3_PDMACTRL_INT)
+		hal2_adc_interrupt(&hal2->adc);
+	return IRQ_HANDLED;
+}
+
+static int hal2_compute_rate(hal2_codec_t *codec, unsigned int rate)
+{
+	unsigned short inc;
+	
+	/* We default to 44.1 kHz and if it isn't possible to fall back to
+	 * 48.0 kHz with the needed adjustments of real_rate.
+	 */
+
+	DEBUG("rate: %d\n", rate);
+	
+	/* Refer to CS4216 data sheet */
+	if (rate < 4000)
+		rate = 4000;
+	if (rate > 50000)
+		rate = 50000;
+
+	/* Note: This is NOT the way they set up the bresenham clock generators
+	 * in the specification. I've tried to implement that method but it
+	 * doesn't work. It's probably another silly bug in the spec.
+	 *
+	 * I accidently discovered this method while I was testing and it seems
+	 * to work very well with all frequencies, and thee shall follow rule #1
+	 * of programming :-)
+	 */
+	
+	if (44100 % rate == 0) {
+		inc = 44100 / rate;
+		if (inc < 1) inc = 1;
+		codec->master = 44100;
+	} else {
+		inc = 48000 / rate;
+		if (inc < 1) inc = 1;
+		rate = 48000 / inc;
+		codec->master = 48000;
+	}
+	codec->inc = inc;
+	codec->mod = 1;
+	
+	DEBUG("real_rate: %d\n", rate);
+
+	return rate;
+}
+
+static void hal2_set_dac_rate(hal2_card_t *hal2)
+{
+	unsigned int master = hal2->dac.master;
+	int inc = hal2->dac.inc;
+	int mod = hal2->dac.mod;
+
+	DEBUG("master: %d inc: %d mod: %d\n", master, inc, mod);
+	
+	hal2_i_write16(hal2, H2I_BRES1_C1, (master == 44100) ? 1 : 0);
+	hal2_i_write32(hal2, H2I_BRES1_C2, ((0xffff & (mod - inc - 1)) << 16) | 1);
+}
+
+static void hal2_set_adc_rate(hal2_card_t *hal2)
+{
+	unsigned int master = hal2->adc.master;
+	int inc = hal2->adc.inc;
+	int mod = hal2->adc.mod;
+
+	DEBUG("master: %d inc: %d mod: %d\n", master, inc, mod);
+	
+	hal2_i_write16(hal2, H2I_BRES2_C1, (master == 44100) ? 1 : 0);
+	hal2_i_write32(hal2, H2I_BRES2_C2, ((0xffff & (mod - inc - 1)) << 16) | 1);
+}
+
+static void hal2_setup_dac(hal2_card_t *hal2)
+{
+	unsigned int fifobeg, fifoend, highwater, sample_size;
+	hal2_pbus_t *pbus = &hal2->dac.pbus;
+
+	DEBUG("hal2_setup_dac\n");
+	
+	/* Now we set up some PBUS information. The PBUS needs information about
+	 * what portion of the fifo it will use. If it's receiving or
+	 * transmitting, and finally whether the stream is little endian or big
+	 * endian. The information is written later, on the start call.
+	 */
+	sample_size = 2 * hal2->dac.voices;
+
+	/* Fifo should be set to hold exactly four samples. Highwater mark
+	 * should be set to two samples. */
+	highwater = (sample_size * 2) >> 1;	/* halfwords */
+	fifobeg = 0;				/* playback is first */
+	fifoend = (sample_size * 4) >> 3;	/* doublewords */
+	pbus->ctrl = HPC3_PDMACTRL_RT | HPC3_PDMACTRL_LD |
+		     (highwater << 8) | (fifobeg << 16) | (fifoend << 24);
+	/* We disable everything before we do anything at all */
+	pbus->pbus->pbdma_ctrl = HPC3_PDMACTRL_LD;
+	hal2_i_clearbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECTX);
+	hal2_i_clearbit16(hal2, H2I_DMA_DRV, (1 << pbus->pbusnr));
+	/* Setup the HAL2 for playback */
+	hal2_set_dac_rate(hal2);
+	/* We are using 1st Bresenham clock generator for playback */
+	hal2_i_write16(hal2, H2I_DAC_C1, (pbus->pbusnr << H2I_C1_DMA_SHIFT)
+			| (1 << H2I_C1_CLKID_SHIFT)
+			| (hal2->dac.voices << H2I_C1_DATAT_SHIFT));
+}
+
+static void hal2_setup_adc(hal2_card_t *hal2)
+{
+	unsigned int fifobeg, fifoend, highwater, sample_size;
+	hal2_pbus_t *pbus = &hal2->adc.pbus;
+
+	DEBUG("hal2_setup_adc\n");
+	
+	sample_size = 2 * hal2->adc.voices;
+
+	highwater = (sample_size * 2) >> 1;		/* halfwords */
+	fifobeg = (4 * 4) >> 3;				/* record is second */
+	fifoend = (4 * 4 + sample_size * 4) >> 3;	/* doublewords */
+	pbus->ctrl = HPC3_PDMACTRL_RT | HPC3_PDMACTRL_RCV | HPC3_PDMACTRL_LD | 
+		     (highwater << 8) | (fifobeg << 16) | (fifoend << 24);
+	pbus->pbus->pbdma_ctrl = HPC3_PDMACTRL_LD;
+	hal2_i_clearbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECR);
+	hal2_i_clearbit16(hal2, H2I_DMA_DRV, (1 << pbus->pbusnr));
+	/* Setup the HAL2 for record */
+	hal2_set_adc_rate(hal2);
+	/* We are using 2nd Bresenham clock generator for record */
+	hal2_i_write16(hal2, H2I_ADC_C1, (pbus->pbusnr << H2I_C1_DMA_SHIFT)
+			| (2 << H2I_C1_CLKID_SHIFT)
+			| (hal2->adc.voices << H2I_C1_DATAT_SHIFT));
+}
+
+static void hal2_start_dac(hal2_card_t *hal2)
+{
+	hal2_pbus_t *pbus = &hal2->dac.pbus;
+
+	DEBUG("hal2_start_dac\n");
+	
+	pbus->pbus->pbdma_dptr = PHYSADDR(hal2->dac.tail);
+	pbus->pbus->pbdma_ctrl = pbus->ctrl | HPC3_PDMACTRL_ACT;
+
+	/* set endianess */
+	if (hal2->dac.format & AFMT_S16_LE)
+		hal2_i_setbit16(hal2, H2I_DMA_END, H2I_DMA_END_CODECTX);
+	else
+		hal2_i_clearbit16(hal2, H2I_DMA_END, H2I_DMA_END_CODECTX);
+	/* set DMA bus */
+	hal2_i_setbit16(hal2, H2I_DMA_DRV, (1 << pbus->pbusnr));
+	/* enable DAC */
+	hal2_i_setbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECTX);
+}
+
+static void hal2_start_adc(hal2_card_t *hal2)
+{
+	hal2_pbus_t *pbus = &hal2->adc.pbus;
+
+	DEBUG("hal2_start_adc\n");
+	
+	pbus->pbus->pbdma_dptr = PHYSADDR(hal2->adc.head);
+	pbus->pbus->pbdma_ctrl = pbus->ctrl | HPC3_PDMACTRL_ACT;
+	
+	/* set endianess */
+	if (hal2->adc.format & AFMT_S16_LE)
+		hal2_i_setbit16(hal2, H2I_DMA_END, H2I_DMA_END_CODECR);
+	else
+		hal2_i_clearbit16(hal2, H2I_DMA_END, H2I_DMA_END_CODECR);
+	/* set DMA bus */
+	hal2_i_setbit16(hal2, H2I_DMA_DRV, (1 << pbus->pbusnr));
+	/* enable ADC */
+	hal2_i_setbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECR);
+}
+
+static inline void hal2_stop_dac(hal2_card_t *hal2)
+{
+	DEBUG("hal2_stop_dac\n");
+	
+	hal2->dac.pbus.pbus->pbdma_ctrl = HPC3_PDMACTRL_LD;
+	/* The HAL2 itself may remain enabled safely */
+}
+
+static inline void hal2_stop_adc(hal2_card_t *hal2)
+{
+	DEBUG("hal2_stop_adc\n");
+	
+	hal2->adc.pbus.pbus->pbdma_ctrl = HPC3_PDMACTRL_LD;
+}
+
+#define hal2_alloc_dac_dmabuf(hal2)	hal2_alloc_dmabuf(hal2, 1)
+#define hal2_alloc_adc_dmabuf(hal2)	hal2_alloc_dmabuf(hal2, 0)
+static int hal2_alloc_dmabuf(hal2_card_t *hal2, int is_dac)
+{
+	int buffers, cntinfo;
+	hal2_buf_t *buf, *prev;
+	hal2_codec_t *codec;
+
+	if (is_dac) {
+		codec = &hal2->dac;
+		buffers = obuffers;
+		cntinfo = HPCDMA_XIE | HPCDMA_EOX;
+	} else {
+		codec = &hal2->adc;
+		buffers = ibuffers;
+		cntinfo = HPCDMA_XIE | H2_BUFFER_SIZE;
+	}
+	
+	DEBUG("allocating %d DMA buffers.\n", buffers);
+	
+	buf = (hal2_buf_t*) get_zeroed_page(GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	codec->head = buf;
+	codec->tail = buf;
+	
+	while (--buffers) {
+		buf->info.desc.pbuf = PHYSADDR(&buf->data);
+		buf->info.desc.cntinfo = cntinfo;
+		buf->info.cnt = 0;
+		prev = buf;
+		buf = (hal2_buf_t*) get_zeroed_page(GFP_KERNEL);
+		if (!buf) {
+			printk("HAL2: Not enough memory for DMA buffer.\n");
+			buf = codec->head;
+			while (buf) {
+				prev = buf;
+				free_page((unsigned long) buf);
+				buf = prev->info.next;
+			}
+			return -ENOMEM;
+		}
+		prev->info.next = buf;
+		prev->info.desc.pnext = PHYSADDR(buf);
+		/* The PBUS can prolly not read this stuff when it's in
+		 * the cache so we have to flush it back to main memory
+		 */
+		dma_cache_wback_inv((unsigned long) prev, PAGE_SIZE);
+	}
+	buf->info.desc.pbuf = PHYSADDR(&buf->data);
+	buf->info.desc.cntinfo = cntinfo;
+	buf->info.cnt = 0;
+	buf->info.next = codec->head;
+	buf->info.desc.pnext = PHYSADDR(codec->head);
+	dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE);
+	
+	return 0;
+}
+
+#define hal2_free_dac_dmabuf(hal2)	hal2_free_dmabuf(hal2, 1)
+#define hal2_free_adc_dmabuf(hal2)	hal2_free_dmabuf(hal2, 0)
+static void hal2_free_dmabuf(hal2_card_t *hal2, int is_dac)
+{
+	hal2_buf_t *buf, *next;
+	hal2_codec_t *codec = (is_dac) ? &hal2->dac : &hal2->adc;
+
+	if (!codec->head)
+		return;
+	
+	buf = codec->head->info.next;
+	codec->head->info.next = NULL;
+	while (buf) {
+		next = buf->info.next;
+		free_page((unsigned long) buf);
+		buf = next;
+	}
+	codec->head = codec->tail = NULL;
+}
+
+/* 
+ * Add 'count' bytes to 'buffer' from DMA ring buffers. Return number of
+ * bytes added or -EFAULT if copy_from_user failed.
+ */
+static int hal2_get_buffer(hal2_card_t *hal2, char *buffer, int count)
+{
+	unsigned long flags;
+	int size, ret = 0;
+	hal2_codec_t *adc = &hal2->adc;
+	
+	spin_lock_irqsave(&adc->lock, flags);
+	
+	DEBUG("getting %d bytes ", count);
+
+	/* enable DMA stream if there are no data */
+	if (!(adc->pbus.pbus->pbdma_ctrl & HPC3_PDMACTRL_ISACT) &&
+	    adc->tail->info.cnt == 0)
+		hal2_start_adc(hal2);
+
+	DEBUG("... ");
+
+	while (adc->tail->info.cnt > 0 && count > 0) {
+		size = min(adc->tail->info.cnt, count);
+		spin_unlock_irqrestore(&adc->lock, flags);
+
+		if (copy_to_user(buffer, &adc->tail->data[H2_BUFFER_SIZE-size],
+				 size)) {
+			ret = -EFAULT;
+			goto out;
+		}
+
+		spin_lock_irqsave(&adc->lock, flags);
+		
+		adc->tail->info.cnt -= size;
+		/* buffer is empty, update tail pointer */
+		if (adc->tail->info.cnt == 0) {
+			adc->tail->info.desc.cntinfo = HPCDMA_XIE |
+						       H2_BUFFER_SIZE;
+			dma_cache_wback_inv((unsigned long) adc->tail,
+					    sizeof(struct hpc_dma_desc));
+			adc->tail = adc->tail->info.next;
+			/* enable DMA stream again if needed */
+			if (!(adc->pbus.pbus->pbdma_ctrl & HPC3_PDMACTRL_ISACT))
+				hal2_start_adc(hal2);
+
+		}
+		buffer += size;
+		ret += size;
+		count -= size;
+
+		DEBUG("(%d) ", size);
+	}
+	spin_unlock_irqrestore(&adc->lock, flags);
+out:	
+	DEBUG("\n");
+	
+	return ret;
+} 
+
+/* 
+ * Add 'count' bytes from 'buffer' to DMA ring buffers. Return number of
+ * bytes added or -EFAULT if copy_from_user failed.
+ */
+static int hal2_add_buffer(hal2_card_t *hal2, char *buffer, int count)
+{
+	unsigned long flags;
+	int size, ret = 0;
+	hal2_codec_t *dac = &hal2->dac;
+	
+	spin_lock_irqsave(&dac->lock, flags);
+	
+	DEBUG("adding %d bytes ", count);
+
+	while (dac->head->info.cnt == 0 && count > 0) {
+		size = min((int)H2_BUFFER_SIZE, count);
+		spin_unlock_irqrestore(&dac->lock, flags);
+		
+		if (copy_from_user(dac->head->data, buffer, size)) {
+			ret = -EFAULT;
+			goto out;
+		}
+		spin_lock_irqsave(&dac->lock, flags);
+
+		dac->head->info.desc.cntinfo = size | HPCDMA_XIE;
+		dac->head->info.cnt = size;
+		dma_cache_wback_inv((unsigned long) dac->head, 
+				    size + PAGE_SIZE - H2_BUFFER_SIZE);
+		buffer += size;
+		ret += size;
+		count -= size;
+		dac->head = dac->head->info.next;
+
+		DEBUG("(%d) ", size);
+	}
+	if (!(dac->pbus.pbus->pbdma_ctrl & HPC3_PDMACTRL_ISACT) && ret > 0)
+		hal2_start_dac(hal2);
+	
+	spin_unlock_irqrestore(&dac->lock, flags);
+out:	
+	DEBUG("\n");
+	
+	return ret;
+}
+
+#define hal2_reset_dac_pointer(hal2)	hal2_reset_pointer(hal2, 1)
+#define hal2_reset_adc_pointer(hal2)	hal2_reset_pointer(hal2, 0)
+static void hal2_reset_pointer(hal2_card_t *hal2, int is_dac)
+{
+	hal2_codec_t *codec = (is_dac) ? &hal2->dac : &hal2->adc;
+	
+	DEBUG("hal2_reset_pointer\n");
+
+	codec->tail = codec->head;
+	do {
+		codec->tail->info.desc.cntinfo = HPCDMA_XIE | (is_dac) ? 
+						 HPCDMA_EOX : H2_BUFFER_SIZE;
+		codec->tail->info.cnt = 0;
+		dma_cache_wback_inv((unsigned long) codec->tail, 
+				    sizeof(struct hpc_dma_desc));
+		codec->tail = codec->tail->info.next;
+	} while (codec->tail != codec->head);
+}
+
+static int hal2_sync_dac(hal2_card_t *hal2)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	hal2_codec_t *dac = &hal2->dac;
+	int ret = 0;
+	signed long timeout = 1000 * H2_BUFFER_SIZE * 2 * dac->voices *
+			      HZ / dac->sample_rate / 900;
+
+	down(&dac->sem);
+	
+	while (dac->pbus.pbus->pbdma_ctrl & HPC3_PDMACTRL_ISACT) {
+		add_wait_queue(&dac->dma_wait, &wait);
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (!schedule_timeout(timeout))
+			/* We may get bogus timeout when system is 
+			 * heavily loaded */
+			if (dac->tail->info.cnt) {
+				printk("HAL2: timeout...\n");
+				ret = -ETIME;
+			}
+		if (signal_pending(current))
+			ret = -ERESTARTSYS;
+		if (ret) {
+			hal2_stop_dac(hal2);
+			hal2_reset_dac_pointer(hal2);
+		}
+		remove_wait_queue(&dac->dma_wait, &wait);
+	}
+
+	up(&dac->sem);
+	
+	return ret;
+}
+
+static int hal2_write_mixer(hal2_card_t *hal2, int index, int vol)
+{
+	unsigned int l, r;
+
+	DEBUG_MIX("mixer %d write\n", index);
+	
+	if (index >= SOUND_MIXER_NRDEVICES || !mixtable[index].avail)
+		return -EINVAL;
+
+	r = (vol >> 8) & 0xff;
+	if (r > 100)
+		r = 100;
+	l = vol & 0xff;
+	if (l > 100)
+		l = 100;
+	
+	hal2->mixer.volume[mixtable[index].idx] = l | (r << 8);
+
+	switch (mixtable[index].idx) {
+	case H2_MIX_OUTPUT_ATT: {
+
+		DEBUG_MIX("output attenuator %d,%d\n", l, r);
+
+		if (r | l) {
+			unsigned int tmp = hal2_i_look32(hal2, H2I_DAC_C2); 
+		
+			tmp &= ~(H2I_C2_L_ATT_M | H2I_C2_R_ATT_M | H2I_C2_MUTE);
+
+			/* Attenuator has five bits */
+			l = (31 * (100 - l) / 99);
+			r = (31 * (100 - r) / 99);
+			
+			DEBUG_MIX("left: %d, right %d\n", l, r);
+
+			tmp |= (l << H2I_C2_L_ATT_SHIFT) & H2I_C2_L_ATT_M;
+			tmp |= (r << H2I_C2_R_ATT_SHIFT) & H2I_C2_R_ATT_M;
+			hal2_i_write32(hal2, H2I_DAC_C2, tmp);
+		} else 
+			hal2_i_setbit32(hal2, H2I_DAC_C2, H2I_C2_MUTE);
+	}
+	case H2_MIX_INPUT_GAIN: {
+		/* TODO */
+	}
+	}
+	return 0;
+}
+
+static void hal2_init_mixer(hal2_card_t *hal2)
+{
+	int i;
+
+	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+		hal2_write_mixer(hal2, i, 100 | (100 << 8));
+		
+}
+
+static int hal2_mixer_ioctl(hal2_card_t *hal2, unsigned int cmd, 
+			    unsigned long arg)
+{
+	int val;
+
+        if (cmd == SOUND_MIXER_INFO) {
+		mixer_info info;
+		
+		strncpy(info.id, hal2str, sizeof(info.id));
+		strncpy(info.name, hal2str, sizeof(info.name));
+		info.modify_counter = hal2->mixer.modcnt;
+		if (copy_to_user((void *)arg, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+	if (cmd == SOUND_OLD_MIXER_INFO) {
+		_old_mixer_info info;
+		
+		strncpy(info.id, hal2str, sizeof(info.id));
+		strncpy(info.name, hal2str, sizeof(info.name));
+		if (copy_to_user((void *)arg, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+	if (cmd == OSS_GETVERSION)
+		return put_user(SOUND_VERSION, (int *)arg);
+
+	if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int))
+                return -EINVAL;
+
+        if (_IOC_DIR(cmd) == _IOC_READ) {
+                switch (_IOC_NR(cmd)) {
+		/* Give the current record source */
+		case SOUND_MIXER_RECSRC:
+			val = 0;	/* FIXME */
+			break;
+		/* Give the supported mixers, all of them support stereo */
+                case SOUND_MIXER_DEVMASK:
+                case SOUND_MIXER_STEREODEVS: {
+			int i;
+			
+			for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+				if (mixtable[i].avail)
+					val |= 1 << i;
+			break;
+			}
+		/* Arg contains a bit for each supported recording source */
+                case SOUND_MIXER_RECMASK:
+			val = 0;
+			break;
+                case SOUND_MIXER_CAPS:
+			val = 0;
+			break;
+		/* Read a specific mixer */
+		default: {
+			int i = _IOC_NR(cmd);
+			
+			if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].avail)
+				return -EINVAL;
+			val = hal2->mixer.volume[mixtable[i].idx];
+			break;
+			}
+		}
+		return put_user(val, (int *)arg);
+	}
+	
+        if (_IOC_DIR(cmd) != (_IOC_WRITE|_IOC_READ))
+		return -EINVAL;
+	
+	hal2->mixer.modcnt++;
+
+	if (get_user(val, (int *)arg))
+		return -EFAULT;
+
+	switch (_IOC_NR(cmd)) {
+	/* Arg contains a bit for each recording source */
+	case SOUND_MIXER_RECSRC:
+		return 0;	/* FIXME */
+	default:
+		return hal2_write_mixer(hal2, _IOC_NR(cmd), val);
+	}
+
+	return 0;
+}
+
+static int hal2_open_mixdev(struct inode *inode, struct file *file)
+{
+	hal2_card_t *hal2 = hal2_mixer_find_card(MINOR(inode->i_rdev));
+
+	if (hal2) {
+		file->private_data = hal2;
+		return 0;
+	}
+	return -ENODEV;
+}
+
+static int hal2_release_mixdev(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static int hal2_ioctl_mixdev(struct inode *inode, struct file *file,
+			     unsigned int cmd, unsigned long arg)
+{
+	return hal2_mixer_ioctl((hal2_card_t *)file->private_data, cmd, arg);
+}
+
+
+static int hal2_ioctl(struct inode *inode, struct file *file, 
+		      unsigned int cmd, unsigned long arg)
+{
+	int val;
+	hal2_card_t *hal2 = (hal2_card_t *) file->private_data;
+
+	switch (cmd) {
+	case OSS_GETVERSION:
+		return put_user(SOUND_VERSION, (int *)arg);
+		
+	case SNDCTL_DSP_SYNC:
+		if (file->f_mode & FMODE_WRITE)
+			return hal2_sync_dac(hal2);
+		return 0;
+		
+	case SNDCTL_DSP_SETDUPLEX:
+		return 0;
+
+	case SNDCTL_DSP_GETCAPS:
+		return put_user(DSP_CAP_DUPLEX | DSP_CAP_MULTI, (int *)arg);
+		
+	case SNDCTL_DSP_RESET:
+		if (file->f_mode & FMODE_READ) {
+			hal2_stop_adc(hal2);
+			hal2_reset_adc_pointer(hal2);
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			hal2_stop_dac(hal2);
+			hal2_reset_dac_pointer(hal2);
+		}
+		return 0;
+
+ 	case SNDCTL_DSP_SPEED:
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (file->f_mode & FMODE_READ) {
+			hal2_stop_adc(hal2);
+			val = hal2_compute_rate(&hal2->adc, val);
+			hal2->adc.sample_rate = val;
+			hal2_set_adc_rate(hal2);
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			hal2_stop_dac(hal2);
+			val = hal2_compute_rate(&hal2->dac, val);
+			hal2->dac.sample_rate = val;
+			hal2_set_dac_rate(hal2);
+		}
+		return put_user(val, (int *)arg);
+		
+	case SNDCTL_DSP_STEREO:
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (file->f_mode & FMODE_READ) {
+			hal2_stop_adc(hal2);
+			hal2->adc.voices = (val) ? 2 : 1;
+			hal2_setup_adc(hal2);
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			hal2_stop_dac(hal2);
+			hal2->dac.voices = (val) ? 2 : 1;
+			hal2_setup_dac(hal2);
+                }
+		return 0;
+
+	case SNDCTL_DSP_CHANNELS:
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (val != 0) {
+			if (file->f_mode & FMODE_READ) {
+				hal2_stop_adc(hal2);
+				hal2->adc.voices = (val == 1) ? 1 : 2;
+				hal2_setup_adc(hal2);
+			}
+			if (file->f_mode & FMODE_WRITE) {
+				hal2_stop_dac(hal2);
+				hal2->dac.voices = (val == 1) ? 1 : 2;
+				hal2_setup_dac(hal2);
+			}
+		}
+		val = -EINVAL;
+		if (file->f_mode & FMODE_READ)
+			val = hal2->adc.voices;
+		if (file->f_mode & FMODE_WRITE)
+			val = hal2->dac.voices;
+		return put_user(val, (int *)arg);
+		
+	case SNDCTL_DSP_GETFMTS: /* Returns a mask */
+                return put_user(H2_SUPPORTED_FORMATS, (int *)arg);
+		
+	case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		if (val != AFMT_QUERY) {
+			if (!(val & H2_SUPPORTED_FORMATS))
+				return -EINVAL;
+			if (file->f_mode & FMODE_READ) {
+				hal2_stop_adc(hal2);
+				hal2->adc.format = val;
+				hal2_setup_adc(hal2);
+			}
+			if (file->f_mode & FMODE_WRITE) {
+				hal2_stop_dac(hal2);
+				hal2->dac.format = val;
+				hal2_setup_dac(hal2);
+			}
+		} else {
+			val = -EINVAL;
+			if (file->f_mode & FMODE_READ)
+				val = hal2->adc.format;
+			if (file->f_mode & FMODE_WRITE)
+				val = hal2->dac.format;
+		}
+		return put_user(val, (int *)arg);
+		
+	case SNDCTL_DSP_POST:
+		return 0;
+
+	case SNDCTL_DSP_GETOSPACE: {
+		unsigned long flags;
+		audio_buf_info info;
+		hal2_buf_t *buf;
+		hal2_codec_t *dac = &hal2->dac;
+		
+		if (!(file->f_mode & FMODE_WRITE))
+			return -EINVAL;
+		
+		spin_lock_irqsave(&dac->lock, flags);
+		info.fragments = 0;
+		buf = dac->head;
+		while (buf->info.cnt == 0 && buf != dac->tail) {
+			info.fragments++;
+			buf = buf->info.next;
+		}
+		spin_unlock_irqrestore(&dac->lock, flags);
+		
+		info.fragstotal = obuffers;
+		info.fragsize = H2_BUFFER_SIZE;
+                info.bytes = info.fragsize * info.fragments;
+
+		return copy_to_user((void *)arg, &info, sizeof(info)) ? -EFAULT : 0;
+	}
+			   
+	case SNDCTL_DSP_GETISPACE: {
+		unsigned long flags;
+		audio_buf_info info;
+		hal2_buf_t *buf;
+		hal2_codec_t *adc = &hal2->adc;
+			
+		if (!(file->f_mode & FMODE_READ))
+			return -EINVAL;
+		
+		spin_lock_irqsave(&adc->lock, flags);
+		info.fragments = 0;
+		info.bytes = 0;
+		buf = adc->tail;
+		while (buf->info.cnt > 0 && buf != adc->head) {
+			info.fragments++;
+			info.bytes += buf->info.cnt;
+			buf = buf->info.next;
+		}
+		spin_unlock_irqrestore(&adc->lock, flags);
+
+		info.fragstotal = ibuffers;
+		info.fragsize = H2_BUFFER_SIZE;
+		
+		return copy_to_user((void *)arg, &info, sizeof(info)) ? -EFAULT : 0;
+	}
+
+	case SNDCTL_DSP_NONBLOCK:
+		file->f_flags |= O_NONBLOCK;
+		return 0;
+		
+	case SNDCTL_DSP_GETBLKSIZE:
+		return put_user(H2_BUFFER_SIZE, (int *)arg);
+	
+	case SNDCTL_DSP_SETFRAGMENT:
+		return 0;
+
+	case SOUND_PCM_READ_RATE:
+		val = -EINVAL;
+		if (file->f_mode & FMODE_READ)
+			val = hal2->adc.sample_rate;
+		if (file->f_mode & FMODE_WRITE)
+			val = hal2->dac.sample_rate;
+		return put_user(val, (int *)arg);
+
+	case SOUND_PCM_READ_CHANNELS:
+		val = -EINVAL;
+		if (file->f_mode & FMODE_READ)
+			val = hal2->adc.voices;
+		if (file->f_mode & FMODE_WRITE)
+			val = hal2->dac.voices;
+		return put_user(val, (int *)arg);
+
+	case SOUND_PCM_READ_BITS:
+		val = 16;
+		return put_user(val, (int *)arg);
+	}
+	
+	return hal2_mixer_ioctl(hal2, cmd, arg);
+}
+
+static ssize_t hal2_read(struct file *file, char *buffer,
+			 size_t count, loff_t *ppos)
+{
+	ssize_t err;
+	hal2_card_t *hal2 = (hal2_card_t *) file->private_data;
+	hal2_codec_t *adc = &hal2->adc;
+
+	if (count == 0)
+		return 0;
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+	
+	down(&adc->sem);
+	
+	if (file->f_flags & O_NONBLOCK) {
+		err = hal2_get_buffer(hal2, buffer, count);
+		err = err == 0 ? -EAGAIN : err;
+	} else {
+		do {
+			/* ~10% longer */
+			signed long timeout = 1000 * H2_BUFFER_SIZE *
+				2 * adc->voices * HZ / adc->sample_rate / 900;
+			DECLARE_WAITQUEUE(wait, current);
+			ssize_t cnt = 0;
+			
+			err = hal2_get_buffer(hal2, buffer, count);
+			if (err > 0) {
+				count -= err;
+				cnt += err;
+				buffer += err;
+				err = cnt;
+			}
+			if (count > 0 && err >= 0) {
+				add_wait_queue(&adc->dma_wait, &wait);
+				set_current_state(TASK_INTERRUPTIBLE);
+				/* Well, it is possible, that interrupt already
+				 * arrived. Hmm, shit happens, we have one more
+				 * buffer filled ;) */
+				if (!schedule_timeout(timeout))
+					/* We may get bogus timeout when system
+					 * is heavily loaded */
+					if (!adc->tail->info.cnt) {
+						printk("HAL2: timeout...\n");
+						hal2_stop_adc(hal2);
+						hal2_reset_adc_pointer(hal2);
+						err = -EAGAIN;
+					}
+				if (signal_pending(current))
+					err = -ERESTARTSYS;
+				remove_wait_queue(&adc->dma_wait, &wait);
+			}
+		} while (count > 0 && err >= 0);
+	
+	}
+	
+	up(&adc->sem);
+	
+	return err;
+}
+
+static ssize_t hal2_write(struct file *file, const char *buffer,
+			  size_t count, loff_t *ppos)
+{
+	ssize_t err;
+	char *buf = (char*) buffer;
+	hal2_card_t *hal2 = (hal2_card_t *) file->private_data;
+	hal2_codec_t *dac = &hal2->dac;
+
+	if (count == 0)
+		return 0;
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+
+	down(&dac->sem);
+
+	if (file->f_flags & O_NONBLOCK) {
+		err = hal2_add_buffer(hal2, buf, count);
+		err = err == 0 ? -EAGAIN : err;
+	} else {
+		do {
+			/* ~10% longer */
+			signed long timeout = 1000 * H2_BUFFER_SIZE *
+				2 * dac->voices * HZ / dac->sample_rate / 900;
+			DECLARE_WAITQUEUE(wait, current);
+			ssize_t cnt = 0;
+			
+			err = hal2_add_buffer(hal2, buf, count);
+			if (err > 0) {
+				count -= err;
+				cnt += err;
+				buf += err;
+				err = cnt;
+			}
+			if (count > 0 && err >= 0) {
+				add_wait_queue(&dac->dma_wait, &wait);
+				set_current_state(TASK_INTERRUPTIBLE);
+				/* Well, it is possible, that interrupt already
+				 * arrived. Hmm, shit happens, we have one more
+				 * buffer free ;) */
+				if (!schedule_timeout(timeout))
+					/* We may get bogus timeout when system
+					 * is heavily loaded */
+					if (dac->head->info.cnt) {
+						printk("HAL2: timeout...\n");
+						hal2_stop_dac(hal2);
+						hal2_reset_dac_pointer(hal2);
+						err = -EAGAIN;
+					}
+				if (signal_pending(current))
+					err = -ERESTARTSYS;
+				remove_wait_queue(&dac->dma_wait, &wait);
+			}
+		} while (count > 0 && err >= 0);
+	}
+	
+	up(&dac->sem);
+
+	return err;
+}
+
+static unsigned int hal2_poll(struct file *file, struct poll_table_struct *wait)
+{
+	unsigned long flags;
+	unsigned int mask = 0;
+	hal2_card_t *hal2 = (hal2_card_t *) file->private_data;
+
+	if (file->f_mode & FMODE_READ) {
+		hal2_codec_t *adc = &hal2->adc;
+		
+		poll_wait(file, &hal2->adc.dma_wait, wait);
+		spin_lock_irqsave(&adc->lock, flags);
+		if (adc->tail->info.cnt > 0)
+			mask |= POLLIN;
+		spin_unlock_irqrestore(&adc->lock, flags);
+	}
+	
+	if (file->f_mode & FMODE_WRITE) {
+		hal2_codec_t *dac = &hal2->dac;
+		
+		poll_wait(file, &dac->dma_wait, wait);
+		spin_lock_irqsave(&dac->lock, flags);
+		if (dac->head->info.cnt == 0)
+			mask |= POLLOUT;
+		spin_unlock_irqrestore(&dac->lock, flags);
+	}
+	
+	return mask;
+}
+
+static int hal2_open(struct inode *inode, struct file *file)
+{
+	int err;
+	hal2_card_t *hal2 = hal2_dsp_find_card(MINOR(inode->i_rdev));
+
+	DEBUG("opening audio device.\n");
+
+	if (!hal2) {
+		printk("HAL2: Whee?! Open door and go away!\n");
+		return -ENODEV;
+	}
+	file->private_data = hal2;
+
+	if (file->f_mode & FMODE_READ) {
+		if (hal2->adc.usecount)
+			return -EBUSY;
+		
+		/* OSS spec wanted us to use 8 bit, 8 kHz mono by default,
+		 * but HAL2 can't do 8bit audio */
+		hal2->adc.format = AFMT_S16_BE;
+		hal2->adc.voices = 1;
+		hal2->adc.sample_rate = hal2_compute_rate(&hal2->adc, 8000);
+		hal2_set_adc_rate(hal2);
+
+		/* alloc DMA buffers */
+		err = hal2_alloc_adc_dmabuf(hal2);
+		if (err)
+			return err;
+		hal2_setup_adc(hal2);
+
+		hal2->adc.usecount++;
+	}
+
+	if (file->f_mode & FMODE_WRITE) {
+		if (hal2->dac.usecount)
+			return -EBUSY;
+
+		hal2->dac.format = AFMT_S16_BE;
+		hal2->dac.voices = 1;
+		hal2->dac.sample_rate = hal2_compute_rate(&hal2->dac, 8000);
+		hal2_set_dac_rate(hal2);
+
+		/* alloc DMA buffers */
+		err = hal2_alloc_dac_dmabuf(hal2);
+		if (err)
+			return err;
+		hal2_setup_dac(hal2);
+		
+		hal2->dac.usecount++;
+	}
+	
+	return 0;
+}
+
+static int hal2_release(struct inode *inode, struct file *file)
+{
+	hal2_card_t *hal2 = (hal2_card_t *) file->private_data;
+
+	if (file->f_mode & FMODE_READ) {
+		hal2_stop_adc(hal2);
+		hal2_free_adc_dmabuf(hal2);
+		hal2->adc.usecount--;
+	}
+
+	if (file->f_mode & FMODE_WRITE) {
+		hal2_sync_dac(hal2);
+		hal2_free_dac_dmabuf(hal2);
+		hal2->dac.usecount--;
+	}
+
+	return 0;
+}
+
+static struct file_operations hal2_audio_fops = {
+	owner:		THIS_MODULE,
+	llseek:		no_llseek,
+	read:		hal2_read,
+	write:		hal2_write,
+	poll:		hal2_poll,
+	ioctl:		hal2_ioctl,
+	open:		hal2_open,
+	release:	hal2_release,
+};
+
+static struct file_operations hal2_mixer_fops = {
+	owner:		THIS_MODULE,
+	llseek:		no_llseek,
+	ioctl:		hal2_ioctl_mixdev,
+	open:		hal2_open_mixdev,
+	release:	hal2_release_mixdev,
+};
+
+static int hal2_request_irq(hal2_card_t *hal2, int irq)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	save_and_cli(flags);
+	if (request_irq(irq, hal2_interrupt, SA_SHIRQ, hal2str, hal2)) {
+		printk(KERN_ERR "HAL2: Can't get irq %d\n", irq);
+		ret = -EAGAIN;
+	}
+	restore_flags(flags);
+	return ret;
+}
+
+static int hal2_alloc_resources(hal2_card_t *hal2, struct hpc3_regs *hpc3)
+{
+	hal2_pbus_t *pbus;
+
+	pbus = &hal2->dac.pbus;
+	pbus->pbusnr = 0;
+	pbus->pbus = &hpc3->pbdma[pbus->pbusnr];
+	/* The spec says that we should write 0x08248844 but that's WRONG. HAL2
+	 * does 8 bit DMA, not 16 bit even if it generates 16 bit audio. */
+	hpc3->pbus_dmacfgs[pbus->pbusnr][0] = 0x08208844;	/* Magic :-) */
+
+	pbus = &hal2->adc.pbus;
+	pbus->pbusnr = 1;
+	pbus->pbus = &hpc3->pbdma[pbus->pbusnr];
+	hpc3->pbus_dmacfgs[pbus->pbusnr][0] = 0x08208844;	/* Magic :-) */
+
+	return hal2_request_irq(hal2, SGI_HPCDMA_IRQ);
+}
+
+static void hal2_init_codec(hal2_codec_t *codec)
+{
+	init_waitqueue_head(&codec->dma_wait);
+	init_MUTEX(&codec->sem);
+	spin_lock_init(&codec->lock);
+}
+
+static void hal2_free_resources(hal2_card_t *hal2)
+{
+	free_irq(SGI_HPCDMA_IRQ, hal2);
+}
+
+static int hal2_detect(hal2_card_t *hal2)
+{
+	unsigned short board, major, minor;
+	unsigned short rev;
+
+	/* reset HAL2 */
+	hal2_isr_write(hal2, 0);
+
+	/* release reset */
+	hal2_isr_write(hal2, H2_ISR_GLOBAL_RESET_N | H2_ISR_CODEC_RESET_N);
+
+	hal2_i_write16(hal2, H2I_RELAY_C, H2I_RELAY_C_STATE); 
+
+	if ((rev = hal2_rev_look(hal2)) & H2_REV_AUDIO_PRESENT) {
+		DEBUG("HAL2: no device detected, rev: 0x%04hx\n", rev);
+		return -ENODEV;
+	}
+
+	board = (rev & H2_REV_BOARD_M) >> 12;
+	major = (rev & H2_REV_MAJOR_CHIP_M) >> 4;
+	minor = (rev & H2_REV_MINOR_CHIP_M);
+
+	printk("SGI HAL2 Processor revision %i.%i.%i detected\n",
+	       board, major, minor);
+
+	if (board != 4 || major != 1 || minor != 0) 
+		printk( "Other revision than 4.1.0 detected. "
+			"Your card is probably unsupported\n");
+
+	return 0;
+}
+
+static int hal2_init_card(hal2_card_t **phal2, struct hpc3_regs *hpc3,
+			  unsigned long hpc3_base)
+{
+	int ret = 0;
+	hal2_card_t *hal2;
+	
+	hal2 = (hal2_card_t *) kmalloc(sizeof(hal2_card_t), GFP_KERNEL);
+	if (!hal2)
+		return -ENOMEM;
+	memset(hal2, 0, sizeof(hal2_card_t));
+
+	hal2->ctl_regs = (hal2_ctl_regs_t *) KSEG1ADDR(hpc3_base + H2_CTL_PIO);
+	hal2->aes_regs = (hal2_aes_regs_t *) KSEG1ADDR(hpc3_base + H2_AES_PIO);
+	hal2->vol_regs = (hal2_vol_regs_t *) KSEG1ADDR(hpc3_base + H2_VOL_PIO);
+	hal2->syn_regs = (hal2_syn_regs_t *) KSEG1ADDR(hpc3_base + H2_SYN_PIO);
+
+	if (hal2_detect(hal2) < 0) {
+		printk("HAL2 audio processor not found\n");
+		ret = -ENODEV;
+		goto fail1;
+	}
+
+	hal2_init_codec(&hal2->dac);
+	hal2_init_codec(&hal2->adc);
+
+	ret = hal2_alloc_resources(hal2, hpc3);
+	if (ret)
+		goto fail1;
+	
+	hal2_init_mixer(hal2);
+
+	hal2->dev_dsp = register_sound_dsp(&hal2_audio_fops, -1);
+	if (hal2->dev_dsp < 0) {
+		ret = hal2->dev_dsp;
+		goto fail2;
+	}
+
+	hal2->dev_mixer = register_sound_mixer(&hal2_mixer_fops, -1);
+	if (hal2->dev_mixer < 0) {
+		ret = hal2->dev_mixer;
+		goto fail3;
+	}
+	
+	*phal2 = hal2;
+	return 0;
+fail3:
+	unregister_sound_dsp(hal2->dev_dsp);
+fail2:
+	hal2_free_resources(hal2);
+fail1:
+	kfree(hal2);
+	
+	return ret;
+}
+
+/* 
+ * We are assuming only one HAL2 card. If you ever meet machine with more than
+ * one, tell immediately about it to someone. Preferably to me. --ladis
+ */
+static int __init init_hal2(void)
+{
+	int i;
+
+	for (i = 0; i < MAXCARDS; i++)
+		hal2_card[i] = NULL;
+
+	return hal2_init_card(&hal2_card[0], hpc3c0, HPC3_CHIP0_PBASE);
+}
+
+static void __exit exit_hal2(void)
+{
+	int i;
+	
+	for (i = 0; i < MAXCARDS; i++)
+		if (hal2_card[i]) {
+			hal2_free_resources(hal2_card[i]);
+			unregister_sound_dsp(hal2_card[i]->dev_dsp);
+			unregister_sound_mixer(hal2_card[i]->dev_mixer);
+			kfree(hal2_card[i]);
+	}
+}
+
+module_init(init_hal2);
+module_exit(exit_hal2);
+
+MODULE_DESCRIPTION("OSS compatible driver for SGI HAL2 audio");
+MODULE_AUTHOR("Ladislav Michl");
+MODULE_LICENSE("GPL");
diff -Nru a/sound/oss/hal2.h b/sound/oss/hal2.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/sound/oss/hal2.h	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,328 @@
+#ifndef __HAL2_H
+#define __HAL2_H
+
+/*
+ *  Driver for HAL2 sound processors
+ *  Copyright (c) 1999 Ulf Carlsson <ulfc@bun.falkenberg.se>
+ *  Copyright (c) 2001 Ladislav Michl <ladis@psi.cz>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as 
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <asm/addrspace.h>
+#include <asm/sgi/sgihpc.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#define H2_HAL2_BASE		0x58000
+#define H2_CTL_PIO		(H2_HAL2_BASE + 0 * 0x400)
+#define H2_AES_PIO		(H2_HAL2_BASE + 1 * 0x400)
+#define H2_VOL_PIO		(H2_HAL2_BASE + 2 * 0x400)
+#define H2_SYN_PIO		(H2_HAL2_BASE + 3 * 0x400)
+
+/* Indirect status register */
+
+#define H2_ISR_TSTATUS		0x01	/* RO: transaction status 1=busy */
+#define H2_ISR_USTATUS		0x02	/* RO: utime status bit 1=armed */
+#define H2_ISR_QUAD_MODE	0x04	/* codec mode 0=indigo 1=quad */
+#define H2_ISR_GLOBAL_RESET_N	0x08	/* chip global reset 0=reset */
+#define H2_ISR_CODEC_RESET_N	0x10	/* codec/synth reset 0=reset  */
+
+/* Revision register */
+
+#define H2_REV_AUDIO_PRESENT	0x8000	/* RO: audio present 0=present */
+#define H2_REV_BOARD_M		0x7000	/* RO: bits 14:12, board revision */
+#define H2_REV_MAJOR_CHIP_M	0x00F0	/* RO: bits 7:4, major chip revision */
+#define H2_REV_MINOR_CHIP_M	0x000F	/* RO: bits 3:0, minor chip revision */
+
+/* Indirect address register */
+
+/*
+ * Address of indirect internal register to be accessed. A write to this
+ * register initiates read or write access to the indirect registers in the
+ * HAL2. Note that there af four indirect data registers for write access to
+ * registers larger than 16 byte.
+ */
+
+#define H2_IAR_TYPE_M		0xF000	/* bits 15:12, type of functional */
+					/* block the register resides in */
+					/* 1=DMA Port */
+					/* 9=Global DMA Control */
+					/* 2=Bresenham */
+					/* 3=Unix Timer */
+#define H2_IAR_NUM_M		0x0F00	/* bits 11:8 instance of the */
+					/* blockin which the indirect */
+					/* register resides */
+					/* If IAR_TYPE_M=DMA Port: */
+					/* 1=Synth In */
+					/* 2=AES In */
+					/* 3=AES Out */
+					/* 4=DAC Out */
+					/* 5=ADC Out */
+					/* 6=Synth Control */
+					/* If IAR_TYPE_M=Global DMA Control: */
+					/* 1=Control */
+					/* If IAR_TYPE_M=Bresenham: */
+					/* 1=Bresenham Clock Gen 1 */
+					/* 2=Bresenham Clock Gen 2 */
+					/* 3=Bresenham Clock Gen 3 */
+					/* If IAR_TYPE_M=Unix Timer: */
+					/* 1=Unix Timer */
+#define H2_IAR_ACCESS_SELECT	0x0080	/* 1=read 0=write */
+#define H2_IAR_PARAM		0x000C	/* Parameter Select */
+#define H2_IAR_RB_INDEX_M	0x0003	/* Read Back Index */
+					/* 00:word0 */
+					/* 01:word1 */
+					/* 10:word2 */
+					/* 11:word3 */
+/*
+ * HAL2 internal addressing
+ *
+ * The HAL2 has "indirect registers" (idr) which are accessed by writing to the
+ * Indirect Data registers. Write the address to the Indirect Address register
+ * to transfer the data.
+ *
+ * We define the H2IR_* to the read address and H2IW_* to the write address and
+ * H2I_* to be fields in whatever register is referred to.
+ *
+ * When we write to indirect registers which are larger than one word (16 bit)
+ * we have to fill more than one indirect register before writing. When we read
+ * back however we have to read several times, each time with different Read
+ * Back Indexes (there are defs for doing this easily).
+ */
+
+/*
+ * Relay Control
+ */
+#define H2I_RELAY_C		0x9100
+#define H2I_RELAY_C_STATE	0x01		/* state of RELAY pin signal */
+
+/* DMA port enable */
+
+#define H2I_DMA_PORT_EN		0x9104
+#define H2I_DMA_PORT_EN_SY_IN	0x01		/* Synth_in DMA port */
+#define H2I_DMA_PORT_EN_AESRX	0x02		/* AES receiver DMA port */
+#define H2I_DMA_PORT_EN_AESTX	0x04		/* AES transmitter DMA port */
+#define H2I_DMA_PORT_EN_CODECTX	0x08		/* CODEC transmit DMA port */
+#define H2I_DMA_PORT_EN_CODECR	0x10		/* CODEC receive DMA port */
+
+#define H2I_DMA_END		0x9108 		/* global dma endian select */
+#define H2I_DMA_END_SY_IN	0x01		/* Synth_in DMA port */
+#define H2I_DMA_END_AESRX	0x02		/* AES receiver DMA port */
+#define H2I_DMA_END_AESTX	0x04		/* AES transmitter DMA port */
+#define H2I_DMA_END_CODECTX	0x08		/* CODEC transmit DMA port */
+#define H2I_DMA_END_CODECR	0x10		/* CODEC receive DMA port */
+						/* 0=b_end 1=l_end */
+
+#define H2I_DMA_DRV		0x910C  	/* global PBUS DMA enable */
+
+#define H2I_SYNTH_C		0x1104		/* Synth DMA control */
+
+#define H2I_AESRX_C		0x1204	 	/* AES RX dma control */
+
+#define H2I_C_TS_EN		0x20		/* Timestamp enable */
+#define H2I_C_TS_FRMT		0x40		/* Timestamp format */
+#define H2I_C_NAUDIO		0x80		/* Sign extend */
+
+/* AESRX CTL, 16 bit */
+
+#define H2I_AESTX_C		0x1304		/* AES TX DMA control */
+#define H2I_AESTX_C_CLKID_SHIFT	3		/* Bresenham Clock Gen 1-3 */
+#define H2I_AESTX_C_CLKID_M	0x18
+#define H2I_AESTX_C_DATAT_SHIFT	8		/* 1=mono 2=stereo (3=quad) */
+#define H2I_AESTX_C_DATAT_M	0x300
+
+/* CODEC registers */
+
+#define H2I_DAC_C1		0x1404 		/* DAC DMA control, 16 bit */
+#define H2I_DAC_C2		0x1408		/* DAC DMA control, 32 bit */
+#define H2I_ADC_C1		0x1504 		/* ADC DMA control, 16 bit */
+#define H2I_ADC_C2		0x1508		/* ADC DMA control, 32 bit */
+
+/* Bits in CTL1 register */
+
+#define H2I_C1_DMA_SHIFT	0		/* DMA channel */
+#define H2I_C1_DMA_M		0x7
+#define H2I_C1_CLKID_SHIFT	3		/* Bresenham Clock Gen 1-3 */
+#define H2I_C1_CLKID_M		0x18
+#define H2I_C1_DATAT_SHIFT	8		/* 1=mono 2=stereo (3=quad) */
+#define H2I_C1_DATAT_M		0x300
+
+/* Bits in CTL2 register */
+
+#define H2I_C2_R_GAIN_SHIFT	0		/* right a/d input gain */	
+#define H2I_C2_R_GAIN_M		0xf	
+#define H2I_C2_L_GAIN_SHIFT	4		/* left a/d input gain */
+#define H2I_C2_L_GAIN_M		0xf0
+#define H2I_C2_R_SEL		0x100		/* right input select */
+#define H2I_C2_L_SEL		0x200		/* left input select */
+#define H2I_C2_MUTE		0x400		/* mute */
+#define H2I_C2_DO1		0x00010000	/* digital output port bit 0 */
+#define H2I_C2_DO2		0x00020000	/* digital output port bit 1 */
+#define H2I_C2_R_ATT_SHIFT	18		/* right d/a output - */
+#define H2I_C2_R_ATT_M		0x007c0000	/* attenuation */
+#define H2I_C2_L_ATT_SHIFT	23		/* left d/a output - */
+#define H2I_C2_L_ATT_M		0x0f800000	/* attenuation */
+
+#define H2I_SYNTH_MAP_C		0x1104		/* synth dma handshake ctrl */
+
+/* Clock generator CTL 1, 16 bit */
+
+#define H2I_BRES1_C1		0x2104
+#define H2I_BRES2_C1		0x2204
+#define H2I_BRES3_C1		0x2304
+
+#define H2I_BRES_C1_SHIFT	0		/* 0=48.0 1=44.1 2=aes_rx */
+#define H2I_BRES_C1_M		0x03
+				
+/* Clock generator CTL 2, 32 bit */
+
+#define H2I_BRES1_C2		0x2108
+#define H2I_BRES2_C2		0x2208
+#define H2I_BRES3_C2		0x2308
+
+#define H2I_BRES_C2_INC_SHIFT	0		/* increment value */
+#define H2I_BRES_C2_INC_M	0xffff
+#define H2I_BRES_C2_MOD_SHIFT	16		/* modcontrol value */
+#define H2I_BRES_C2_MOD_M	0xffff0000	/* modctrl=0xffff&(modinc-1) */
+
+/* Unix timer, 64 bit */
+
+#define H2I_UTIME		0x3104
+#define H2I_UTIME_0_LD		0xffff		/* microseconds, LSB's */
+#define H2I_UTIME_1_LD0		0x0f		/* microseconds, MSB's */
+#define H2I_UTIME_1_LD1		0xf0		/* tenths of microseconds */
+#define H2I_UTIME_2_LD		0xffff		/* seconds, LSB's */
+#define H2I_UTIME_3_LD		0xffff		/* seconds, MSB's */
+
+typedef volatile u32 hal2_reg_t;
+
+typedef struct stru_hal2_ctl_regs hal2_ctl_regs_t;
+struct stru_hal2_ctl_regs {
+	hal2_reg_t _unused0[4];
+	hal2_reg_t isr;			/* 0x10 Status Register */
+	hal2_reg_t _unused1[3];
+	hal2_reg_t rev;			/* 0x20 Revision Register */
+	hal2_reg_t _unused2[3];
+	hal2_reg_t iar;			/* 0x30 Indirect Address Register */
+	hal2_reg_t _unused3[3];
+	hal2_reg_t idr0;		/* 0x40 Indirect Data Register 0 */
+	hal2_reg_t _unused4[3];
+	hal2_reg_t idr1;		/* 0x50 Indirect Data Register 1 */
+	hal2_reg_t _unused5[3];
+	hal2_reg_t idr2;		/* 0x60 Indirect Data Register 2 */
+	hal2_reg_t _unused6[3];
+	hal2_reg_t idr3;		/* 0x70 Indirect Data Register 3 */
+};
+
+typedef struct stru_hal2_aes_regs hal2_aes_regs_t;
+struct stru_hal2_aes_regs {
+	hal2_reg_t rx_stat[2];		/* Status registers */
+	hal2_reg_t rx_cr[2];		/* Control registers */
+	hal2_reg_t rx_ud[4];		/* User data window */
+	hal2_reg_t rx_st[24];		/* Channel status data */
+	
+	hal2_reg_t tx_stat[1];		/* Status register */
+	hal2_reg_t tx_cr[3];		/* Control registers */
+	hal2_reg_t tx_ud[4];		/* User data window */
+	hal2_reg_t tx_st[24];		/* Channel status data */
+};
+
+typedef struct stru_hal2_vol_regs hal2_vol_regs_t;
+struct stru_hal2_vol_regs {
+	hal2_reg_t right;		/* 0x00 Right volume */
+	hal2_reg_t left;		/* 0x04 Left volume */
+};
+
+typedef struct stru_hal2_syn_regs hal2_syn_regs_t;
+struct stru_hal2_syn_regs {
+	hal2_reg_t _unused0[2];
+	hal2_reg_t page;		/* DOC Page register */
+	hal2_reg_t regsel;		/* DOC Register selection */
+	hal2_reg_t dlow;		/* DOC Data low */
+	hal2_reg_t dhigh;		/* DOC Data high */
+	hal2_reg_t irq;			/* IRQ Status */
+	hal2_reg_t dram;		/* DRAM Access */
+};
+
+/* HAL2 specific structures */
+
+typedef struct stru_hal2_pbus hal2_pbus_t;
+struct stru_hal2_pbus {
+	struct hpc3_pbus_dmacregs *pbus;
+	int pbusnr;
+	unsigned int ctrl;		/* Current state of pbus->pbdma_ctrl */
+};
+
+typedef struct stru_hal2_binfo hal2_binfo_t;
+typedef struct stru_hal2_buffer hal2_buf_t;
+struct stru_hal2_binfo {
+	volatile struct hpc_dma_desc desc;
+	hal2_buf_t *next;		/* pointer to next buffer */
+	int cnt;			/* bytes in buffer */
+};
+#define H2_BUFFER_SIZE	(PAGE_SIZE - \
+		((sizeof(hal2_binfo_t) - 1) / 8 + 1) * 8)
+struct stru_hal2_buffer {
+	hal2_binfo_t info;
+	char data[H2_BUFFER_SIZE] __attribute__((aligned(8)));
+};
+
+typedef struct stru_hal2_codec hal2_codec_t;
+struct stru_hal2_codec {
+	hal2_buf_t *head;
+	hal2_buf_t *tail; 
+	hal2_pbus_t pbus;
+	unsigned int format;		/* Audio data format */
+	int voices;			/* mono/stereo */
+	unsigned int sample_rate;
+	unsigned int master;		/* Master frequency */
+	unsigned short mod;		/* MOD value */
+	unsigned short inc;		/* INC value */
+
+	wait_queue_head_t dma_wait;
+	spinlock_t lock;
+	struct semaphore sem;
+
+	int usecount;			/* recording and playback are 
+					 * independent */
+};
+
+#define H2_MIX_OUTPUT_ATT	0
+#define H2_MIX_INPUT_GAIN	1
+#define H2_MIXERS		2
+typedef struct stru_hal2_mixer hal2_mixer_t;
+struct stru_hal2_mixer {
+	int modcnt;
+	unsigned int volume[H2_MIXERS];
+};
+
+typedef struct stru_hal2_card hal2_card_t;
+struct stru_hal2_card {
+	int dev_dsp;			/* audio device */
+	int dev_mixer;			/* mixer device */
+	int dev_midi;			/* midi device */
+	
+	hal2_ctl_regs_t *ctl_regs;	/* HAL2 ctl registers */
+	hal2_aes_regs_t *aes_regs;	/* HAL2 vol registers */
+	hal2_vol_regs_t *vol_regs;	/* HAL2 aes registers */
+	hal2_syn_regs_t *syn_regs;	/* HAL2 syn registers */
+
+	hal2_codec_t dac;
+	hal2_codec_t adc;
+	hal2_mixer_t mixer;
+};
+
+#endif				/* __HAL2_H */
diff -Nru a/sound/oss/harmony.c b/sound/oss/harmony.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/sound/oss/harmony.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,1307 @@
+/*
+ 	drivers/sound/harmony.c 
+
+	This is a sound driver for ASP's and Lasi's Harmony sound chip
+	and is unlikely to be used for anything other than on a HP PA-RISC.
+
+	Harmony is found in HP 712s, 715/new and many other GSC based machines.
+	On older 715 machines you'll find the technically identical chip 
+	called 'Vivace'. Both Harmony and Vicace are supported by this driver.
+
+	Copyright 2000 (c) Linuxcare Canada, Alex deVries <alex@linuxcare.com>
+	Copyright 2000-2002 (c) Helge Deller <deller@gmx.de>
+	Copyright 2001 (c) Matthieu Delahaye <delahaym@esiee.fr>
+	Copyright 2001 (c) Jean-Christophe Vaugeois <vaugeoij@esiee.fr>
+
+				
+TODO:
+	- fix SNDCTL_DSP_GETOSPACE and SNDCTL_DSP_GETISPACE ioctls to
+		return the real values
+	- add private ioctl for selecting line- or microphone input
+		(only one of them is available at the same time)
+	- add module parameters
+	- implement mmap functionality
+	- implement gain meter ?
+	- ...
+*/
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+
+#include <asm/gsc.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+
+#include "sound_config.h"
+
+
+#define PFX "harmony: "
+#define HARMONY_VERSION "V0.9a"
+
+#undef DEBUG
+#ifdef DEBUG
+# define DPRINTK printk 
+#else
+# define DPRINTK(x,...)
+#endif
+
+
+#define MAX_BUFS 10		/* maximum number of rotating buffers */
+#define HARMONY_BUF_SIZE 4096	/* needs to be a multiple of PAGE_SIZE (4096)! */
+
+#define CNTL_C		0x80000000
+#define	CNTL_ST		0x00000020
+#define CNTL_44100	0x00000015	/* HARMONY_SR_44KHZ */
+#define CNTL_8000	0x00000008	/* HARMONY_SR_8KHZ */
+
+#define GAINCTL_HE	0x08000000
+#define GAINCTL_LE	0x04000000
+#define GAINCTL_SE	0x02000000
+
+#define DSTATUS_PN	0x00000200
+#define DSTATUS_RN	0x00000002
+
+#define DSTATUS_IE	0x80000000
+
+#define HARMONY_DF_16BIT_LINEAR	0
+#define HARMONY_DF_8BIT_ULAW	1
+#define HARMONY_DF_8BIT_ALAW	2
+
+#define HARMONY_SS_MONO		0
+#define HARMONY_SS_STEREO	1
+
+#define HARMONY_SR_8KHZ		0x08
+#define HARMONY_SR_16KHZ	0x09
+#define HARMONY_SR_27KHZ	0x0A
+#define HARMONY_SR_32KHZ	0x0B
+#define HARMONY_SR_48KHZ	0x0E
+#define HARMONY_SR_9KHZ		0x0F
+#define HARMONY_SR_5KHZ		0x10
+#define HARMONY_SR_11KHZ	0x11
+#define HARMONY_SR_18KHZ	0x12
+#define HARMONY_SR_22KHZ	0x13
+#define HARMONY_SR_37KHZ	0x14
+#define HARMONY_SR_44KHZ	0x15
+#define HARMONY_SR_33KHZ	0x16
+#define HARMONY_SR_6KHZ		0x17
+
+/*
+ * Some magics numbers used to auto-detect file formats
+ */
+
+#define HARMONY_MAGIC_8B_ULAW	1
+#define HARMONY_MAGIC_8B_ALAW	27
+#define HARMONY_MAGIC_16B_LINEAR 3
+#define HARMONY_MAGIC_MONO	1
+#define HARMONY_MAGIC_STEREO	2
+
+/*
+ * Channels Positions in mixer register
+ */
+
+#define GAIN_HE_SHIFT   27
+#define GAIN_HE_MASK    ( 1 << GAIN_HE_SHIFT) 
+#define GAIN_LE_SHIFT   26
+#define GAIN_LE_MASK    ( 1 << GAIN_LE_SHIFT) 
+#define GAIN_SE_SHIFT   25
+#define GAIN_SE_MASK    ( 1 << GAIN_SE_SHIFT) 
+#define GAIN_IS_SHIFT   24
+#define GAIN_IS_MASK    ( 1 << GAIN_IS_SHIFT) 
+#define GAIN_MA_SHIFT   20
+#define GAIN_MA_MASK    ( 0x0f << GAIN_MA_SHIFT) 
+#define GAIN_LI_SHIFT   16
+#define GAIN_LI_MASK    ( 0x0f << GAIN_LI_SHIFT) 
+#define GAIN_RI_SHIFT   12
+#define GAIN_RI_MASK    ( 0x0f << GAIN_RI_SHIFT) 
+#define GAIN_LO_SHIFT   6
+#define GAIN_LO_MASK    ( 0x3f << GAIN_LO_SHIFT) 
+#define GAIN_RO_SHIFT   0
+#define GAIN_RO_MASK    ( 0x3f << GAIN_RO_SHIFT) 
+
+
+#define MAX_OUTPUT_LEVEL (GAIN_RO_MASK >> GAIN_RO_SHIFT)
+#define MAX_INPUT_LEVEL  (GAIN_RI_MASK >> GAIN_RI_SHIFT)
+#define MAX_VOLUME_LEVEL (GAIN_MA_MASK >> GAIN_MA_SHIFT)
+
+/*
+ * Channels Mask in mixer register
+ */
+
+#define GAIN_TOTAL_SILENCE 0x00F00FFF
+#define GAIN_DEFAULT       0x0FF00000
+
+
+struct harmony_hpa {
+	u8	unused000;
+	u8	id;
+	u8	teleshare_id;
+	u8	unused003;
+	u32	reset;
+	u32	cntl;
+	u32	gainctl;
+	u32	pnxtadd;
+	u32	pcuradd;
+	u32	rnxtadd;
+	u32	rcuradd;
+	u32	dstatus;
+	u32	ov;
+	u32	pio;
+	u32	unused02c;
+	u32	unused030[3];
+	u32	diag;
+};
+
+struct harmony_dev {
+	int irq;
+	struct harmony_hpa *hpa;
+	u32 current_gain;
+	u8 data_format;		/* HARMONY_DF_xx_BIT_xxx */
+	u8 sample_rate;		/* HARMONY_SR_xx_KHZ */
+	u8 stereo_select;	/* HARMONY_SS_MONO or HARMONY_SS_STEREO */
+	int format_initialized;
+	u32 dac_rate;		/* 8000 ... 48000 (Hz) */
+	int suspended_playing;
+	int suspended_recording;
+	
+	int blocked_playing;
+	int blocked_recording;
+	
+	wait_queue_head_t wq_play, wq_record;
+	int first_filled_play;	/* first buffer containing data (next to play) */
+	int nb_filled_play; 
+	int play_offset;
+	int first_filled_record;
+	int nb_filled_record;
+		
+	int audio_open, mixer_open;
+	int dsp_unit, mixer_unit;
+
+	struct pci_dev *fake_pci_dev; /* The fake pci_dev needed for 
+					pci_* functions under ccio. */
+};
+
+
+static struct harmony_dev harmony;
+
+
+/*
+ * Dynamic sound buffer allocation and DMA memory
+ */
+
+struct harmony_buffer {
+	unsigned char *addr;
+	dma_addr_t dma_handle;
+	int dma_consistent;	/* Zero if pci_alloc_consistent() fails */
+	int len;
+};
+
+/*
+ * Harmony memory buffers
+ */
+
+static struct harmony_buffer played_buf, recorded_buf, silent, graveyard;
+
+
+#define CHECK_WBACK_INV_OFFSET(b,offset,len) \
+        do { if (!b.dma_consistent) \
+		dma_cache_wback_inv((unsigned long)b.addr+offset,len); \
+	} while (0) 
+
+	
+static int __init harmony_alloc_buffer(struct harmony_buffer *b, 
+		int buffer_count)
+{
+	b->len = buffer_count * HARMONY_BUF_SIZE;
+	b->addr = pci_alloc_consistent(harmony.fake_pci_dev, 
+			  b->len, &b->dma_handle);
+	if (b->addr && b->dma_handle) {
+		b->dma_consistent = 1;
+		DPRINTK(KERN_INFO PFX "consistent memory: 0x%lx, played_buf: 0x%lx\n",
+				(unsigned long)b->dma_handle, (unsigned long)b->addr);
+	} else {
+		b->dma_consistent = 0;
+		/* kmalloc()ed memory will HPMC on ccio machines ! */
+		b->addr = kmalloc(b->len, GFP_KERNEL);
+		if (!b->addr) {
+			printk(KERN_ERR PFX "couldn't allocate memory\n");
+			return -EBUSY;
+		}
+		b->dma_handle = __pa(b->addr);
+	}
+	return 0;
+}
+
+static void __exit harmony_free_buffer(struct harmony_buffer *b)
+{
+	if (!b->addr)
+		return;
+
+	if (b->dma_consistent)
+		pci_free_consistent(harmony.fake_pci_dev,
+				b->len, b->addr, b->dma_handle);
+	else
+		kfree(b->addr);
+
+	memset(b, 0, sizeof(*b));
+}
+
+
+
+/*
+ * Low-Level sound-chip programming
+ */
+
+static void __inline__ harmony_wait_CNTL(void)
+{
+	/* Wait until we're out of control mode */
+	while (gsc_readl(&harmony.hpa->cntl) & CNTL_C)
+		/* wait */ ;
+}
+
+
+static void harmony_update_control(void) 
+{
+	u32 default_cntl;
+	
+	/* Set CNTL */
+	default_cntl = (CNTL_C |  		/* The C bit */
+		(harmony.data_format << 6) |	/* Set the data format */
+		(harmony.stereo_select << 5) |	/* Stereo select */
+		(harmony.sample_rate));		/* Set sample rate */
+	harmony.format_initialized = 1;
+	
+	/* initialize CNTL */
+	gsc_writel(default_cntl, &harmony.hpa->cntl);
+}
+
+static void harmony_set_control(u8 data_format, u8 sample_rate, u8 stereo_select) 
+{
+	harmony.sample_rate = sample_rate;
+	harmony.data_format = data_format;
+	harmony.stereo_select = stereo_select;
+	harmony_update_control();
+}
+
+static void harmony_set_rate(u8 data_rate) 
+{
+	harmony.sample_rate = data_rate;
+	harmony_update_control();
+}
+
+static int harmony_detect_rate(int *freq)
+{
+	int newrate;
+	switch (*freq) {
+	case 8000:	newrate = HARMONY_SR_8KHZ;	break;
+	case 16000:	newrate = HARMONY_SR_16KHZ;	break; 
+	case 27428:	newrate = HARMONY_SR_27KHZ;	break; 
+	case 32000:	newrate = HARMONY_SR_32KHZ;	break; 
+	case 48000:	newrate = HARMONY_SR_48KHZ;	break; 
+	case 9600:	newrate = HARMONY_SR_9KHZ;	break; 
+	case 5125:	newrate = HARMONY_SR_5KHZ;	break; 
+	case 11025:	newrate = HARMONY_SR_11KHZ;	break; 
+	case 18900:	newrate = HARMONY_SR_18KHZ;	break; 
+	case 22050:	newrate = HARMONY_SR_22KHZ;	break; 
+	case 37800:	newrate = HARMONY_SR_37KHZ;	break; 
+	case 44100:	newrate = HARMONY_SR_44KHZ;	break; 
+	case 33075:	newrate = HARMONY_SR_33KHZ;	break; 
+	case 6615:	newrate = HARMONY_SR_6KHZ;	break; 
+	default:	newrate = HARMONY_SR_8KHZ; 
+			*freq = 8000;			break;
+	}
+	return newrate;
+}
+
+static void harmony_set_format(u8 data_format) 
+{
+	harmony.data_format = data_format;
+	harmony_update_control();
+}
+
+static void harmony_set_stereo(u8 stereo_select) 
+{
+	harmony.stereo_select = stereo_select;
+	harmony_update_control();
+}
+
+static void harmony_disable_interrupts(void) 
+{
+	harmony_wait_CNTL();
+	gsc_writel(0, &harmony.hpa->dstatus); 
+}
+
+static void harmony_enable_interrupts(void) 
+{
+	harmony_wait_CNTL();
+	gsc_writel(DSTATUS_IE, &harmony.hpa->dstatus); 
+}
+
+/*
+ * harmony_silence()
+ *
+ * This subroutine fills in a buffer starting at location start and
+ * silences for length bytes.  This references the current
+ * configuration of the audio format.
+ *
+ */
+
+static void harmony_silence(struct harmony_buffer *buffer, int start, int length) 
+{
+	u8 silence_char;
+
+	/* Despite what you hear, silence is different in
+	   different audio formats.  */
+	switch (harmony.data_format) {
+		case HARMONY_DF_8BIT_ULAW:	silence_char = 0x55; break;
+		case HARMONY_DF_8BIT_ALAW:	silence_char = 0xff; break;
+		case HARMONY_DF_16BIT_LINEAR:	/* fall through */
+		default:			silence_char = 0;
+	}
+
+	memset(buffer->addr+start, silence_char, length);
+}
+
+
+static int harmony_audio_open(struct inode *inode, struct file *file)
+{
+	if (harmony.audio_open) 
+		return -EBUSY;
+	
+	harmony.audio_open++;
+	harmony.suspended_playing = harmony.suspended_recording = 1;
+	harmony.blocked_playing   = harmony.blocked_recording   = 0;
+	harmony.first_filled_play = harmony.first_filled_record = 0;
+	harmony.nb_filled_play    = harmony.nb_filled_record    = 0;
+	harmony.play_offset = 0;
+	init_waitqueue_head(&harmony.wq_play);
+	init_waitqueue_head(&harmony.wq_record);
+	
+	/* Start off in a balanced mode. */
+	harmony_set_control(HARMONY_DF_8BIT_ULAW, HARMONY_SR_8KHZ, HARMONY_SS_MONO);
+	harmony_update_control();
+	harmony.format_initialized = 0;
+
+	/* Clear out all the buffers and flush to cache */
+	harmony_silence(&played_buf, 0, HARMONY_BUF_SIZE*MAX_BUFS);
+	CHECK_WBACK_INV_OFFSET(played_buf, 0, HARMONY_BUF_SIZE*MAX_BUFS);
+	
+	return 0;
+}
+
+/*
+ * Release (close) the audio device.
+ */
+
+static int harmony_audio_release(struct inode *inode, struct file *file)
+{
+	if (!harmony.audio_open) 
+		return -EBUSY;
+	
+	harmony.audio_open--;
+
+	return 0;
+}
+
+/*
+ * Read recorded data off the audio device.
+ */
+
+static ssize_t harmony_audio_read(struct file *file,
+                                char *buffer,
+                                size_t size_count,
+                                loff_t *ppos)
+{
+	int total_count = (int) size_count;
+	int count = 0;
+	int buf_to_read;
+
+	while (count<total_count) {
+		/* Wait until we're out of control mode */
+		harmony_wait_CNTL();
+		
+		/* Figure out which buffer to fill in */
+		if (harmony.nb_filled_record <= 2) {
+			harmony.blocked_recording = 1;
+		        if (harmony.suspended_recording) {
+				harmony.suspended_recording = 0;
+				harmony_enable_interrupts();
+			}
+							
+			interruptible_sleep_on(&harmony.wq_record);
+			harmony.blocked_recording = 0;
+		}
+		
+		if (harmony.nb_filled_record < 2)
+			return -EBUSY;
+		
+		buf_to_read = harmony.first_filled_record;
+
+		/* Copy the page to an aligned buffer */
+		if (copy_to_user(buffer+count, recorded_buf.addr +
+				 (HARMONY_BUF_SIZE*buf_to_read),
+				 HARMONY_BUF_SIZE)) {
+			count = -EFAULT;
+			break;
+		}
+		
+		harmony.nb_filled_record--;
+		harmony.first_filled_record++;
+		harmony.first_filled_record %= MAX_BUFS;
+				
+		count += HARMONY_BUF_SIZE;
+	}
+	return count;
+}
+
+
+
+
+/*
+ * Here is the place where we try to recognize file format.
+ * Sun/NeXT .au files begin with the string .snd
+ * At offset 12 is specified the encoding.
+ * At offset 16 is specified speed rate
+ * At Offset 20 is specified the numbers of voices
+ */
+
+#define four_bytes_to_u32(start) (file_header[start] << 24)|\
+                                  (file_header[start+1] << 16)|\
+                                  (file_header[start+2] << 8)|\
+                                  (file_header[start+3]);
+
+#define test_rate(tested,real_value,harmony_value) if ((tested)<=(real_value))\
+                                                    
+
+static int harmony_format_auto_detect(const char *buffer, int block_size)
+{
+	u8 file_header[24];
+	u32 start_string;
+	int ret = 0;
+	
+	if (block_size>24) {
+		if (copy_from_user(file_header, buffer, sizeof(file_header)))
+			ret = -EFAULT;
+			
+		start_string = four_bytes_to_u32(0);
+		
+		if ((file_header[4]==0) && (start_string==0x2E736E64)) {
+			u32 format;
+			u32 nb_voices;
+			u32 speed;
+			
+			format = four_bytes_to_u32(12);
+			nb_voices = four_bytes_to_u32(20);
+			speed = four_bytes_to_u32(16);
+			
+			switch (format) {
+			case HARMONY_MAGIC_8B_ULAW:
+				harmony.data_format = HARMONY_DF_8BIT_ULAW;
+				break;
+			case HARMONY_MAGIC_8B_ALAW:
+				harmony.data_format = HARMONY_DF_8BIT_ALAW;
+				break;
+			case HARMONY_MAGIC_16B_LINEAR:
+				harmony.data_format = HARMONY_DF_16BIT_LINEAR;
+				break;
+			default:
+				harmony_set_control(HARMONY_DF_16BIT_LINEAR,
+						HARMONY_SR_44KHZ, HARMONY_SS_STEREO);
+				goto out;
+			}
+			switch (nb_voices) {
+			case HARMONY_MAGIC_MONO:
+				harmony.stereo_select = HARMONY_SS_MONO;
+				break;
+			case HARMONY_MAGIC_STEREO:
+				harmony.stereo_select = HARMONY_SS_STEREO;
+				break;
+			default:
+				harmony.stereo_select = HARMONY_SS_MONO;
+				break;
+			}
+			harmony_set_rate(harmony_detect_rate(&speed));
+			harmony.dac_rate = speed;
+			goto out;
+		}
+	}
+	harmony_set_control(HARMONY_DF_8BIT_ULAW, HARMONY_SR_8KHZ, HARMONY_SS_MONO);
+out:
+	return ret;
+}
+#undef four_bytes_to_u32
+
+
+static ssize_t harmony_audio_write(struct file *file,
+                                 const char *buffer,
+                                 size_t size_count,
+                                 loff_t *ppos)
+{
+	int total_count = (int) size_count;
+	int count = 0;
+	int frame_size;
+	int buf_to_fill;
+
+	if (!harmony.format_initialized) {
+		if (harmony_format_auto_detect(buffer, total_count))
+			return -EFAULT;
+	}
+	
+	while (count<total_count) {
+		/* Wait until we're out of control mode */
+		harmony_wait_CNTL();
+
+		/* Figure out which buffer to fill in */
+		if (harmony.nb_filled_play+2 >= MAX_BUFS && !harmony.play_offset) {
+			harmony.blocked_playing = 1;
+			interruptible_sleep_on(&harmony.wq_play);
+			harmony.blocked_playing = 0;
+		}
+		if (harmony.nb_filled_play+2 >= MAX_BUFS && !harmony.play_offset)
+			return -EBUSY;
+		
+		
+		buf_to_fill = (harmony.first_filled_play+harmony.nb_filled_play); 
+		if (harmony.play_offset)
+			buf_to_fill--;
+		buf_to_fill %= MAX_BUFS;
+
+		/* Figure out the size of the frame */
+		if ((total_count-count) > HARMONY_BUF_SIZE - harmony.play_offset) {
+			frame_size = HARMONY_BUF_SIZE - harmony.play_offset;
+		} else {
+			frame_size = total_count - count;
+			/* Clear out the buffer, since there we'll only be 
+			   overlaying part of the old buffer with the new one */
+			harmony_silence(&played_buf, 
+				HARMONY_BUF_SIZE*buf_to_fill+frame_size+harmony.play_offset,
+				HARMONY_BUF_SIZE-frame_size-harmony.play_offset);
+		}
+
+		/* Copy the page to an aligned buffer */
+		if (copy_from_user(played_buf.addr +(HARMONY_BUF_SIZE*buf_to_fill) + harmony.play_offset, 
+				   buffer+count, frame_size))
+			return -EFAULT;
+		CHECK_WBACK_INV_OFFSET(played_buf, (HARMONY_BUF_SIZE*buf_to_fill + harmony.play_offset), 
+				frame_size);
+	
+		if (!harmony.play_offset)
+			harmony.nb_filled_play++;
+		
+		count += frame_size;
+		harmony.play_offset += frame_size;
+		harmony.play_offset %= HARMONY_BUF_SIZE;
+		if (harmony.suspended_playing && (harmony.nb_filled_play>=4))
+			harmony_enable_interrupts();
+	}
+	
+	return count;
+}
+
+static unsigned int harmony_audio_poll(struct file *file,
+                                     struct poll_table_struct *wait)
+{
+	unsigned int mask = 0;
+	
+	if (file->f_mode & FMODE_READ) {
+		if (!harmony.suspended_recording)
+			poll_wait(file, &harmony.wq_record, wait);
+		if (harmony.nb_filled_record)
+			mask |= POLLIN | POLLRDNORM;
+	}
+
+	if (file->f_mode & FMODE_WRITE) {
+		if (!harmony.suspended_playing)
+			poll_wait(file, &harmony.wq_play, wait);
+		if (harmony.nb_filled_play)
+			mask |= POLLOUT | POLLWRNORM;
+	}
+
+	return mask;
+}
+
+static int harmony_audio_ioctl(struct inode *inode,
+                                struct file *file,
+				unsigned int cmd,
+                                unsigned long arg)
+{
+	int ival, new_format;
+	int frag_size, frag_buf;
+	struct audio_buf_info info;
+	
+	switch (cmd) {
+	case OSS_GETVERSION:
+		return put_user(SOUND_VERSION, (int *) arg);
+
+	case SNDCTL_DSP_GETCAPS:
+		ival = DSP_CAP_DUPLEX;
+		return put_user(ival, (int *) arg);
+
+	case SNDCTL_DSP_GETFMTS:
+		ival = (AFMT_S16_BE | AFMT_MU_LAW | AFMT_A_LAW ); 
+		return put_user(ival, (int *) arg);
+	
+	case SNDCTL_DSP_SETFMT:
+		if (get_user(ival, (int *) arg)) 
+			return -EFAULT;
+		if (ival != AFMT_QUERY) {
+			switch (ival) {
+			case AFMT_MU_LAW:	new_format = HARMONY_DF_8BIT_ULAW; break;
+			case AFMT_A_LAW:	new_format = HARMONY_DF_8BIT_ALAW; break;
+			case AFMT_S16_LE:	/* fall through, but not really supported */
+			case AFMT_S16_BE:	new_format = HARMONY_DF_16BIT_LINEAR;
+						ival = AFMT_S16_BE;
+						break; 
+			default: {
+				DPRINTK(KERN_WARNING PFX 
+					"unsupported sound format 0x%04x requested.\n",
+					ival);
+				return -EINVAL;
+			}
+			}
+			harmony_set_format(new_format);
+		} else {
+			switch (harmony.data_format) {
+			case HARMONY_DF_8BIT_ULAW:	ival = AFMT_MU_LAW; break;
+			case HARMONY_DF_8BIT_ALAW:	ival = AFMT_A_LAW;  break;
+			case HARMONY_DF_16BIT_LINEAR:	ival = AFMT_U16_BE; break;
+			default: ival = 0;
+			}
+		}
+		return put_user(ival, (int *) arg);
+
+	case SOUND_PCM_READ_RATE:
+		ival = harmony.dac_rate;
+		return put_user(ival, (int *) arg);
+
+	case SNDCTL_DSP_SPEED:
+		if (get_user(ival, (int *) arg))
+			return -EFAULT;
+		harmony_set_rate(harmony_detect_rate(&ival));
+		harmony.dac_rate = ival;
+		return put_user(ival, (int*) arg);
+
+	case SNDCTL_DSP_STEREO:
+		if (get_user(ival, (int *) arg))
+			return -EFAULT;
+		if (ival != 0 && ival != 1)
+			return -EINVAL;
+		harmony_set_stereo(ival);
+		return put_user(ival, (int *) arg);
+
+	case SNDCTL_DSP_GETBLKSIZE:
+		ival = HARMONY_BUF_SIZE;
+		return put_user(ival, (int *) arg);
+		
+        case SNDCTL_DSP_NONBLOCK:
+                file->f_flags |= O_NONBLOCK;
+                return 0;
+
+        case SNDCTL_DSP_RESET:
+		if (!harmony.suspended_recording) {
+			/* TODO: stop_recording() */
+		}
+		return 0;
+
+	case SNDCTL_DSP_SETFRAGMENT:
+		if (get_user(ival, (int *)arg))
+			return -EFAULT;
+		frag_size = ival & 0xffff;
+		frag_buf = (ival>>16) & 0xffff;
+		/* TODO: We use hardcoded fragment sizes and numbers for now */
+		frag_size = 12;  /* 4096 == 2^12 */
+		frag_buf  = MAX_BUFS;
+		ival = (frag_buf << 16) + frag_size;
+		return put_user(ival, (int *) arg);
+		
+	case SNDCTL_DSP_GETOSPACE:
+		if (!(file->f_mode & FMODE_WRITE))
+			return -EINVAL;
+		info.fragstotal = MAX_BUFS;
+                info.fragments = MAX_BUFS - harmony.nb_filled_play;
+		info.fragsize = HARMONY_BUF_SIZE;
+                info.bytes = info.fragments * info.fragsize;
+		return copy_to_user((void *)arg, &info, sizeof(info));
+
+	case SNDCTL_DSP_GETISPACE:
+		if (!(file->f_mode & FMODE_READ))
+			return -EINVAL;
+		info.fragstotal = MAX_BUFS;
+                info.fragments = /*MAX_BUFS-*/ harmony.nb_filled_record;
+		info.fragsize = HARMONY_BUF_SIZE;
+                info.bytes = info.fragments * info.fragsize;
+		return copy_to_user((void *)arg, &info, sizeof(info));
+	
+	case SNDCTL_DSP_SYNC:
+		return 0;
+	}
+	
+	return -EINVAL;
+}
+
+
+/*
+ * harmony_interrupt()
+ *
+ * harmony interruption service routine
+ * 
+ */
+
+static irqreturn_t harmony_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+	u32 dstatus;
+	struct harmony_hpa *hpa;
+
+	/* Setup the hpa */
+	hpa = ((struct harmony_dev *)dev)->hpa;
+	harmony_wait_CNTL();
+
+	/* Read dstatus and pcuradd (the current address) */
+	dstatus = gsc_readl(&hpa->dstatus);
+	
+	/* Turn off interrupts */
+	harmony_disable_interrupts();
+	
+	/* Check if this is a request to get the next play buffer */
+	if (dstatus & DSTATUS_PN) {
+		if (!harmony.nb_filled_play) {
+			harmony.suspended_playing = 1;
+			gsc_writel((unsigned long)silent.dma_handle, &hpa->pnxtadd);
+						
+			if (!harmony.suspended_recording)
+				harmony_enable_interrupts();
+		} else {
+			harmony.suspended_playing = 0;
+			gsc_writel((unsigned long)played_buf.dma_handle + 
+					(HARMONY_BUF_SIZE*harmony.first_filled_play),
+					&hpa->pnxtadd);
+			harmony.first_filled_play++;
+			harmony.first_filled_play %= MAX_BUFS;
+			harmony.nb_filled_play--;
+			
+		       	harmony_enable_interrupts();
+		}
+		
+		if (harmony.blocked_playing)
+			wake_up_interruptible(&harmony.wq_play);
+	}
+	
+	/* Check if we're being asked to fill in a recording buffer */
+	if (dstatus & DSTATUS_RN) {
+		if((harmony.nb_filled_record+2>=MAX_BUFS) || harmony.suspended_recording)
+		{
+			harmony.nb_filled_record = 0;
+			harmony.first_filled_record = 0;
+			harmony.suspended_recording = 1;
+			gsc_writel((unsigned long)graveyard.dma_handle, &hpa->rnxtadd);
+			if (!harmony.suspended_playing)
+				harmony_enable_interrupts();
+		} else {
+			int buf_to_fill;
+			buf_to_fill = (harmony.first_filled_record+harmony.nb_filled_record) % MAX_BUFS;
+			CHECK_WBACK_INV_OFFSET(recorded_buf, HARMONY_BUF_SIZE*buf_to_fill, HARMONY_BUF_SIZE);
+			gsc_writel((unsigned long)recorded_buf.dma_handle +
+					HARMONY_BUF_SIZE*buf_to_fill,
+					&hpa->rnxtadd);
+			harmony.nb_filled_record++;
+			harmony_enable_interrupts();
+		}
+
+		if (harmony.blocked_recording && harmony.nb_filled_record>3)
+			wake_up_interruptible(&harmony.wq_record);
+	}
+	return IRQ_HANDLED;
+}
+
+/*
+ * Sound playing functions
+ */
+
+static struct file_operations harmony_audio_fops = {
+	owner:	THIS_MODULE,
+	llseek:	no_llseek,
+	read: 	harmony_audio_read,
+	write:	harmony_audio_write,
+	poll: 	harmony_audio_poll,
+	ioctl: 	harmony_audio_ioctl,
+	open: 	harmony_audio_open,
+	release:harmony_audio_release,
+};
+
+static int harmony_audio_init(void)
+{
+	/* Request that IRQ */
+	if (request_irq(harmony.irq, harmony_interrupt, 0 ,"harmony", &harmony)) {
+		printk(KERN_ERR PFX "Error requesting irq %d.\n", harmony.irq);
+		return -EFAULT;
+	}
+
+   	harmony.dsp_unit = register_sound_dsp(&harmony_audio_fops, -1);
+	if (harmony.dsp_unit < 0) {
+		printk(KERN_ERR PFX "Error registering dsp\n");
+		free_irq(harmony.irq, &harmony);
+		return -EFAULT;
+	}
+	
+	/* Clear the buffers so you don't end up with crap in the buffers. */ 
+	harmony_silence(&played_buf, 0, HARMONY_BUF_SIZE*MAX_BUFS);
+
+	/* Make sure this makes it to cache */
+	CHECK_WBACK_INV_OFFSET(played_buf, 0, HARMONY_BUF_SIZE*MAX_BUFS);
+
+	/* Clear out the silent buffer and flush to cache */
+	harmony_silence(&silent, 0, HARMONY_BUF_SIZE);
+	CHECK_WBACK_INV_OFFSET(silent, 0, HARMONY_BUF_SIZE);
+	
+	harmony.audio_open = 0;
+	
+	return 0;
+}
+
+
+/*
+ * mixer functions 
+ */
+
+static void harmony_mixer_set_gain(void)
+{
+	harmony_wait_CNTL();
+	gsc_writel(harmony.current_gain, &harmony.hpa->gainctl);
+}
+
+/* 
+ *  Read gain of selected channel.
+ *  The OSS rate is from 0 (silent) to 100 -> need some conversions
+ *
+ *  The harmony gain are attenuation for output and monitor gain.
+ *                   is amplifaction for input gain
+ */
+#define to_harmony_level(level,max) ((level)*max/100)
+#define to_oss_level(level,max) ((level)*100/max)
+
+static int harmony_mixer_get_level(int channel)
+{
+	int left_level;
+	int right_level;
+
+	switch (channel) {
+		case SOUND_MIXER_OGAIN:
+			left_level  = (harmony.current_gain & GAIN_LO_MASK) >> GAIN_LO_SHIFT;
+			right_level = (harmony.current_gain & GAIN_RO_MASK) >> GAIN_RO_SHIFT;
+			left_level  = to_oss_level(MAX_OUTPUT_LEVEL - left_level, MAX_OUTPUT_LEVEL);
+			right_level = to_oss_level(MAX_OUTPUT_LEVEL - right_level, MAX_OUTPUT_LEVEL);
+			return (right_level << 8)+left_level;
+			
+		case SOUND_MIXER_IGAIN:
+			left_level = (harmony.current_gain & GAIN_LI_MASK) >> GAIN_LI_SHIFT;
+			right_level= (harmony.current_gain & GAIN_RI_MASK) >> GAIN_RI_SHIFT;
+			left_level = to_oss_level(left_level, MAX_INPUT_LEVEL);
+			right_level= to_oss_level(right_level, MAX_INPUT_LEVEL);
+			return (right_level << 8)+left_level;
+			
+		case SOUND_MIXER_VOLUME:
+			left_level = (harmony.current_gain & GAIN_MA_MASK) >> GAIN_MA_SHIFT;
+			left_level = to_oss_level(MAX_VOLUME_LEVEL-left_level, MAX_VOLUME_LEVEL);
+			return left_level;
+	}
+	return -EINVAL;
+}
+
+
+
+/*
+ * Some conversions for the same reasons.
+ * We give back the new real value(s) due to
+ * the rescale.
+ */
+
+static int harmony_mixer_set_level(int channel, int value)
+{
+	int left_level;
+	int right_level;
+	int new_left_level;
+	int new_right_level;
+
+	right_level = (value & 0x0000ff00) >> 8;
+	left_level = value & 0x000000ff;
+  
+	switch (channel) {
+		case SOUND_MIXER_OGAIN:
+			right_level = to_harmony_level(100-right_level, MAX_OUTPUT_LEVEL);
+			left_level  = to_harmony_level(100-left_level, MAX_OUTPUT_LEVEL);
+			new_right_level = to_oss_level(MAX_OUTPUT_LEVEL - right_level, MAX_OUTPUT_LEVEL);
+			new_left_level  = to_oss_level(MAX_OUTPUT_LEVEL - left_level, MAX_OUTPUT_LEVEL);
+			harmony.current_gain = (harmony.current_gain & ~(GAIN_LO_MASK | GAIN_RO_MASK)) 
+					| (left_level << GAIN_LO_SHIFT) | (right_level << GAIN_RO_SHIFT);
+			harmony_mixer_set_gain();
+			return (new_right_level << 8) + new_left_level;
+			
+		case SOUND_MIXER_IGAIN:
+			right_level = to_harmony_level(right_level, MAX_INPUT_LEVEL);
+			left_level  = to_harmony_level(left_level, MAX_INPUT_LEVEL);
+			new_right_level = to_oss_level(right_level, MAX_INPUT_LEVEL);
+			new_left_level  = to_oss_level(left_level, MAX_INPUT_LEVEL);
+			harmony.current_gain = (harmony.current_gain & ~(GAIN_LI_MASK | GAIN_RI_MASK))
+					| (left_level << GAIN_LI_SHIFT) | (right_level << GAIN_RI_SHIFT);
+			harmony_mixer_set_gain();
+			return (new_right_level << 8) + new_left_level;
+	
+		case SOUND_MIXER_VOLUME:
+			left_level = to_harmony_level(100-left_level, MAX_VOLUME_LEVEL);
+			new_left_level = to_oss_level(MAX_VOLUME_LEVEL-left_level, MAX_VOLUME_LEVEL);
+			harmony.current_gain = (harmony.current_gain & ~GAIN_MA_MASK)| (left_level << GAIN_MA_SHIFT);
+			harmony_mixer_set_gain();
+			return new_left_level;
+	}
+
+	return -EINVAL;
+}
+
+#undef to_harmony_level
+#undef to_oss_level
+
+/* 
+ * Return the selected input device (mic or line)
+ */
+
+static int harmony_mixer_get_recmask(void) 
+{
+	int current_input_line;
+	
+	current_input_line = (harmony.current_gain & GAIN_IS_MASK) 
+				    >> GAIN_IS_SHIFT;
+	if (current_input_line) 
+		return SOUND_MASK_MIC;
+
+	return SOUND_MASK_LINE;
+}
+
+/*
+ * Set the input (only one at time, arbitrary priority to line in)
+ */
+
+static int harmony_mixer_set_recmask(int recmask)
+{
+	int new_input_line;
+	int new_input_mask;
+
+	if ((recmask & SOUND_MASK_LINE)) {
+		new_input_line = 0;
+		new_input_mask = SOUND_MASK_LINE;
+	} else  {
+		new_input_line = 1;
+		new_input_mask = SOUND_MASK_MIC;
+	}
+	harmony.current_gain = ((harmony.current_gain & ~GAIN_IS_MASK) | 
+				(new_input_line << GAIN_IS_SHIFT ));
+	harmony_mixer_set_gain();
+	return new_input_mask;
+}
+
+
+/* 
+ * give the active outlines
+ */
+
+static int harmony_mixer_get_outmask(void)
+{
+	int outmask = 0;
+	
+	if (harmony.current_gain & GAIN_HE_MASK) outmask |=SOUND_MASK_PHONEOUT;
+	if (harmony.current_gain & GAIN_LE_MASK) outmask |=SOUND_MASK_LINE;
+	if (harmony.current_gain & GAIN_SE_MASK) outmask |=SOUND_MASK_SPEAKER;
+	
+	return outmask;
+}
+
+
+static int harmony_mixer_set_outmask(int outmask)
+{
+	if (outmask & SOUND_MASK_PHONEOUT) 
+		harmony.current_gain |= GAIN_HE_MASK; 
+	else 
+		harmony.current_gain &= ~GAIN_HE_MASK;
+	
+	if (outmask & SOUND_MASK_LINE) 
+		harmony.current_gain |= GAIN_LE_MASK;
+	else 
+		harmony.current_gain &= ~GAIN_LE_MASK;
+	
+	if (outmask & SOUND_MASK_SPEAKER) 
+		harmony.current_gain |= GAIN_SE_MASK;
+	else 
+		harmony.current_gain &= ~GAIN_SE_MASK;
+	
+	harmony_mixer_set_gain();
+
+	return (outmask & (SOUND_MASK_PHONEOUT | SOUND_MASK_LINE | SOUND_MASK_SPEAKER));
+}
+
+/*
+ * This code is inspired from sb_mixer.c
+ */
+
+static int harmony_mixer_ioctl(struct inode * inode, struct file * file,
+		unsigned int cmd, unsigned long arg)
+{
+	int val;
+	int ret;
+
+	if (cmd == SOUND_MIXER_INFO) {
+		mixer_info info;
+		memset(&info, 0, sizeof(info));
+                strncpy(info.id, "harmony", sizeof(info.id)-1);
+                strncpy(info.name, "Harmony audio", sizeof(info.name)-1);
+                info.modify_counter = 1; /* ? */
+                if (copy_to_user((void *)arg, &info, sizeof(info)))
+                        return -EFAULT;
+		return 0;
+	}
+	
+	if (cmd == OSS_GETVERSION)
+		return put_user(SOUND_VERSION, (int *)arg);
+
+	/* read */
+	val = 0;
+	if (_SIOC_DIR(cmd) & _SIOC_WRITE)
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+
+	switch (cmd) {
+	case MIXER_READ(SOUND_MIXER_CAPS):
+		ret = SOUND_CAP_EXCL_INPUT;
+		break;
+	case MIXER_READ(SOUND_MIXER_STEREODEVS):
+		ret = SOUND_MASK_IGAIN | SOUND_MASK_OGAIN;
+		break;
+		
+	case MIXER_READ(SOUND_MIXER_RECMASK):
+		ret = SOUND_MASK_MIC | SOUND_MASK_LINE;
+		break;
+	case MIXER_READ(SOUND_MIXER_DEVMASK):
+		ret = SOUND_MASK_OGAIN | SOUND_MASK_IGAIN |
+			SOUND_MASK_VOLUME;
+		break;
+	case MIXER_READ(SOUND_MIXER_OUTMASK):
+		ret = SOUND_MASK_SPEAKER | SOUND_MASK_LINE |
+			SOUND_MASK_PHONEOUT;
+		break;
+		
+	case MIXER_WRITE(SOUND_MIXER_RECSRC):
+		ret = harmony_mixer_set_recmask(val);
+		break;
+	case MIXER_READ(SOUND_MIXER_RECSRC):
+		ret = harmony_mixer_get_recmask();
+		break;
+	      
+	case MIXER_WRITE(SOUND_MIXER_OUTSRC):
+		ret = harmony_mixer_set_outmask(val);
+		break;
+	case MIXER_READ(SOUND_MIXER_OUTSRC):
+		ret = harmony_mixer_get_outmask();
+		break;
+	
+	case MIXER_WRITE(SOUND_MIXER_OGAIN):
+	case MIXER_WRITE(SOUND_MIXER_IGAIN):
+	case MIXER_WRITE(SOUND_MIXER_VOLUME):
+		ret = harmony_mixer_set_level(cmd & 0xff, val);
+		break;
+
+	case MIXER_READ(SOUND_MIXER_OGAIN):
+	case MIXER_READ(SOUND_MIXER_IGAIN):
+	case MIXER_READ(SOUND_MIXER_VOLUME):
+		ret = harmony_mixer_get_level(cmd & 0xff);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (put_user(ret, (int *)arg))
+		return -EFAULT;
+	return 0;
+}
+
+
+static int harmony_mixer_open(struct inode *inode, struct file *file)
+{
+	if (harmony.mixer_open) 
+		return -EBUSY;
+	harmony.mixer_open++;
+	return 0;
+}
+
+static int harmony_mixer_release(struct inode *inode, struct file *file)
+{
+	if (!harmony.mixer_open) 
+		return -EBUSY;
+	harmony.mixer_open--;
+	return 0;
+}
+
+static struct file_operations harmony_mixer_fops = {
+	owner:		THIS_MODULE,
+	llseek:		no_llseek,
+	open:		harmony_mixer_open,
+	release:	harmony_mixer_release,
+	ioctl:		harmony_mixer_ioctl,
+};
+
+
+/*
+ * Mute all the output and reset Harmony.
+ */
+
+static void __init harmony_mixer_reset(void)
+{
+	harmony.current_gain = GAIN_TOTAL_SILENCE;
+	harmony_mixer_set_gain();
+	harmony_wait_CNTL();
+	gsc_writel(1, &harmony.hpa->reset);
+	mdelay(50);		/* wait 50 ms */
+	gsc_writel(0, &harmony.hpa->reset);
+	harmony.current_gain = GAIN_DEFAULT;
+	harmony_mixer_set_gain();
+}
+
+static int __init harmony_mixer_init(void)
+{
+	/* Register the device file operations */
+	harmony.mixer_unit = register_sound_mixer(&harmony_mixer_fops, -1);
+	if (harmony.mixer_unit < 0) {
+		printk(KERN_WARNING PFX "Error Registering Mixer Driver\n");
+		return -EFAULT;
+	}
+  
+	harmony_mixer_reset();
+	harmony.mixer_open = 0;
+	
+	return 0;
+}
+
+
+
+/* 
+ * This is the callback that's called by the inventory hardware code 
+ * if it finds a match to the registered driver. 
+ */
+static int __init
+harmony_driver_callback(struct parisc_device *dev)
+{
+	u8	id;
+	u8	rev;
+	u32	cntl;
+	int	ret;
+
+	if (harmony.hpa) {
+		/* We only support one Harmony at this time */
+		printk(KERN_ERR PFX "driver already registered\n");
+		return -EBUSY;
+	}
+
+	/* Set the HPA of harmony */
+	harmony.hpa = (struct harmony_hpa *)dev->hpa;
+
+	harmony.irq = dev->irq;
+	if (!harmony.irq) {
+		printk(KERN_ERR PFX "no irq found\n");
+		return -ENODEV;
+	}
+
+	/* Grab the ID and revision from the device */
+	id = gsc_readb(&harmony.hpa->id);
+	if ((id | 1) != 0x15) {
+		printk(KERN_WARNING PFX "wrong harmony id 0x%02x\n", id);
+		return -EBUSY;
+	}
+	cntl = gsc_readl(&harmony.hpa->cntl);
+	rev = (cntl>>20) & 0xff;
+
+	printk(KERN_INFO "Lasi Harmony Audio driver " HARMONY_VERSION ", "
+			"h/w id %i, rev. %i at 0x%lx, IRQ %i\n",
+			id, rev, dev->hpa, harmony.irq);
+	
+	/* Make sure the control bit isn't set, although I don't think it 
+	   ever is. */
+	if (cntl & CNTL_C) {
+		printk(KERN_WARNING PFX "CNTL busy\n");
+		harmony.hpa = 0;
+		return -EBUSY;
+	}
+
+	/* a fake pci_dev is needed for pci_* functions under ccio */
+	harmony.fake_pci_dev = ccio_get_fake(dev);
+	
+	/* Initialize the memory buffers */
+	if (harmony_alloc_buffer(&played_buf, MAX_BUFS) || 
+	    harmony_alloc_buffer(&recorded_buf, MAX_BUFS) ||
+	    harmony_alloc_buffer(&graveyard, 1) ||
+	    harmony_alloc_buffer(&silent, 1)) {
+		ret = -EBUSY;
+		goto out_err;
+	}
+
+	/* Initialize /dev/mixer and /dev/audio  */
+	if ((ret=harmony_mixer_init())) 
+		goto out_err;
+	if ((ret=harmony_audio_init())) 
+		goto out_err;
+
+	return 0;
+
+out_err:
+	harmony.hpa = 0;
+	harmony_free_buffer(&played_buf);
+	harmony_free_buffer(&recorded_buf);
+	harmony_free_buffer(&graveyard);
+	harmony_free_buffer(&silent);
+	return ret;
+}
+
+
+static struct parisc_device_id harmony_tbl[] = {
+ /* { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007A }, Bushmaster/Flounder */
+ { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007B }, /* 712/715 Audio */
+ { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007E }, /* Pace Audio */
+ { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007F }, /* Outfield / Coral II */
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(parisc, harmony_tbl);
+
+static struct parisc_driver harmony_driver = {
+	name:		"Lasi Harmony",
+	id_table:	harmony_tbl,
+	probe:		harmony_driver_callback,
+};
+
+static int __init init_harmony(void)
+{
+	return register_parisc_driver(&harmony_driver);
+}
+
+static void __exit cleanup_harmony(void)
+{
+	free_irq(harmony.irq, &harmony);
+	unregister_sound_mixer(harmony.mixer_unit);
+	unregister_sound_dsp(harmony.dsp_unit);
+	harmony_free_buffer(&played_buf);
+	harmony_free_buffer(&recorded_buf);
+	harmony_free_buffer(&graveyard);
+	harmony_free_buffer(&silent);
+	unregister_parisc_driver(&harmony_driver);
+}
+
+EXPORT_NO_SYMBOLS;
+
+MODULE_AUTHOR("Alex DeVries <alex@linuxcare.com>");
+MODULE_DESCRIPTION("Harmony sound driver");
+MODULE_LICENSE("GPL");
+
+module_init(init_harmony);
+module_exit(cleanup_harmony);
+
diff -Nru a/sound/oss/kahlua.c b/sound/oss/kahlua.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/sound/oss/kahlua.c	Sat Jul 19 12:54:30 2003
@@ -0,0 +1,227 @@
+/*
+ *	Initialisation code for Cyrix/NatSemi VSA1 softaudio
+ *
+ *	(C) Copyright 2003 Red Hat Inc <alan@redhat.com>
+ *
+ * XpressAudio(tm) is used on the Cyrix MediaGX (now NatSemi Geode) systems.
+ * The older version (VSA1) provides fairly good soundblaster emulation
+ * although there are a couple of bugs: large DMA buffers break record,
+ * and the MPU event handling seems suspect. VSA2 allows the native driver
+ * to control the AC97 audio engine directly and requires a different driver.
+ *
+ * Thanks to National Semiconductor for providing the needed information
+ * on the XpressAudio(tm) internals.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * TO DO:
+ *	Investigate whether we can portably support Cognac (5520) in the
+ *	same manner.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "sound_config.h"
+
+#include "sb.h"
+
+/*
+ *	Read a soundblaster compatible mixer register.
+ *	In this case we are actually reading an SMI trap
+ *	not real hardware.
+ */
+
+static u8 __devinit mixer_read(unsigned long io, u8 reg)
+{
+	outb(reg, io + 4);
+	udelay(20);
+	reg = inb(io + 5);
+	udelay(20);
+	return reg;
+}
+
+static int __devinit probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct address_info *hw_config;
+	unsigned long base;
+	void *mem;
+	unsigned long io;
+	u16 map;
+	u8 irq, dma8, dma16;
+	int oldquiet;
+	extern int sb_be_quiet;
+		
+	base = pci_resource_start(pdev, 0);
+	if(base == 0UL)
+		return 1;
+	
+	mem = ioremap(base, 128);
+	if(mem == 0UL)
+		return 1;
+	map = readw(mem + 0x18);	/* Read the SMI enables */
+	iounmap(mem);
+	
+	/* Map bits
+		0:1	* 0x20 + 0x200 = sb base
+		2	sb enable
+		3	adlib enable
+		5	MPU enable 0x330
+		6	MPU enable 0x300
+		
+	   The other bits may be used internally so must be masked */
+
+	io = 0x220 + 0x20 * (map & 3);	   
+	
+	if(map & (1<<2))
+		printk(KERN_INFO "kahlua: XpressAudio at 0x%lx\n", io);
+	else
+		return 1;
+		
+	if(map & (1<<5))
+		printk(KERN_INFO "kahlua: MPU at 0x300\n");
+	else if(map & (1<<6))
+		printk(KERN_INFO "kahlua: MPU at 0x330\n");
+	
+	irq = mixer_read(io, 0x80) & 0x0F;
+	dma8 = mixer_read(io, 0x81);
+
+	// printk("IRQ=%x MAP=%x DMA=%x\n", irq, map, dma8);
+	
+	if(dma8 & 0x20)
+		dma16 = 5;
+	else if(dma8 & 0x40)
+		dma16 = 6;
+	else if(dma8 & 0x80)
+		dma16 = 7;
+	else
+	{
+		printk(KERN_ERR "kahlua: No 16bit DMA enabled.\n");
+		return 1;
+	}
+		
+	if(dma8 & 0x01)
+		dma8 = 0;
+	else if(dma8 & 0x02)
+		dma8 = 1;
+	else if(dma8 & 0x08)
+		dma8 = 3;
+	else
+	{
+		printk(KERN_ERR "kahlua: No 8bit DMA enabled.\n");
+		return 1;
+	}
+	
+	if(irq & 1)
+		irq = 9;
+	else if(irq & 2)
+		irq = 5;
+	else if(irq & 4)
+		irq = 7;
+	else if(irq & 8)
+		irq = 10;
+	else
+	{
+		printk(KERN_ERR "kahlua: SB IRQ not set.\n");
+		return 1;
+	}
+	
+	printk(KERN_INFO "kahlua: XpressAudio on IRQ %d, DMA %d, %d\n",
+		irq, dma8, dma16);
+	
+	hw_config = kmalloc(sizeof(struct address_info), GFP_KERNEL);
+	if(hw_config == NULL)
+	{
+		printk(KERN_ERR "kahlua: out of memory.\n");
+		return 1;
+	}
+	memset(hw_config, 0, sizeof(*hw_config));
+	
+	pci_set_drvdata(pdev, hw_config);
+	
+	hw_config->io_base = io;
+	hw_config->irq = irq;
+	hw_config->dma = dma8;
+	hw_config->dma2 = dma16;
+	hw_config->name = "Cyrix XpressAudio";
+	hw_config->driver_use_1 = SB_NO_MIDI | SB_PCI_IRQ;
+	
+	if(sb_dsp_detect(hw_config, 0, 0, NULL)==0)
+	{
+		printk(KERN_ERR "kahlua: audio not responding.\n");
+		goto err_out_free;
+	}
+
+	oldquiet = sb_be_quiet;	
+	sb_be_quiet = 1;
+	if(sb_dsp_init(hw_config, THIS_MODULE))
+	{
+		sb_be_quiet = oldquiet;
+		goto err_out_free;
+	}
+	sb_be_quiet = oldquiet;
+	
+	return 0;
+
+err_out_free:
+	pci_set_drvdata(pdev, NULL);
+	kfree(hw_config);
+	return 1;
+}
+
+static void __devexit remove_one(struct pci_dev *pdev)
+{
+	struct address_info *hw_config = pci_get_drvdata(pdev);
+	sb_dsp_unload(hw_config, 0);
+	pci_set_drvdata(pdev, NULL);
+	kfree(hw_config);
+}
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("Kahlua VSA1 PCI Audio");
+MODULE_LICENSE("GPL");
+
+/*
+ *	5530 only. The 5510/5520 decode is different.
+ */
+
+static struct pci_device_id id_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(pci, id_tbl);
+
+static struct pci_driver kahlua_driver = {
+	name:		"kahlua",
+	id_table:	id_tbl,
+	probe:		probe_one,
+	remove:         __devexit_p(remove_one),
+};
+
+
+static int __init kahlua_init_module(void)
+{
+	printk(KERN_INFO "Cyrix Kahlua VSA1 XpressAudio support (c) Copyright 2003 Red Hat Inc\n");
+	return pci_module_init(&kahlua_driver);
+}
+
+static void __devexit kahlua_cleanup_module(void)
+{
+	return pci_unregister_driver(&kahlua_driver);
+}
+
+
+module_init(kahlua_init_module);
+module_exit(kahlua_cleanup_module);
+
diff -Nru a/usr/Makefile b/usr/Makefile
--- a/usr/Makefile	Sat Jul 19 12:54:25 2003
+++ b/usr/Makefile	Sat Jul 19 12:54:25 2003
@@ -3,7 +3,7 @@
 
 host-progs  := gen_init_cpio
 
-clean-files := initramfs_data.cpio.gz
+clean-files := initramfs_data.cpio.gz initramfs_data.S
 
 $(src)/initramfs_data.S: $(obj)/initramfs_data.cpio.gz
 	echo "	.section .init.ramfs,\"a\"" > $(src)/initramfs_data.S
