some MNCI "Ramses" related changes
authorHolger Schurig <schurig@mn-solutions.de>
Thu, 30 Sep 2004 14:49:57 +0000 (14:49 +0000)
committerHolger Schurig <schurig@mn-solutions.de>
Thu, 30 Sep 2004 14:49:57 +0000 (14:49 +0000)
BKrev: 415c1d15quLlMWHqQc8WEmYm8QzznA

ipkg/ipkg-collateral/ramses/src
linux/mnci-ramses-2.4.21-rmk2-pxa1/mnci-combined.patch
linux/mnci-ramses_2.4.21-rmk2-pxa1.oe
update-modules/update-modules-1.0/ramses/update-modules [new file with mode: 0644]

index e69de29..5b99d48 100644 (file)
@@ -0,0 +1,3 @@
+src mnci54 http://www.mn-solutions.de/feed/mnci54
+#src unstable http://www.mn-solutions.de/feed/unstable
+#src stable http://www.mn-solutions.de/feed/stable
index e69de29..55d91b9 100644 (file)
+
+# This is a cumulative patch consisting of:
+#
+#   linux-vtcomparison.patch
+#   linux-mkdep.patch
+#   linux-iw241_we16-6.patch
+#   arm-noshortloads.patch
+#   pxa-pcmcia.patch
+#   pxa-smc91x.patch
+#   pxa-usb.patch
+#   pxa-usbeth.patch
+#   pxa-irda.patch
+#   pxa-ac97.patch
+#   pxa-timerint.patch
+#   fb-buffered.patch
+#   fb-turn180.patch
+#   i2c-ds1337.patch
+#   keyb-input.patch
+#   keyb-module.patch
+#   logo-noscrollregion.patch
+#   net-dhcp-timeout.patch
+#   pm.patch
+#   swap-performance.patch
+#   small-nocramdisk.patch
+#   smc91x-ethtool.patch
+#   ucb1x00.patch
+#   vmalloc.patch
+#   usb-sl811.patch
+#   orinoco013e.patch
+#   ramses.patch
+#   ramses-ac97.patch
+#   ramses-keyb.patch
+#   ramses-mtd.patch
+#   ramses-orinoco-ignorecis.patch
+#   ramses-pcmcia.patch
+#   ramses-serial.patch
+#   ramses-smc91x.patch
+#   ramses-sysctl.patch
+#   ramses-ucb1x00-dejitter.patch
+#   ramses-lcd.patch
+#   ramses-usb.patch
+#   ramses-corevolt.patch
+#   wedge.patch
+#   usb-sonycamera.patch
+#   ramses-ucb1x00-rotate.patch
+#   vt-noblank.patch
+#
+# Patch managed by http://www.holgerschurig.de/patcher.html
+#
+
+--- linux-2.4.21/Makefile~linux-mkdep
++++ linux-2.4.21/Makefile
+@@ -14,10 +14,11 @@
+         else echo sh; fi ; fi)
+ TOPDIR        := $(shell /bin/pwd)
++PATH          := /usr/local/arm/3.3/bin:$(PATH)
+ HPATH         = $(TOPDIR)/include
+ FINDHPATH     = $(HPATH)/asm $(HPATH)/linux $(HPATH)/scsi $(HPATH)/net $(HPATH)/math-emu
+-HOSTCC        = gcc
++HOSTCC        = ccache gcc
+ HOSTCFLAGS    = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
+ CROSS_COMPILE         = arm-linux-
+@@ -28,7 +29,7 @@
+ AS            = $(CROSS_COMPILE)as
+ LD            = $(CROSS_COMPILE)ld
+-CC            = $(CROSS_COMPILE)gcc
++CC            = ccache $(CROSS_COMPILE)gcc
+ CPP           = $(CC) -E
+ AR            = $(CROSS_COMPILE)ar
+ NM            = $(CROSS_COMPILE)nm
+@@ -80,6 +81,7 @@
+ # makefile but the arguement can be passed to make if needed.
+ #
++export INSTALL_MOD_PATH = /tftpboot/ramses2
+ MODLIB        := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
+ export MODLIB
+@@ -140,7 +142,6 @@
+ DRIVERS-y += drivers/serial/serial.o \
+       drivers/char/char.o \
+       drivers/block/block.o \
+-      drivers/misc/misc.o \
+       drivers/net/net.o
+ DRIVERS-$(CONFIG_AGP) += drivers/char/agp/agp.o
+ DRIVERS-$(CONFIG_DRM_NEW) += drivers/char/drm/drm.o
+@@ -197,6 +198,7 @@
+ DRIVERS-$(CONFIG_ISDN_BOOL) += drivers/isdn/vmlinux-obj.o
+ DRIVERS-$(CONFIG_PLD) += drivers/pld/pld.o
+ DRIVERS-$(CONFIG_ARCH_AT91RM9200) += drivers/at91/at91drv.o
++DRIVERS-y += drivers/misc/misc.o
+ DRIVERS := $(DRIVERS-y)
+@@ -416,7 +418,7 @@
+ endif
+ .PHONY: _modinst_post
+ _modinst_post: _modinst_post_pcmcia
+-      if [ -r System.map ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi
++#     if [ -r System.map ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi
+ # Backwards compatibilty symlinks for people still using old versions
+ # of pcmcia-cs with hard coded pathnames on insmod.  Remove
+@@ -495,7 +497,7 @@
+ ifdef CONFIG_MODVERSIONS
+       $(MAKE) update-modverfile
+ endif
+-      scripts/mkdep -- `find $(FINDHPATH) \( -name SCCS -o -name .svn \) -prune -o -follow -name \*.h ! -name modversions.h -print` > .hdepend
++      $(foreach, dir, $(FINDHPATH), scripts/mkdep -- `find $(dir) -name SCCS -prune -o -follow -name \*.h ! -name modversions.h -print` >> .hdepend)  
+       scripts/mkdep -- init/*.c > .depend
+ ifdef CONFIG_MODVERSIONS
+@@ -574,3 +576,14 @@
+       . scripts/mkversion > .version ; \
+       rpm -ta $(TOPDIR)/../$(KERNELPATH).tar.gz ; \
+       rm $(TOPDIR)/../$(KERNELPATH).tar.gz
++
++
++
++#
++# Burn Linux Image for ArmBoot using the bdi2000
++#
++burn burn_zImage:
++      python ../hwtester/burner.py arch/arm/boot/zImage 0x40000
++
++publish: arch/arm/boot/zImage
++      cp arch/arm/boot/zImage /tftpboot/bdi/zImage.testing
+--- linux-2.4.21/arch/arm/Makefile~arm-noshortloads
++++ linux-2.4.21/arch/arm/Makefile
+@@ -55,8 +55,8 @@
+ #tune-$(CONFIG_CPU_XSCALE)    :=-mtune=xscale
+ tune-$(CONFIG_CPU_XSCALE)     :=-mtune=strongarm
+-CFLAGS_BOOT   :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm
+-CFLAGS                +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Uarm
++CFLAGS_BOOT   :=$(apcs-y) $(arch-y) $(tune-y) -msoft-float -Uarm
++CFLAGS                +=$(apcs-y) $(arch-y) $(tune-y) -msoft-float -Uarm
+ AFLAGS                +=$(apcs-y) $(arch-y) -msoft-float
+ ifeq ($(CONFIG_CPU_26),y)
+@@ -289,7 +289,7 @@
+ arch/arm/kernel arch/arm/mm arch/arm/lib: dummy
+       $(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" $(subst $@, _dir_$@, $@)
+-bzImage zImage zinstall Image xipImage bootpImage install: vmlinux
++bzImage zImage zinstall Image xipImage bootpImage: vmlinux
+       @$(MAKEBOOT) $@
+ CLEAN_FILES   += \
+--- linux-2.4.21/arch/arm/config.in~pm
++++ linux-2.4.21/arch/arm/config.in
+@@ -152,6 +152,7 @@
+ dep_bool '  Intel DBPXA250 Development Platform' CONFIG_ARCH_LUBBOCK $CONFIG_ARCH_PXA
+ dep_bool '  Accelent Xscale IDP' CONFIG_ARCH_PXA_IDP $CONFIG_ARCH_PXA
+ dep_bool '  Intrinsyc CerfBoard' CONFIG_ARCH_PXA_CERF $CONFIG_ARCH_PXA
++dep_bool '  M und N Ramses' CONFIG_ARCH_RAMSES $CONFIG_ARCH_PXA
+ dep_bool '  Trizeps-II MT6N' CONFIG_ARCH_TRIZEPS2 $CONFIG_ARCH_PXA
+ if [ "$CONFIG_ARCH_PXA_CERF" = "y" ]; then
+@@ -586,6 +587,7 @@
+ tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+ dep_bool 'Power Management support (experimental)' CONFIG_PM $CONFIG_EXPERIMENTAL
++dep_bool 'Advanced power management emulation support' CONFIG_APM $CONFIG_PM
+ dep_tristate 'RISC OS personality' CONFIG_ARTHUR $CONFIG_CPU_32
+ string 'Default kernel command string' CONFIG_CMDLINE ""
+--- /dev/null
++++ linux-2.4.21/arch/arm/def-configs/ramses
+@@ -0,0 +1,1128 @@
++#
++# Automatically generated by make menuconfig: don't edit
++#
++CONFIG_ARM=y
++# CONFIG_EISA is not set
++# CONFIG_SBUS is not set
++# CONFIG_MCA is not set
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
++# CONFIG_GENERIC_BUST_SPINLOCK is not set
++# CONFIG_GENERIC_ISA_DMA is not set
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++# CONFIG_OBSOLETE is not set
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++# CONFIG_MODVERSIONS is not set
++CONFIG_KMOD=y
++
++#
++# System Type
++#
++# CONFIG_ARCH_ANAKIN is not set
++# CONFIG_ARCH_ARCA5K is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++CONFIG_ARCH_PXA=y
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_CAMELOT is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_OMAHA is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_MX1ADS is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_RISCSTATION is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_AT91RM9200 is not set
++
++#
++# Archimedes/A5000 Implementations
++#
++# CONFIG_ARCH_ARC is not set
++# CONFIG_ARCH_A5K is not set
++
++#
++# Footbridge Implementations
++#
++# CONFIG_ARCH_CATS is not set
++# CONFIG_ARCH_PERSONAL_SERVER is not set
++# CONFIG_ARCH_EBSA285_ADDIN is not set
++# CONFIG_ARCH_EBSA285_HOST is not set
++# CONFIG_ARCH_NETWINDER is not set
++
++#
++# SA11x0 Implementations
++#
++# CONFIG_SA1100_ACCELENT is not set
++# CONFIG_SA1100_ASSABET is not set
++# CONFIG_ASSABET_NEPONSET is not set
++# CONFIG_SA1100_ADSAGC is not set
++# CONFIG_SA1100_ADSBITSY is not set
++# CONFIG_SA1100_ADSBITSYPLUS is not set
++# CONFIG_SA1100_BRUTUS is not set
++# CONFIG_SA1100_CEP is not set
++# CONFIG_SA1100_CERF is not set
++# CONFIG_SA1100_H3100 is not set
++# CONFIG_SA1100_H3600 is not set
++# CONFIG_SA1100_H3800 is not set
++# CONFIG_SA1100_H3XXX is not set
++# CONFIG_H3600_SLEEVE is not set
++# CONFIG_SA1100_EXTENEX1 is not set
++# CONFIG_SA1100_FLEXANET is not set
++# CONFIG_SA1100_FREEBIRD is not set
++# CONFIG_SA1100_FRODO is not set
++# CONFIG_SA1100_GRAPHICSCLIENT is not set
++# CONFIG_SA1100_GRAPHICSMASTER is not set
++# CONFIG_SA1100_HACKKIT is not set
++# CONFIG_SA1100_BADGE4 is not set
++# CONFIG_SA1100_JORNADA720 is not set
++# CONFIG_SA1100_HUW_WEBPANEL is not set
++# CONFIG_SA1100_ITSY is not set
++# CONFIG_SA1100_LART is not set
++# CONFIG_SA1100_NANOENGINE is not set
++# CONFIG_SA1100_OMNIMETER is not set
++# CONFIG_SA1100_PANGOLIN is not set
++# CONFIG_SA1100_PLEB is not set
++# CONFIG_SA1100_PT_SYSTEM3 is not set
++# CONFIG_SA1100_SHANNON is not set
++# CONFIG_SA1100_SHERMAN is not set
++# CONFIG_SA1100_SIMPAD is not set
++# CONFIG_SA1100_SIMPUTER is not set
++# CONFIG_SA1100_PFS168 is not set
++# CONFIG_SA1100_VICTOR is not set
++# CONFIG_SA1100_XP860 is not set
++# CONFIG_SA1100_YOPY is not set
++# CONFIG_SA1100_USB is not set
++# CONFIG_SA1100_USB_NETLINK is not set
++# CONFIG_SA1100_USB_CHAR is not set
++# CONFIG_SA1100_SSP is not set
++
++#
++# AT91RM9200 Implementations
++#
++# CONFIG_ARCH_AT91RM9200DK is not set
++
++#
++# Intel PXA250/210 Implementations
++#
++# CONFIG_ARCH_LUBBOCK is not set
++# CONFIG_ARCH_PXA_IDP is not set
++# CONFIG_ARCH_PXA_CERF is not set
++CONFIG_ARCH_RAMSES=y
++# CONFIG_ARCH_TRIZEPS2 is not set
++CONFIG_PXA_USB=m
++CONFIG_PXA_USB_NETLINK=m
++CONFIG_PXA_USB_CHAR=m
++
++#
++# CLPS711X/EP721X Implementations
++#
++# CONFIG_ARCH_AUTCPU12 is not set
++# CONFIG_ARCH_CDB89712 is not set
++# CONFIG_ARCH_CLEP7312 is not set
++# CONFIG_ARCH_EDB7211 is not set
++# CONFIG_ARCH_FORTUNET is not set
++# CONFIG_ARCH_GUIDEA07 is not set
++# CONFIG_ARCH_P720T is not set
++# CONFIG_ARCH_EP7211 is not set
++# CONFIG_ARCH_EP7212 is not set
++# CONFIG_ARCH_ACORN is not set
++# CONFIG_PLD is not set
++# CONFIG_FOOTBRIDGE is not set
++# CONFIG_FOOTBRIDGE_HOST is not set
++# CONFIG_FOOTBRIDGE_ADDIN is not set
++CONFIG_CPU_32=y
++# CONFIG_CPU_26 is not set
++# CONFIG_CPU_ARM610 is not set
++# CONFIG_CPU_ARM710 is not set
++# CONFIG_CPU_ARM720T is not set
++# CONFIG_CPU_ARM920T is not set
++# CONFIG_CPU_ARM922T is not set
++# CONFIG_CPU_ARM926T is not set
++# CONFIG_CPU_ARM1020 is not set
++# CONFIG_CPU_ARM1020E is not set
++# CONFIG_CPU_ARM1022 is not set
++# CONFIG_CPU_ARM1026 is not set
++# CONFIG_CPU_SA110 is not set
++# CONFIG_CPU_SA1100 is not set
++CONFIG_CPU_32v5=y
++CONFIG_CPU_XSCALE=y
++# CONFIG_XSCALE_CACHE_ERRATA is not set
++# CONFIG_CPU_32v3 is not set
++# CONFIG_CPU_32v4 is not set
++# CONFIG_DISCONTIGMEM is not set
++
++#
++# General setup
++#
++# CONFIG_PCI is not set
++# CONFIG_ISA is not set
++# CONFIG_ISA_DMA is not set
++CONFIG_ZBOOT_ROM=y
++CONFIG_ZBOOT_ROM_TEXT=00040000
++CONFIG_ZBOOT_ROM_BSS=a00c0000
++CONFIG_CPU_FREQ=y
++CONFIG_HOTPLUG=y
++
++#
++# PCMCIA/CardBus support
++#
++CONFIG_PCMCIA=y
++# CONFIG_I82092 is not set
++# CONFIG_I82365 is not set
++# CONFIG_TCIC is not set
++# CONFIG_PCMCIA_CLPS6700 is not set
++# CONFIG_PCMCIA_SA1100 is not set
++CONFIG_PCMCIA_PXA=y
++
++#
++# MMC device drivers
++#
++CONFIG_MMC=m
++CONFIG_MMC_PXA=m
++CONFIG_MMC_BLOCK=m
++CONFIG_MMC_PARTITIONS=y
++CONFIG_NET=y
++CONFIG_SYSVIPC=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++CONFIG_SYSCTL=y
++# CONFIG_XIP_KERNEL is not set
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_KCORE_ELF=y
++# CONFIG_KCORE_AOUT is not set
++# CONFIG_BINFMT_AOUT is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_MISC is not set
++CONFIG_PM=y
++CONFIG_APM=y
++# CONFIG_ARTHUR is not set
++CONFIG_CMDLINE="debug"
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Memory Technology Devices (MTD)
++#
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_CONCAT is not set
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++CONFIG_MTD_CFI_ADV_OPTIONS=y
++CONFIG_MTD_CFI_NOSWAP=y
++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
++CONFIG_MTD_CFI_GEOMETRY=y
++# CONFIG_MTD_CFI_B1 is not set
++# CONFIG_MTD_CFI_B2 is not set
++CONFIG_MTD_CFI_B4=y
++# CONFIG_MTD_CFI_B8 is not set
++# CONFIG_MTD_CFI_I1 is not set
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_CFI_INTELEXT=y
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++# CONFIG_MTD_OBSOLETE_CHIPS is not set
++# CONFIG_MTD_AMDSTD is not set
++# CONFIG_MTD_SHARP is not set
++# CONFIG_MTD_JEDEC is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_PHYSMAP is not set
++# CONFIG_MTD_LUBBOCK is not set
++CONFIG_MTD_RAMSES=y
++# CONFIG_MTD_NORA is not set
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_CDB89712 is not set
++# CONFIG_MTD_SA1100 is not set
++# CONFIG_MTD_DC21285 is not set
++# CONFIG_MTD_IQ80310 is not set
++# CONFIG_MTD_FORTUNET is not set
++# CONFIG_MTD_EPXA is not set
++# CONFIG_MTD_AUTCPU12 is not set
++# CONFIG_MTD_EDB7312 is not set
++# CONFIG_MTD_IMPA7 is not set
++# CONFIG_MTD_CEIVA is not set
++# CONFIG_MTD_PCI is not set
++# CONFIG_MTD_PCMCIA is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_PMC551 is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLKMTD is not set
++# CONFIG_MTD_DOC1000 is not set
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOCPROBE is not set
++
++#
++# NAND Flash Device Drivers
++#
++# CONFIG_MTD_NAND is not set
++
++#
++# Plug and Play configuration
++#
++# CONFIG_PNP is not set
++# CONFIG_ISAPNP is not set
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_XD is not set
++# CONFIG_PARIDE is not set
++# CONFIG_BLK_CPQ_DA is not set
++# CONFIG_BLK_CPQ_CISS_DA is not set
++# CONFIG_CISS_SCSI_TAPE is not set
++# CONFIG_BLK_DEV_DAC960 is not set
++# CONFIG_BLK_DEV_UMEM is not set
++CONFIG_BLK_DEV_LOOP=m
++CONFIG_BLK_DEV_NBD=m
++# CONFIG_BLK_DEV_RAM is not set
++# CONFIG_BLK_DEV_INITRD is not set
++CONFIG_BLK_STATS=y
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++# CONFIG_BLK_DEV_MD is not set
++# CONFIG_MD_LINEAR is not set
++# CONFIG_MD_RAID0 is not set
++# CONFIG_MD_RAID1 is not set
++# CONFIG_MD_RAID5 is not set
++# CONFIG_MD_MULTIPATH is not set
++# CONFIG_BLK_DEV_LVM is not set
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_NETLINK_DEV=m
++# CONFIG_NETFILTER is not set
++# CONFIG_FILTER is not set
++CONFIG_UNIX=y
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++CONFIG_NET_IPIP=m
++CONFIG_NET_IPGRE=m
++# CONFIG_ARPD is not set
++# CONFIG_INET_ECN is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_IPV6 is not set
++# CONFIG_KHTTPD is not set
++# CONFIG_ATM is not set
++CONFIG_VLAN_8021Q=m
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++
++#
++# Appletalk devices
++#
++# CONFIG_DEV_APPLETALK is not set
++# CONFIG_DECNET is not set
++CONFIG_BRIDGE=m
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_LLC is not set
++# CONFIG_NET_DIVERT is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_FASTROUTE is not set
++# CONFIG_NET_HW_FLOWCONTROL is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++
++#
++# ARCnet devices
++#
++# CONFIG_ARCNET is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_ETHERTAP is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++# CONFIG_ARM_AM79C961A is not set
++# CONFIG_ARM_CIRRUS is not set
++# CONFIG_SUNLANCE is not set
++# CONFIG_SUNBMAC is not set
++# CONFIG_SUNQE is not set
++# CONFIG_SUNGEM is not set
++# CONFIG_NET_VENDOR_3COM is not set
++# CONFIG_LANCE is not set
++CONFIG_NET_VENDOR_SMC=y
++# CONFIG_WD80x3 is not set
++# CONFIG_ULTRAMCA is not set
++# CONFIG_ULTRA is not set
++# CONFIG_ULTRA32 is not set
++# CONFIG_SMC9194 is not set
++CONFIG_SMC91X=y
++# CONFIG_NET_VENDOR_RACAL is not set
++# CONFIG_NET_ISA is not set
++# CONFIG_NET_PCI is not set
++# CONFIG_NET_POCKET is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_MYRI_SBUS is not set
++# CONFIG_NS83820 is not set
++# CONFIG_HAMACHI is not set
++# CONFIG_YELLOWFIN is not set
++# CONFIG_R8169 is not set
++# CONFIG_SK98LIN is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PLIP is not set
++CONFIG_PPP=m
++# CONFIG_PPP_MULTILINK is not set
++# CONFIG_PPP_FILTER is not set
++CONFIG_PPP_ASYNC=m
++CONFIG_PPP_SYNC_TTY=m
++CONFIG_PPP_DEFLATE=m
++CONFIG_PPP_BSDCOMP=m
++CONFIG_PPPOE=m
++# CONFIG_SLIP is not set
++
++#
++# Wireless LAN (non-hamradio)
++#
++CONFIG_NET_RADIO=y
++# CONFIG_STRIP is not set
++# CONFIG_WAVELAN is not set
++# CONFIG_ARLAN is not set
++# CONFIG_AIRONET4500 is not set
++# CONFIG_AIRONET4500_NONCS is not set
++# CONFIG_AIRONET4500_PROC is not set
++CONFIG_HERMES=m
++CONFIG_PCMCIA_HERMES=m
++# CONFIG_AIRO_CS is not set
++CONFIG_NET_WIRELESS=y
++
++#
++# Token Ring devices
++#
++# CONFIG_TR is not set
++# CONFIG_NET_FC is not set
++# CONFIG_RCPCI is not set
++# CONFIG_SHAPER is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++
++#
++# PCMCIA network device support
++#
++CONFIG_NET_PCMCIA=y
++# CONFIG_PCMCIA_3C589 is not set
++# CONFIG_PCMCIA_3C574 is not set
++# CONFIG_PCMCIA_FMVJ18X is not set
++# CONFIG_PCMCIA_PCNET is not set
++# CONFIG_PCMCIA_AXNET is not set
++# CONFIG_PCMCIA_NMCLAN is not set
++# CONFIG_PCMCIA_SMC91C92 is not set
++# CONFIG_PCMCIA_XIRC2PS is not set
++# CONFIG_ARCNET_COM20020_CS is not set
++# CONFIG_PCMCIA_IBMTR is not set
++# CONFIG_NET_PCMCIA_RADIO is not set
++
++#
++# Amateur Radio support
++#
++# CONFIG_HAMRADIO is not set
++
++#
++# IrDA (infrared) support
++#
++CONFIG_IRDA=m
++CONFIG_IRLAN=m
++CONFIG_IRNET=m
++CONFIG_IRCOMM=m
++CONFIG_IRDA_ULTRA=y
++CONFIG_IRDA_CACHE_LAST_LSAP=y
++CONFIG_IRDA_FAST_RR=y
++CONFIG_IRDA_DEBUG=y
++
++#
++# Infrared-port device drivers
++#
++CONFIG_IRTTY_SIR=m
++CONFIG_IRPORT_SIR=m
++# CONFIG_DONGLE is not set
++# CONFIG_USB_IRDA is not set
++# CONFIG_NSC_FIR is not set
++# CONFIG_WINBOND_FIR is not set
++# CONFIG_TOSHIBA_OLD is not set
++# CONFIG_TOSHIBA_FIR is not set
++# CONFIG_SMC_IRCC_FIR is not set
++# CONFIG_ALI_FIR is not set
++# CONFIG_VLSI_FIR is not set
++CONFIG_PXA_FIR=m
++
++#
++# ATA/ATAPI/MFM/RLL support
++#
++# CONFIG_IDE is not set
++# CONFIG_BLK_DEV_IDE_MODES is not set
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI support
++#
++CONFIG_SCSI=m
++CONFIG_BLK_DEV_SD=m
++CONFIG_SD_EXTRA_DEVS=4
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_SCSI_DEBUG_QUEUES is not set
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_SCSI_7000FASST is not set
++# CONFIG_SCSI_ACARD is not set
++# CONFIG_SCSI_AHA152X is not set
++# CONFIG_SCSI_AHA1542 is not set
++# CONFIG_SCSI_AHA1740 is not set
++# CONFIG_SCSI_AACRAID is not set
++# CONFIG_SCSI_AIC7XXX is not set
++# CONFIG_SCSI_AIC79XX is not set
++# CONFIG_SCSI_AIC7XXX_OLD is not set
++# CONFIG_SCSI_DPT_I2O is not set
++# CONFIG_SCSI_ADVANSYS is not set
++# CONFIG_SCSI_IN2000 is not set
++# CONFIG_SCSI_AM53C974 is not set
++# CONFIG_SCSI_MEGARAID is not set
++# CONFIG_SCSI_BUSLOGIC is not set
++# CONFIG_SCSI_DMX3191D is not set
++# CONFIG_SCSI_DTC3280 is not set
++# CONFIG_SCSI_EATA is not set
++# CONFIG_SCSI_EATA_DMA is not set
++# CONFIG_SCSI_EATA_PIO is not set
++# CONFIG_SCSI_FUTURE_DOMAIN is not set
++# CONFIG_SCSI_GDTH is not set
++# CONFIG_SCSI_GENERIC_NCR5380 is not set
++# CONFIG_SCSI_INITIO is not set
++# CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_NCR53C406A is not set
++# CONFIG_SCSI_NCR53C7xx is not set
++# CONFIG_SCSI_PAS16 is not set
++# CONFIG_SCSI_PCI2000 is not set
++# CONFIG_SCSI_PCI2220I is not set
++# CONFIG_SCSI_PSI240I is not set
++# CONFIG_SCSI_QLOGIC_FAS is not set
++# CONFIG_SCSI_SIM710 is not set
++# CONFIG_SCSI_SYM53C416 is not set
++# CONFIG_SCSI_T128 is not set
++# CONFIG_SCSI_U14_34F is not set
++# CONFIG_SCSI_NSP32 is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# PCMCIA SCSI adapter support
++#
++# CONFIG_SCSI_PCMCIA is not set
++
++#
++# I2O device support
++#
++# CONFIG_I2O is not set
++# CONFIG_I2O_BLOCK is not set
++# CONFIG_I2O_LAN is not set
++# CONFIG_I2O_SCSI is not set
++# CONFIG_I2O_PROC is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Input core support
++#
++CONFIG_INPUT=y
++CONFIG_INPUT_KEYBDEV=y
++CONFIG_INPUT_RAMSES_KEYB=y
++CONFIG_INPUT_RAMSES_WEDGE=y
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_MX1TS is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_SERIAL=y
++CONFIG_SERIAL_CONSOLE=y
++# CONFIG_SERIAL_EXTENDED is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_ANAKIN is not set
++# CONFIG_SERIAL_ANAKIN_CONSOLE is not set
++# CONFIG_SERIAL_AMBA is not set
++# CONFIG_SERIAL_AMBA_CONSOLE is not set
++# CONFIG_SERIAL_CLPS711X is not set
++# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
++# CONFIG_SERIAL_21285 is not set
++# CONFIG_SERIAL_21285_OLD is not set
++# CONFIG_SERIAL_21285_CONSOLE is not set
++# CONFIG_SERIAL_UART00 is not set
++# CONFIG_SERIAL_UART00_CONSOLE is not set
++# CONFIG_SERIAL_SA1100 is not set
++# CONFIG_SERIAL_SA1100_CONSOLE is not set
++# CONFIG_SERIAL_OMAHA is not set
++# CONFIG_SERIAL_OMAHA_CONSOLE is not set
++# CONFIG_SERIAL_AT91 is not set
++# CONFIG_SERIAL_AT91_CONSOLE is not set
++# CONFIG_SERIAL_8250 is not set
++# CONFIG_SERIAL_8250_CONSOLE is not set
++# CONFIG_SERIAL_8250_EXTENDED is not set
++# CONFIG_SERIAL_8250_MANY_PORTS is not set
++# CONFIG_SERIAL_8250_SHARE_IRQ is not set
++# CONFIG_SERIAL_8250_DETECT_IRQ is not set
++# CONFIG_SERIAL_8250_MULTIPORT is not set
++# CONFIG_SERIAL_8250_HUB6 is not set
++CONFIG_UNIX98_PTYS=y
++CONFIG_UNIX98_PTY_COUNT=32
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++CONFIG_I2C_PXA_ALGO=y
++CONFIG_I2C_PXA_ADAP=y
++CONFIG_I2C_CHARDEV=m
++CONFIG_I2C_PROC=m
++# CONFIG_I2C_DS1307 is not set
++CONFIG_I2C_DS1337=y
++
++#
++# L3 serial bus support
++#
++# CONFIG_L3 is not set
++# CONFIG_L3_ALGOBIT is not set
++# CONFIG_L3_BIT_SA1100_GPIO is not set
++# CONFIG_L3_SA1111 is not set
++# CONFIG_BIT_SA1100_GPIO is not set
++
++#
++# Mice
++#
++# CONFIG_BUSMOUSE is not set
++# CONFIG_MOUSE is not set
++
++#
++# Joysticks
++#
++# CONFIG_INPUT_GAMEPORT is not set
++# CONFIG_INPUT_NS558 is not set
++# CONFIG_INPUT_LIGHTNING is not set
++# CONFIG_INPUT_PCIGAME is not set
++# CONFIG_INPUT_CS461X is not set
++# CONFIG_INPUT_EMU10K1 is not set
++# CONFIG_INPUT_SERIO is not set
++# CONFIG_INPUT_SERPORT is not set
++# CONFIG_INPUT_ANALOG is not set
++# CONFIG_INPUT_A3D is not set
++# CONFIG_INPUT_ADI is not set
++# CONFIG_INPUT_COBRA is not set
++# CONFIG_INPUT_GF2K is not set
++# CONFIG_INPUT_GRIP is not set
++# CONFIG_INPUT_INTERACT is not set
++# CONFIG_INPUT_TMDC is not set
++# CONFIG_INPUT_SIDEWINDER is not set
++# CONFIG_INPUT_IFORCE_USB is not set
++# CONFIG_INPUT_IFORCE_232 is not set
++# CONFIG_INPUT_WARRIOR is not set
++# CONFIG_INPUT_MAGELLAN is not set
++# CONFIG_INPUT_SPACEORB is not set
++# CONFIG_INPUT_SPACEBALL is not set
++# CONFIG_INPUT_STINGER is not set
++# CONFIG_INPUT_DB9 is not set
++# CONFIG_INPUT_GAMECON is not set
++# CONFIG_INPUT_TURBOGRAFX is not set
++# CONFIG_QIC02_TAPE is not set
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_IPMI_PANIC_EVENT is not set
++# CONFIG_IPMI_DEVICE_INTERFACE is not set
++# CONFIG_IPMI_KCS is not set
++# CONFIG_IPMI_WATCHDOG is not set
++
++#
++# Watchdog Cards
++#
++# CONFIG_WATCHDOG is not set
++# CONFIG_SCx200_GPIO is not set
++# CONFIG_AMD_PM768 is not set
++# CONFIG_NVRAM is not set
++CONFIG_RTC=m
++CONFIG_PXA_RTC=m
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++# CONFIG_FTAPE is not set
++# CONFIG_AGP is not set
++# CONFIG_DRM is not set
++
++#
++# PCMCIA character devices
++#
++# CONFIG_PCMCIA_SERIAL_CS is not set
++# CONFIG_SYNCLINK_CS is not set
++
++#
++# Multimedia devices
++#
++CONFIG_VIDEO_DEV=m
++
++#
++# Video For Linux
++#
++CONFIG_VIDEO_PROC_FS=y
++# CONFIG_I2C_PARPORT is not set
++# CONFIG_VIDEO_BT848 is not set
++# CONFIG_VIDEO_PMS is not set
++# CONFIG_VIDEO_CPIA is not set
++# CONFIG_VIDEO_SAA5249 is not set
++# CONFIG_TUNER_3036 is not set
++# CONFIG_VIDEO_STRADIS is not set
++# CONFIG_VIDEO_ZORAN is not set
++# CONFIG_VIDEO_ZORAN_BUZ is not set
++# CONFIG_VIDEO_ZORAN_DC10 is not set
++# CONFIG_VIDEO_ZORAN_LML33 is not set
++# CONFIG_VIDEO_ZR36120 is not set
++# CONFIG_VIDEO_MEYE is not set
++# CONFIG_VIDEO_CYBERPRO is not set
++
++#
++# Radio Adapters
++#
++# CONFIG_RADIO_GEMTEK_PCI is not set
++# CONFIG_RADIO_MAXIRADIO is not set
++# CONFIG_RADIO_MAESTRO is not set
++# CONFIG_RADIO_MIROPCM20 is not set
++
++#
++# File systems
++#
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_REISERFS_CHECK is not set
++# CONFIG_REISERFS_PROC_INFO is not set
++# CONFIG_ADFS_FS is not set
++# CONFIG_ADFS_FS_RW is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BEFS_DEBUG is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_JBD is not set
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FAT_FS=m
++CONFIG_MSDOS_FS=m
++# CONFIG_UMSDOS_FS is not set
++CONFIG_VFAT_FS=m
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_CRAMFS=m
++# CONFIG_CRAMFS_LINEAR is not set
++# CONFIG_CRAMFS_LINEAR_XIP is not set
++# CONFIG_ROOT_CRAMFS_LINEAR is not set
++CONFIG_TMPFS=y
++CONFIG_RAMFS=y
++# CONFIG_ISO9660_FS is not set
++# CONFIG_JOLIET is not set
++# CONFIG_ZISOFS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_JFS_DEBUG is not set
++# CONFIG_JFS_STATISTICS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_NTFS_FS is not set
++# CONFIG_NTFS_RW is not set
++# CONFIG_HPFS_FS is not set
++CONFIG_PROC_FS=y
++CONFIG_DEVFS_FS=y
++CONFIG_DEVFS_MOUNT=y
++# CONFIG_DEVFS_DEBUG is not set
++# CONFIG_DEVPTS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_QNX4FS_RW is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_EXT2_FS=m
++# CONFIG_SYSV_FS is not set
++# CONFIG_UDF_FS is not set
++# CONFIG_UDF_RW is not set
++# CONFIG_UFS_FS is not set
++# CONFIG_UFS_FS_WRITE is not set
++
++#
++# Network File Systems
++#
++# CONFIG_CODA_FS is not set
++# CONFIG_INTERMEZZO_FS is not set
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++CONFIG_ROOT_NFS=y
++# CONFIG_NFSD is not set
++# CONFIG_NFSD_V3 is not set
++# CONFIG_NFSD_TCP is not set
++CONFIG_SUNRPC=y
++CONFIG_LOCKD=y
++# CONFIG_SMB_FS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_NCPFS_PACKET_SIGNING is not set
++# CONFIG_NCPFS_IOCTL_LOCKING is not set
++# CONFIG_NCPFS_STRONG is not set
++# CONFIG_NCPFS_NFS_NS is not set
++# CONFIG_NCPFS_OS2_NS is not set
++# CONFIG_NCPFS_SMALLDOS is not set
++# CONFIG_NCPFS_NLS is not set
++# CONFIG_NCPFS_EXTRAS is not set
++# CONFIG_ZISOFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_SMB_NLS is not set
++CONFIG_NLS=y
++
++#
++# Native Language Support
++#
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=m
++CONFIG_NLS_CODEPAGE_737=m
++CONFIG_NLS_CODEPAGE_775=m
++CONFIG_NLS_CODEPAGE_850=m
++CONFIG_NLS_CODEPAGE_852=m
++CONFIG_NLS_CODEPAGE_855=m
++CONFIG_NLS_CODEPAGE_857=m
++CONFIG_NLS_CODEPAGE_860=m
++CONFIG_NLS_CODEPAGE_861=m
++CONFIG_NLS_CODEPAGE_862=m
++CONFIG_NLS_CODEPAGE_863=m
++CONFIG_NLS_CODEPAGE_864=m
++CONFIG_NLS_CODEPAGE_865=m
++CONFIG_NLS_CODEPAGE_866=m
++CONFIG_NLS_CODEPAGE_869=m
++CONFIG_NLS_CODEPAGE_936=m
++CONFIG_NLS_CODEPAGE_950=m
++CONFIG_NLS_CODEPAGE_932=m
++CONFIG_NLS_CODEPAGE_949=m
++CONFIG_NLS_CODEPAGE_874=m
++CONFIG_NLS_ISO8859_8=m
++CONFIG_NLS_CODEPAGE_1250=m
++CONFIG_NLS_CODEPAGE_1251=m
++CONFIG_NLS_ISO8859_1=m
++CONFIG_NLS_ISO8859_2=m
++CONFIG_NLS_ISO8859_3=m
++CONFIG_NLS_ISO8859_4=m
++CONFIG_NLS_ISO8859_5=m
++CONFIG_NLS_ISO8859_6=m
++CONFIG_NLS_ISO8859_7=m
++CONFIG_NLS_ISO8859_9=m
++CONFIG_NLS_ISO8859_13=m
++CONFIG_NLS_ISO8859_14=m
++CONFIG_NLS_ISO8859_15=m
++CONFIG_NLS_KOI8_R=m
++CONFIG_NLS_KOI8_U=m
++CONFIG_NLS_UTF8=m
++
++#
++# Console drivers
++#
++CONFIG_PC_KEYMAP=y
++# CONFIG_VGA_CONSOLE is not set
++
++#
++# Frame-buffer support
++#
++CONFIG_FB=y
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_FB_ACORN is not set
++# CONFIG_FB_ANAKIN is not set
++# CONFIG_FB_CLPS711X is not set
++# CONFIG_FB_SA1100 is not set
++# CONFIG_FB_DBMX1 is not set
++CONFIG_FB_PXA=y
++# CONFIG_FB_PXA_8BPP is not set
++CONFIG_FB_PXA_16BPP=y
++# CONFIG_FB_CYBER2000 is not set
++# CONFIG_FB_VIRTUAL is not set
++CONFIG_FBCON_ADVANCED=y
++# CONFIG_FBCON_MFB is not set
++# CONFIG_FBCON_CFB2 is not set
++# CONFIG_FBCON_CFB4 is not set
++# CONFIG_FBCON_CFB8 is not set
++CONFIG_FBCON_CFB16=y
++# CONFIG_FBCON_CFB24 is not set
++# CONFIG_FBCON_CFB32 is not set
++# CONFIG_FBCON_AFB is not set
++# CONFIG_FBCON_ILBM is not set
++# CONFIG_FBCON_IPLAN2P2 is not set
++# CONFIG_FBCON_IPLAN2P4 is not set
++# CONFIG_FBCON_IPLAN2P8 is not set
++# CONFIG_FBCON_MAC is not set
++# CONFIG_FBCON_VGA_PLANES is not set
++# CONFIG_FBCON_VGA is not set
++# CONFIG_FBCON_HGA is not set
++# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
++# CONFIG_FBCON_FONTS is not set
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++# CONFIG_SOUND_ALI5455 is not set
++# CONFIG_SOUND_BT878 is not set
++# CONFIG_SOUND_CMPCI is not set
++# CONFIG_SOUND_EMU10K1 is not set
++# CONFIG_MIDI_EMU10K1 is not set
++# CONFIG_SOUND_FUSION is not set
++# CONFIG_SOUND_CS4281 is not set
++# CONFIG_SOUND_ES1370 is not set
++# CONFIG_SOUND_ES1371 is not set
++# CONFIG_SOUND_ESSSOLO1 is not set
++# CONFIG_SOUND_MAESTRO is not set
++# CONFIG_SOUND_MAESTRO3 is not set
++# CONFIG_SOUND_FORTE is not set
++# CONFIG_SOUND_ICH is not set
++# CONFIG_SOUND_RME96XX is not set
++# CONFIG_SOUND_SONICVIBES is not set
++# CONFIG_SOUND_TRIDENT is not set
++# CONFIG_SOUND_MSNDCLAS is not set
++# CONFIG_SOUND_MSNDPIN is not set
++# CONFIG_SOUND_VIA82CXXX is not set
++# CONFIG_MIDI_VIA82CXXX is not set
++# CONFIG_SOUND_OSS is not set
++# CONFIG_SOUND_VIDC is not set
++# CONFIG_SOUND_WAVEARTIST is not set
++CONFIG_SOUND_PXA_AC97=y
++# CONFIG_SOUND_TVMIXER is not set
++
++#
++# Multimedia Capabilities Port drivers
++#
++CONFIG_MCP=y
++# CONFIG_MCP_SA1100 is not set
++# CONFIG_MCP_UCB1200 is not set
++# CONFIG_MCP_UCB1200_AUDIO is not set
++# CONFIG_MCP_UCB1200_TS is not set
++CONFIG_MCP_UCB1400_TS=y
++
++#
++# USB support
++#
++CONFIG_USB=m
++# CONFIG_USB_DEBUG is not set
++CONFIG_USB_DEVICEFS=y
++# CONFIG_USB_BANDWIDTH is not set
++# CONFIG_USB_EHCI_HCD is not set
++# CONFIG_USB_UHCI is not set
++# CONFIG_USB_UHCI_ALT is not set
++# CONFIG_USB_OHCI is not set
++# CONFIG_USB_OHCI_SA1111 is not set
++CONFIG_USB_SL811HS_ALT=m
++CONFIG_USB_AUDIO=m
++CONFIG_USB_EMI26=m
++# CONFIG_USB_BLUETOOTH is not set
++CONFIG_USB_MIDI=m
++CONFIG_USB_STORAGE=m
++CONFIG_USB_STORAGE_DEBUG=y
++CONFIG_USB_STORAGE_DATAFAB=y
++CONFIG_USB_STORAGE_FREECOM=y
++# CONFIG_USB_STORAGE_ISD200 is not set
++CONFIG_USB_STORAGE_DPCM=y
++CONFIG_USB_STORAGE_HP8200e=y
++CONFIG_USB_STORAGE_SDDR09=y
++CONFIG_USB_STORAGE_SDDR55=y
++CONFIG_USB_STORAGE_JUMPSHOT=y
++# CONFIG_USB_ACM is not set
++CONFIG_USB_PRINTER=m
++CONFIG_USB_HID=m
++CONFIG_USB_HIDINPUT=y
++CONFIG_USB_HIDDEV=y
++CONFIG_USB_KBD=m
++# CONFIG_USB_MOUSE is not set
++# CONFIG_USB_AIPTEK is not set
++# CONFIG_USB_WACOM is not set
++# CONFIG_USB_KBTAB is not set
++# CONFIG_USB_POWERMATE is not set
++CONFIG_USB_DC2XX=m
++CONFIG_USB_MDC800=m
++CONFIG_USB_SCANNER=m
++CONFIG_USB_MICROTEK=m
++CONFIG_USB_HPUSBSCSI=m
++CONFIG_USB_IBMCAM=m
++CONFIG_USB_KONICAWC=m
++CONFIG_USB_OV511=m
++CONFIG_USB_PWC=m
++CONFIG_USB_SE401=m
++CONFIG_USB_STV680=m
++CONFIG_USB_VICAM=m
++# CONFIG_USB_DSBR is not set
++# CONFIG_USB_DABUSB is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_CDCETHER is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_USB_USS720 is not set
++
++#
++# USB Serial Converter support
++#
++CONFIG_USB_SERIAL=m
++# CONFIG_USB_SERIAL_DEBUG is not set
++CONFIG_USB_SERIAL_GENERIC=y
++CONFIG_USB_SERIAL_BELKIN=m
++CONFIG_USB_SERIAL_WHITEHEAT=m
++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
++CONFIG_USB_SERIAL_EMPEG=m
++# CONFIG_USB_SERIAL_FTDI_SIO is not set
++# CONFIG_USB_SERIAL_VISOR is not set
++# CONFIG_USB_SERIAL_IPAQ is not set
++# CONFIG_USB_SERIAL_IR is not set
++# CONFIG_USB_SERIAL_EDGEPORT is not set
++# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
++# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
++# CONFIG_USB_SERIAL_KEYSPAN is not set
++# CONFIG_USB_SERIAL_MCT_U232 is not set
++# CONFIG_USB_SERIAL_KLSI is not set
++# CONFIG_USB_SERIAL_KOBIL_SCT is not set
++# CONFIG_USB_SERIAL_PL2303 is not set
++# CONFIG_USB_SERIAL_CYBERJACK is not set
++# CONFIG_USB_SERIAL_XIRCOM is not set
++# CONFIG_USB_SERIAL_OMNINET is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_TIGL is not set
++# CONFIG_USB_BRLVGER is not set
++# CONFIG_USB_LCD is not set
++
++#
++# Bluetooth support
++#
++# CONFIG_BLUEZ is not set
++
++#
++# Kernel hacking
++#
++CONFIG_FRAME_POINTER=y
++# CONFIG_DEBUG_USER is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_NO_PGT_CACHE is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_WAITQ is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_ERRORS is not set
++# CONFIG_DEBUG_LL is not set
++# CONFIG_DEBUG_DC21285_PORT is not set
++# CONFIG_DEBUG_CLPS711X_UART2 is not set
++
++#
++# Library routines
++#
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+--- linux-2.4.21/arch/arm/mach-pxa/Makefile~pm
++++ linux-2.4.21/arch/arm/mach-pxa/Makefile
+@@ -14,8 +14,11 @@
+ obj-n :=
+ obj-  :=
+-export-objs := generic.o irq.o dma.o sa1111.o \
+-               usb_ctl.o usb_recv.o usb_send.o
++export-objs := apm.o generic.o irq.o dma.o sa1111.o \
++               usb_ctl.o usb_recv.o usb_send.o pm.o
++
++
++export-objs += ramses.o
+ # Common support (must be linked before board specific support)
+ obj-y += generic.o irq.o dma.o
+@@ -27,6 +30,7 @@
+ obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
+ obj-$(CONFIG_ARCH_PXA_CERF) += cerf.o
+ obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
++obj-$(CONFIG_ARCH_RAMSES) += ramses.o
+ obj-$(CONFIG_ARCH_TRIZEPS2) += trizeps2.o
+ # Support for blinky lights
+@@ -48,6 +52,7 @@
+ # Misc features
+ obj-$(CONFIG_PM) += pm.o sleep.o
++obj-$(CONFIG_APM) += apm.o
+ obj-$(CONFIG_CPU_FREQ) += cpu-pxa.o
+ include $(TOPDIR)/Rules.make
+--- /dev/null
++++ linux-2.4.21/arch/arm/mach-pxa/apm.c
+@@ -0,0 +1,491 @@
++/*
++ * bios-less APM driver for ARM Linux 
++ *  Jamey Hicks <jamey@crl.dec.com>
++ *  adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com)
++ *
++ * APM 1.2 Reference:
++ *   Intel Corporation, Microsoft Corporation. Advanced Power Management
++ *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
++ *
++ * [This document is available from Microsoft at:
++ *    http://www.microsoft.com/hwdev/busbios/amp_12.htm]
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++
++#include <linux/poll.h>
++#include <linux/types.h>
++#include <linux/stddef.h>
++#include <linux/timer.h>
++#include <linux/fcntl.h>
++#include <linux/slab.h>
++#include <linux/stat.h>
++#include <linux/proc_fs.h>
++#include <linux/miscdevice.h>
++#include <linux/apm_bios.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/pm.h>
++#include <linux/kernel.h>
++#include <linux/smp_lock.h>
++
++#include <asm/system.h>
++#include <asm/hardware.h>
++
++#ifdef CONFIG_SA1100_H3XXX
++#include <asm/arch/h3600_hal.h>
++#endif
++
++#include "pm-common.c"
++
++struct apm_bios_info apm_bios_info = {
++        /* this driver simulates APM version 1.2 */
++        version: 0x102,
++        flags: APM_32_BIT_SUPPORT
++};
++
++/*
++ * The apm_bios device is one of the misc char devices.
++ * This is its minor number.
++ */
++#define       APM_MINOR_DEV   134
++
++/*
++ * See Documentation/Config.help for the configuration options.
++ *
++ * Various options can be changed at boot time as follows:
++ * (We allow underscores for compatibility with the modules code)
++ *    apm=on/off                      enable/disable APM
++ *        [no-]power[-_]off           power off on shutdown
++ */
++
++/*
++ * Maximum number of events stored
++ */
++#define APM_MAX_EVENTS                10
++
++/*
++ * The per-file APM data
++ */
++struct apm_user {
++      int             magic;
++      struct apm_user *       next;
++      int             suser: 1;
++      int             suspend_wait: 1;
++      int             suspend_result;
++      int             suspends_pending;
++      int             standbys_pending;
++      int             suspends_read;
++      int             standbys_read;
++      int             event_head;
++      int             event_tail;
++      apm_event_t     events[APM_MAX_EVENTS];
++};
++
++/*
++ * The magic number in apm_user
++ */
++#define APM_BIOS_MAGIC                0x4101
++
++/*
++ * Local variables
++ */
++
++#ifdef CONFIG_APM_RTC_IS_GMT
++#define       clock_cmos_diff 0
++#define       got_clock_diff  1
++#endif
++static int                    apm_disabled;
++#ifdef CONFIG_SMP
++static int                    power_off;
++#else
++static int                    power_off = 1;
++#endif
++static int                    exit_kapmd;
++static int                    kapmd_running;
++
++static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
++static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
++static struct apm_user *      user_list = NULL;
++
++static char                   driver_version[] = "1.13";      /* no spaces */
++
++typedef struct lookup_t {
++      int     key;
++      char *  msg;
++} lookup_t;
++
++static const lookup_t error_table[] = {
++/* N/A        { APM_SUCCESS,          "Operation succeeded" }, */
++      { APM_DISABLED,         "Power management disabled" },
++      { APM_CONNECTED,        "Real mode interface already connected" },
++      { APM_NOT_CONNECTED,    "Interface not connected" },
++      { APM_16_CONNECTED,     "16 bit interface already connected" },
++/* N/A        { APM_16_UNSUPPORTED,   "16 bit interface not supported" }, */
++      { APM_32_CONNECTED,     "32 bit interface already connected" },
++      { APM_32_UNSUPPORTED,   "32 bit interface not supported" },
++      { APM_BAD_DEVICE,       "Unrecognized device ID" },
++      { APM_BAD_PARAM,        "Parameter out of range" },
++      { APM_NOT_ENGAGED,      "Interface not engaged" },
++      { APM_BAD_FUNCTION,     "Function not supported" },
++      { APM_RESUME_DISABLED,  "Resume timer disabled" },
++      { APM_BAD_STATE,        "Unable to enter requested state" },
++/* N/A        { APM_NO_EVENTS,        "No events pending" }, */
++      { APM_NO_ERROR,         "BIOS did not set a return code" },
++      { APM_NOT_PRESENT,      "No APM present" }
++};
++#define ERROR_COUNT   (sizeof(error_table)/sizeof(lookup_t))
++
++static int (*apm_get_power_status)(u_char *ac_line_status,
++                                u_char *battery_status,
++                                u_char *battery_flag,
++                                u_char *battery_percentage,
++                                u_short *battery_life) = 0;
++
++void apm_register_get_power_status( int (*fn)(u_char *ac_line_status,
++                                u_char *battery_status,
++                                u_char *battery_flag,
++                                u_char *battery_percentage,
++                                u_short *battery_life))
++{
++      apm_get_power_status = fn;
++}
++
++static int queue_empty(struct apm_user *as)
++{
++      return as->event_head == as->event_tail;
++}
++
++static apm_event_t get_queued_event(struct apm_user *as)
++{
++      as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
++      return as->events[as->event_tail];
++}
++
++static int check_apm_user(struct apm_user *as, const char *func)
++{
++      if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
++              printk(KERN_ERR "apm: %s passed bad filp\n", func);
++              return 1;
++      }
++      return 0;
++}
++
++static ssize_t do_read(struct file *fp, char *buf, size_t count, loff_t *ppos)
++{
++      struct apm_user *       as;
++      int                     i;
++      apm_event_t             event;
++      DECLARE_WAITQUEUE(wait, current);
++
++      as = fp->private_data;
++      if (check_apm_user(as, "read"))
++              return -EIO;
++      if (count < sizeof(apm_event_t))
++              return -EINVAL;
++      if (queue_empty(as)) {
++              if (fp->f_flags & O_NONBLOCK)
++                      return -EAGAIN;
++              add_wait_queue(&apm_waitqueue, &wait);
++                printk("do_read: waiting\n");
++repeat:
++              set_current_state(TASK_INTERRUPTIBLE);
++              if (queue_empty(as) && !signal_pending(current)) {
++                      schedule();
++                      goto repeat;
++              }
++              set_current_state(TASK_RUNNING);
++              remove_wait_queue(&apm_waitqueue, &wait);
++      }
++      i = count;
++      while ((i >= sizeof(event)) && !queue_empty(as)) {
++              event = get_queued_event(as);
++                printk("  do_read: event=%d\n", event);
++              if (copy_to_user(buf, &event, sizeof(event))) {
++                      if (i < count)
++                              break;
++                      return -EFAULT;
++              }
++              switch (event) {
++              case APM_SYS_SUSPEND:
++              case APM_USER_SUSPEND:
++                      as->suspends_read++;
++                      break;
++
++              case APM_SYS_STANDBY:
++              case APM_USER_STANDBY:
++                      as->standbys_read++;
++                      break;
++              }
++              buf += sizeof(event);
++              i -= sizeof(event);
++      }
++      if (i < count)
++              return count - i;
++      if (signal_pending(current))
++              return -ERESTARTSYS;
++      return 0;
++}
++
++static unsigned int do_poll(struct file *fp, poll_table * wait)
++{
++      struct apm_user * as;
++
++      as = fp->private_data;
++      if (check_apm_user(as, "poll"))
++              return 0;
++      poll_wait(fp, &apm_waitqueue, wait);
++      if (!queue_empty(as))
++              return POLLIN | POLLRDNORM;
++      return 0;
++}
++
++static int do_ioctl(struct inode * inode, struct file *filp,
++                  u_int cmd, u_long arg)
++{
++      struct apm_user *       as;
++
++      as = filp->private_data;
++      if (check_apm_user(as, "ioctl"))
++              return -EIO;
++      if (!as->suser)
++              return -EPERM;
++      switch (cmd) {
++        case APM_IOC_SUSPEND:
++              pm_suggest_suspend();
++              break;
++      default:
++              printk("//hs %x\n", cmd);
++              return -EINVAL;
++      }
++      return 0;
++}
++
++static int do_release(struct inode * inode, struct file * filp)
++{
++      struct apm_user *       as;
++
++      as = filp->private_data;
++      if (check_apm_user(as, "release"))
++              return 0;
++      filp->private_data = NULL;
++      lock_kernel();
++      unlock_kernel();
++      kfree(as);
++      return 0;
++}
++
++static int do_open(struct inode * inode, struct file * filp)
++{
++      struct apm_user *       as;
++
++      as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
++      if (as == NULL) {
++              printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
++                     sizeof(*as));
++              return -ENOMEM;
++      }
++      as->magic = APM_BIOS_MAGIC;
++      as->event_tail = as->event_head = 0;
++      as->suspends_pending = as->standbys_pending = 0;
++      as->suspends_read = as->standbys_read = 0;
++      /*
++       * XXX - this is a tiny bit broken, when we consider BSD
++         * process accounting. If the device is opened by root, we
++       * instantly flag that we used superuser privs. Who knows,
++       * we might close the device immediately without doing a
++       * privileged operation -- cevans
++       */
++      as->suser = capable(CAP_SYS_ADMIN);
++      as->next = user_list;
++      user_list = as;
++      filp->private_data = as;
++      return 0;
++}
++
++static int apm_get_info(char *buf, char **start, off_t fpos, int length)
++{
++      char *          p;
++      unsigned short  dx;
++      unsigned short  error;
++      unsigned char   ac_line_status = 0xff;
++      unsigned char   battery_status = 0xff;
++      unsigned char   battery_flag   = 0xff;
++        unsigned char   percentage     = 0xff;
++      int             time_units     = -1;
++      char            *units         = "?";
++
++      p = buf;
++
++      if ( (smp_num_cpus == 1) && 
++              apm_get_power_status &&
++          !(error = apm_get_power_status(&ac_line_status,
++                                           &battery_status, &battery_flag, &percentage, &dx))) {
++              if (apm_bios_info.version > 0x100) {
++                      if (dx != 0xffff) {
++                              units = (dx & 0x8000) ? "min" : "sec";
++                              time_units = dx & 0x7fff;
++                      }
++              }
++      }
++      /* Arguments, with symbols from linux/apm_bios.h.  Information is
++         from the Get Power Status (0x0a) call unless otherwise noted.
++
++         0) Linux driver version (this will change if format changes)
++         1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
++         2) APM flags from APM Installation Check (0x00):
++            bit 0: APM_16_BIT_SUPPORT
++            bit 1: APM_32_BIT_SUPPORT
++            bit 2: APM_IDLE_SLOWS_CLOCK
++            bit 3: APM_BIOS_DISABLED
++            bit 4: APM_BIOS_DISENGAGED
++         3) AC line status
++            0x00: Off-line
++            0x01: On-line
++            0x02: On backup power (BIOS >= 1.1 only)
++            0xff: Unknown
++         4) Battery status
++            0x00: High
++            0x01: Low
++            0x02: Critical
++            0x03: Charging
++            0x04: Selected battery not present (BIOS >= 1.2 only)
++            0xff: Unknown
++         5) Battery flag
++            bit 0: High
++            bit 1: Low
++            bit 2: Critical
++            bit 3: Charging
++            bit 7: No system battery
++            0xff: Unknown
++         6) Remaining battery life (percentage of charge):
++            0-100: valid
++            -1: Unknown
++         7) Remaining battery life (time units):
++            Number of remaining minutes or seconds
++            -1: Unknown
++         8) min = minutes; sec = seconds */
++
++      p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
++                   driver_version,
++                   (apm_bios_info.version >> 8) & 0xff,
++                   apm_bios_info.version & 0xff,
++                   apm_bios_info.flags,
++                   ac_line_status,
++                   battery_status,
++                   battery_flag,
++                   percentage,
++                   time_units,
++                   units);
++
++      return p - buf;
++}
++
++#ifndef MODULE
++static int __init apm_setup(char *str)
++{
++      int     invert;
++
++printk("//hs apm_setup\n");
++      while ((str != NULL) && (*str != '\0')) {
++              if (strncmp(str, "off", 3) == 0)
++                      apm_disabled = 1;
++              if (strncmp(str, "on", 2) == 0)
++                      apm_disabled = 0;
++              invert = (strncmp(str, "no-", 3) == 0);
++              if (invert)
++                      str += 3;
++              if ((strncmp(str, "power-off", 9) == 0) ||
++                  (strncmp(str, "power_off", 9) == 0))
++                      power_off = !invert;
++              str = strchr(str, ',');
++              if (str != NULL)
++                      str += strspn(str, ", \t");
++      }
++      return 1;
++}
++
++__setup("apm=", apm_setup);
++#endif
++
++static struct file_operations apm_bios_fops = {
++      owner:          THIS_MODULE,
++      read:           do_read,
++      poll:           do_poll,
++      ioctl:          do_ioctl,
++      open:           do_open,
++      release:        do_release,
++};
++
++static struct miscdevice apm_device = {
++      APM_MINOR_DEV,
++      "apm_bios",
++      &apm_bios_fops
++};
++
++#define APM_INIT_ERROR_RETURN return -1
++
++/*
++ * Just start the APM thread. We do NOT want to do APM BIOS
++ * calls from anything but the APM thread, if for no other reason
++ * than the fact that we don't trust the APM BIOS. This way,
++ * most common APM BIOS problems that lead to protection errors
++ * etc will have at least some level of being contained...
++ *
++ * In short, if something bad happens, at least we have a choice
++ * of just killing the apm thread..
++ */
++static int __init apm_init(void)
++{
++      if (apm_bios_info.version == 0) {
++              printk(KERN_INFO "apm: BIOS not found.\n");
++              APM_INIT_ERROR_RETURN;
++      }
++      printk(KERN_INFO
++              "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
++              ((apm_bios_info.version >> 8) & 0xff),
++              (apm_bios_info.version & 0xff),
++              apm_bios_info.flags,
++              driver_version);
++
++      if (apm_disabled) {
++              printk(KERN_NOTICE "apm: disabled on user request.\n");
++              APM_INIT_ERROR_RETURN;
++      }
++
++      if (PM_IS_ACTIVE()) {
++              printk(KERN_NOTICE "apm: overridden by ACPI.\n");
++              APM_INIT_ERROR_RETURN;
++      }
++      pm_active = 1;
++
++      create_proc_info_entry("apm", 0, NULL, apm_get_info);
++
++      misc_register(&apm_device);
++
++      return 0;
++}
++
++module_init(apm_init);
++
++#ifdef MODULE
++static void __exit apm_exit(void)
++{
++      misc_deregister(&apm_device);
++      remove_proc_entry("apm", NULL);
++      if (power_off)
++              pm_power_off = NULL;
++      exit_kapmd = 1;
++      while (kapmd_running)
++              schedule();
++      pm_active = 0;
++}
++
++module_exit(apm_exit);
++
++MODULE_AUTHOR("Jamey Hicks, pulling bits from original by Stephen Rothwell");
++MODULE_DESCRIPTION("A minimal emulation of APM");
++MODULE_PARM(power_off, "i");
++MODULE_PARM_DESC(power_off, "Enable power off");
++#endif
+--- linux-2.4.21/arch/arm/mach-pxa/cpu-pxa.c~ramses-corevolt
++++ linux-2.4.21/arch/arm/mach-pxa/cpu-pxa.c
+@@ -39,7 +39,7 @@
+ #include <asm/hardware.h>
+-#define DEBUGGING     1
++#define DEBUGGING     0
+ #if DEBUGGING
+ static unsigned int freq_debug = DEBUGGING;
+@@ -52,6 +52,7 @@
+       unsigned int khz;
+       unsigned int cccr;
+       unsigned int pxbus;
++      unsigned int corevolt;
+ } pxa_freqs_t;
+ #define CCLKCFG_TURBO         0x1
+@@ -79,23 +80,23 @@
+ static pxa_freqs_t pxa250_valid_freqs[] =
+ {
+-      {199100, 0x141, 99}, /* mem= 99, run=199, turbo=199, PXbus= 99 */
+-      {298600, 0x1c1, 99}, /* mem= 99, run=199, turbo=298, PXbus= 99 */
+-      {398100, 0x241, 99}, /* mem= 99, run=199, turbo=398, PXbus= 99 */
++      {199100, 0x141, 99, 115}, /* mem= 99, run=199, turbo=199, PXbus= 99 */
++      {298600, 0x1c1, 99, 125}, /* mem= 99, run=199, turbo=298, PXbus= 99 */
++      {398100, 0x241, 99, 135}, /* mem= 99, run=199, turbo=398, PXbus= 99 */
+       {0,0}
+ };
+ static pxa_freqs_t pxa255_valid_freqs[] =
+ {
+-      { 99000, 0x121, 50}, /* mem= 99, run= 99, turbo= 99, PXbus= 50 */
+-OC(   {118000, 0x122, 59},)/* mem=118, run=118, turbo=118, PXbus= 59 OC'd mem */
+-      {199100, 0x141, 99}, /* mem= 99, run=199, turbo=199, PXbus= 99 */
+-OC(   {236000, 0x142,118},)/* mem=118, run=236, turbo=236, PXbus=118 OC'd mem */
+-      {298600, 0x1c1, 99}, /* mem= 99, run=199, turbo=298, PXbus= 99 */
+-OC(   {354000, 0x1c2,118},)/* mem=118, run=236, turbo=354, PXbus=118 OC'd mem */
+-      {398099, 0x241, 99}, /* mem= 99, run=199, turbo=398, PXbus= 99 */
+-      {398100, 0x161,196}, /* mem= 99, run=398, turbo=398, PXbus=196 */
+-OC(   {471000, 0x162,236},)/* mem=118, run=471, turbo=471, PXbus=236 OC'd mem/core/bus */
++      { 99000, 0x121, 50, 105}, /* mem= 99, run= 99, turbo= 99, PXbus= 50 */
++OC(   {118000, 0x122, 59, 115},)/* mem=118, run=118, turbo=118, PXbus= 59 OC'd mem */
++      {199100, 0x141, 99, 115}, /* mem= 99, run=199, turbo=199, PXbus= 99 */
++OC(   {236000, 0x142,118, 125},)/* mem=118, run=236, turbo=236, PXbus=118 OC'd mem */
++      {298600, 0x1c1, 99, 125}, /* mem= 99, run=199, turbo=298, PXbus= 99 */
++OC(   {354000, 0x1c2,118, 135},)/* mem=118, run=236, turbo=354, PXbus=118 OC'd mem */
++      {398099, 0x241, 99, 135}, /* mem= 99, run=199, turbo=398, PXbus= 99 */
++      {398100, 0x161,196, 135}, /* mem= 99, run=398, turbo=398, PXbus=196 */
++OC(   {471000, 0x162,236, 150},)/* mem=118, run=471, turbo=471, PXbus=236 OC'd mem/core/bus */
+       {0,0}
+ };
+@@ -109,7 +110,7 @@
+       int i=0;
+       while( pxa_valid_freqs[i].khz)
+       {
+-              if( pxa_valid_freqs[i].khz == khz) 
++              if (pxa_valid_freqs[i].khz == khz) 
+                       return &pxa_valid_freqs[i]; 
+               i++;
+       }
+@@ -141,14 +142,17 @@
+       void *ramstart = phys_to_virt(0xa0000000);
+       pxa_freqs_t *freq_info;
+-      if( ! supported) return;
++      if (! supported) return;
+       freq_info = pxa_get_freq_info( khz);
+-      if( ! freq_info) return;
++      if (! freq_info) return;
++
++      if (freq_info->corevolt > ramses_corevolt_shadow)
++              ramses_set_corevolt(freq_info->corevolt);
+       CCCR = freq_info->cccr;
+-      if( freq_debug)
++      if (freq_debug)
+               printk(KERN_INFO "Changing CPU frequency to %d Mhz (PXbus=%dMhz).\n", 
+                       khz/1000, freq_info->pxbus);
+@@ -184,6 +188,9 @@
+               : "r" (&MDREFR), "r" (CCLKCFG_TURBO|CCLKCFG_FCS), "r" (ramstart)
+               : "r4", "r5");
+       local_irq_restore(flags);
++
++      if (freq_info->corevolt < ramses_corevolt_shadow)
++              ramses_set_corevolt(freq_info->corevolt);
+ }
+ static int pxa_init_freqs( void)
+@@ -191,19 +198,19 @@
+       int cpu_ver; 
+       asm("mrc%? p15, 0, %0, c0, c0" : "=r" (cpu_ver));
+-      if( (cpu_ver & 0xf) <= PXA250_REV_A1)
++      if ((cpu_ver & 0xf) <= PXA250_REV_A1)
+       {
+               return 0;
+       }
+-      if( (cpu_ver & 0xf) <= PXA250_REV_B2)
++      if ((cpu_ver & 0xf) <= PXA250_REV_B2)
+       {
+-              if( freq_debug) printk(KERN_INFO "Using PXA250 frequency points.\n");
++              if (freq_debug) printk(KERN_INFO "Using PXA250 frequency points.\n");
+               pxa_valid_freqs = pxa250_valid_freqs;
+       }       
+       else /* C0 and above */
+       {
+-              if( freq_debug) printk(KERN_INFO "Using PXA255 frequency points.\n");
++              if (freq_debug) printk(KERN_INFO "Using PXA255 frequency points.\n");
+               pxa_valid_freqs = pxa255_valid_freqs;
+       }
+       
+@@ -212,24 +219,23 @@
+ static int __init pxa_clk_init(void)
+ {
+-      if( pxa_init_freqs())
++      if (pxa_init_freqs())
+       {
+-              if( freq_debug) printk(KERN_INFO "Registering CPU frequency change support.\n");
++              if (freq_debug) printk(KERN_INFO "Registering CPU frequency change support.\n");
+               supported = 1;
+               cpufreq_init( get_clk_frequency_khz(0), PXA25x_MIN_FREQ, PXA25x_MAX_FREQ);
+-              cpufreq_setfunctions(pxa_validate_speed, pxa_setspeed);
+       }
+       else
+       {
+-              if( freq_debug) printk(KERN_INFO "Disabling CPU frequency change support.\n");
++              if (freq_debug) printk(KERN_INFO "Disabling CPU frequency change support.\n");
+               /* Note that we have to initialize the generic code in order to 
+                * release a lock (cpufreq_sem). Any registration for freq changes
+                * (e.g. lcd driver) will get blocked otherwise.
+                */
+               cpufreq_init( 0, 0, 0);
+-              cpufreq_setfunctions(pxa_validate_speed, pxa_setspeed);
+       }
++      cpufreq_setfunctions(pxa_validate_speed, pxa_setspeed);
+       return 0;
+ }
+--- linux-2.4.21/arch/arm/mach-pxa/generic.c~pm
++++ linux-2.4.21/arch/arm/mach-pxa/generic.c
+@@ -28,6 +28,11 @@
+ #include <asm/pgtable.h>
+ #include <asm/mach/map.h>
++#ifdef CONFIG_PXA_RTC_HACK
++#include <asm/setup.h>
++#include <linux/bootmem.h>
++#endif
++
+ #include "generic.h"
+ /*
+@@ -139,4 +144,41 @@
+ {
+       iotable_init(standard_io_desc);
+       get_clk_frequency_khz( 1);
++#ifdef CONFIG_PXA_RTC_HACK
++      pxa_rtc_hack_init();
++#endif
++}
++
++\f
++
++#ifdef CONFIG_PXA_RTC_HACK
++unsigned long *save_RCNR = 0;
++
++void pxa_rtc_hack_init(void)
++{
++      /* 
++         This has to be here since I guess the bootmem API is the
++         right choice to allocate the memory during boot
++         place. And we are sure that timer iqr is not already
++         running.
++         - Christian Pellegin <chri@infis.univ.trieste.it>
++      */
++      unsigned long pxa_rtc_hack = 0;
++
++      pxa_rtc_hack = meminfo.bank[meminfo.nr_banks-1].start + 
++              meminfo.bank[meminfo.nr_banks-1].size -
++              PAGE_SIZE;
++      reserve_bootmem(pxa_rtc_hack, PAGE_SIZE);
++      printk("Reserved %ld bytes at %lx for RTC hack\n", 
++             PAGE_SIZE, pxa_rtc_hack);
++      save_RCNR = (unsigned long *)  phys_to_virt(pxa_rtc_hack);
++      if ( (save_RCNR[0] ^ save_RCNR[1]) == 0xffffffff ) {
++              printk("Restoring saved RCNR value to %ld (from %lx)\n", 
++                     save_RCNR[0], (unsigned long) save_RCNR);
++              RCNR = save_RCNR[0];
++      }
++      else {
++              printk("No valid saved RCNR value found at %lx\n", (unsigned long) save_RCNR);
++      }
+ }
++#endif /* CONFIG_PXA_RTC_HACK */
+--- linux-2.4.21/arch/arm/mach-pxa/generic.h~pm
++++ linux-2.4.21/arch/arm/mach-pxa/generic.h
+@@ -17,3 +17,7 @@
+       mi->bank[__nr].size = (__size), \
+       mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27)
++#ifdef CONFIG_PXA_RTC_HACK
++void pxa_rtc_hack_init(void);
++extern unsigned long *save_RCNR;
++#endif
+--- /dev/null
++++ linux-2.4.21/arch/arm/mach-pxa/pm-common.c
+@@ -0,0 +1,285 @@
++/*
++ * SA1100 Power Management Routines
++ *
++ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License.
++ *
++ * History:
++ *
++ * 2001-02-06:        Cliff Brake         Initial code
++ *
++ * 2001-02-25:        Sukjae Cho <sjcho@east.isi.edu> &
++ *            Chester Kuo <chester@linux.org.tw>
++ *                    Save more value for the resume function! Support
++ *                    Bitsy/Assabet/Freebird board
++ *
++ * 2001-08-29:        Nicolas Pitre <nico@cam.org>
++ *                    Cleaned up, pushed platform dependent stuff
++ *                    in the platform specific files.
++ *
++ * 2002-05-27:        Nicolas Pitre   Killed sleep.h and the kmalloced save array.
++ *                            Storage is local on the stack now.
++ */
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/pm.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/sysctl.h>
++#include <linux/errno.h>
++#include <linux/cpufreq.h>
++
++#include <asm/hardware.h>
++#include <asm/memory.h>
++#include <asm/system.h>
++#include <asm/leds.h>
++#include <asm/uaccess.h>
++
++
++#ifdef CONFIG_IPAQ_HANDHELD
++#include <asm/arch-sa1100/h3600_asic.h>
++#endif
++
++#define __KERNEL_SYSCALLS__
++#include <linux/unistd.h>
++
++\f
++
++static char pm_helper_path[128] = "/etc/apm/apmd_proxy";
++extern int exec_usermodehelper(char *path, char **argv, char **envp);
++int debug_pm = 0;
++static int pm_helper_veto = 0;
++
++static int
++run_sbin_pm_helper( pm_request_t action )
++{
++      int i;
++      char *argv[3], *envp[8];
++
++      if (!pm_helper_path[0])
++              return 2;
++
++      if ( action != PM_SUSPEND && action != PM_RESUME )
++              return 1;
++
++      /* Be root */
++      current->uid = current->gid = 0;
++
++      i = 0;
++      argv[i++] = pm_helper_path;
++      argv[i++] = (action == PM_RESUME ? "resume" : "suspend");
++
++      if (action == PM_RESUME)
++              argv[i++]="suspend";
++
++      argv[i] = 0;
++
++      i = 0;
++      /* minimal command environment */
++      envp[i++] = "HOME=/";
++      envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
++      envp[i] = 0;
++
++      /* other stuff we want to pass to /sbin/pm_helper */
++      return exec_usermodehelper (argv [0], argv, envp);
++}
++
++/*
++ * If pm_suggest_suspend_hook is non-NULL, it is called by pm_suggest_suspend.
++ */
++int (*pm_suggest_suspend_hook)(int state);
++EXPORT_SYMBOL(pm_suggest_suspend_hook);
++
++/*
++ * If pm_use_sbin_pm_helper is nonzero, then run_sbin_pm_helper is called before suspend and after resume
++ */
++int pm_use_sbin_pm_helper = 1;
++EXPORT_SYMBOL(pm_use_sbin_pm_helper);
++
++/*
++ * If sysctl_pm_do_suspend_hook is non-NULL, it is called by sysctl_pm_do_suspend.
++ * If it returns a true value, then pm_suspend is not called. 
++ * Use this to hook in apmd, for now.
++ */
++int (*pm_sysctl_suspend_hook)(int state);
++EXPORT_SYMBOL(pm_sysctl_suspend_hook);
++
++int pm_suspend(void);
++
++int pm_suggest_suspend(void)
++{
++      int retval;
++
++      if (pm_suggest_suspend_hook) {
++              if (pm_suggest_suspend_hook(PM_SUSPEND))
++                      return 0;
++      }
++      
++      if (pm_use_sbin_pm_helper) {
++              pid_t pid;
++              int res;
++              int status = 0;
++              unsigned int old_fs;
++              
++              pid = kernel_thread ((int (*) (void *)) run_sbin_pm_helper, (void *) PM_SUSPEND, 0 );
++              if ( pid < 0 )
++                      return pid;
++
++              if (debug_pm)
++                      printk(KERN_CRIT "%s:%d got pid=%d\n", __FUNCTION__, __LINE__, pid);    
++                      
++              old_fs = get_fs ();
++              set_fs (get_ds ());
++              res = waitpid(pid, &status, __WCLONE);
++              set_fs (old_fs);
++      
++              if ( pid != res ) {
++                      if (debug_pm)
++                              printk(KERN_CRIT ": waitpid returned %d (exit_code=%d); not suspending\n", res, status );
++                      
++                      return -1;
++              }
++                      
++              /*if ( WIFEXITED(status) && ( WIFEXITSTATUS(status) != 0 )) {*/
++              if (( status & 0xff7f ) != 0 ) {
++                      if (pm_helper_veto) {
++                              if (debug_pm)
++                                      printk(KERN_CRIT "%s: SUSPEND WAS CANCELLED BY pm_helper (exit status %d)\n", __FUNCTION__, status >> 8);
++                              return -1;
++                      } else {
++                              if (debug_pm)
++                                      printk(KERN_CRIT "%s: pm_helper returned %d, but going ahead anyway\n", __FUNCTION__, status >> 8);
++                      }
++              }
++      }
++
++      if (debug_pm)
++              printk(KERN_CRIT "%s: REALLY SUSPENDING NOW\n", __FUNCTION__ );
++
++      if (pm_sysctl_suspend_hook) {
++              if (pm_sysctl_suspend_hook(PM_SUSPEND))
++                      return 0;
++      }
++
++      retval = pm_suspend();
++      if (retval) {
++              if (debug_pm)
++                      printk(KERN_CRIT "pm_suspend returned %d\n", retval);
++              return retval;
++      }
++
++      if (pm_use_sbin_pm_helper) {
++              pid_t pid;
++              
++              if (debug_pm)
++                      printk(KERN_CRIT "%s: running pm_helper for wakeup\n", __FUNCTION__);
++
++              pid = kernel_thread ((int (*) (void *)) run_sbin_pm_helper, (void *) PM_RESUME, 0 );
++              if ( pid < 0 )
++                      return pid;
++                      
++              if ( pid != waitpid ( pid, NULL, __WCLONE ))
++                      return -1;
++      }
++
++      return 0;
++}
++
++EXPORT_SYMBOL(pm_suggest_suspend);
++
++
++/*
++ * Send us to sleep.
++ */
++int pm_suspend(void)
++{
++      int retval;
++
++      retval = pm_send_all(PM_SUSPEND, (void *)3);
++      if ( retval )
++              return retval;
++
++#ifdef CONFIG_IPAQ_HANDHELD
++      retval = h3600_power_management(PM_SUSPEND);
++      if (retval) {
++              pm_send_all(PM_RESUME, (void *)0);
++              return retval;
++      }
++#endif
++
++      retval = pm_do_suspend();
++
++#ifdef CONFIG_IPAQ_HANDHELD
++      /* Allow the power management routines to override resuming */
++      while ( h3600_power_management(PM_RESUME) )
++              retval = pm_do_suspend();
++#endif
++
++      pm_send_all(PM_RESUME, (void *)0);
++
++      return retval;
++}
++EXPORT_SYMBOL(pm_suspend);
++
++#ifdef CONFIG_SYSCTL
++/*
++ * ARGH!  ACPI people defined CTL_ACPI in linux/acpi.h rather than
++ * linux/sysctl.h.
++ *
++ * This means our interface here won't survive long - it needs a new
++ * interface.  Quick hack to get this working - use sysctl id 9999.
++ */
++#warning ACPI broke the kernel, this interface needs to be fixed up.
++#define CTL_ACPI 9999
++#define ACPI_S1_SLP_TYP 19
++
++/*
++ * Send us to sleep.
++ */
++static int sysctl_pm_do_suspend(void)
++{
++      int retval;
++
++      retval = pm_send_all(PM_SUSPEND, (void *)3);
++
++      if (retval == 0) {
++              retval = pm_do_suspend();
++
++              pm_send_all(PM_RESUME, (void *)0);
++      }
++
++      return retval;
++}
++
++static struct ctl_table pm_table[] =
++{
++      {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_do_suspend},
++      {2, "helper", pm_helper_path, sizeof(pm_helper_path), 0644, NULL, (proc_handler *)&proc_dostring},
++      {3, "debug", &debug_pm, sizeof(debug_pm), 0644, NULL, (proc_handler *)&proc_dointvec},
++      {4, "helper_veto", &pm_helper_veto, sizeof(pm_helper_veto), 0644, NULL, (proc_handler *)&proc_dointvec},
++      {0}
++};
++
++static struct ctl_table pm_dir_table[] =
++{
++      {CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
++      {0}
++};
++
++/*
++ * Initialize power interface
++ */
++static int __init pm_init(void)
++{
++      register_sysctl_table(pm_dir_table, 1);
++      return 0;
++}
++
++__initcall(pm_init);
++
++#endif
++
+--- linux-2.4.21/arch/arm/mach-pxa/pm.c~pm
++++ linux-2.4.21/arch/arm/mach-pxa/pm.c
+@@ -19,6 +19,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/sysctl.h>
+ #include <linux/errno.h>
++#include <linux/module.h>
+ #include <asm/hardware.h>
+ #include <asm/memory.h>
+@@ -82,7 +83,7 @@
+       /* 
+        * Temporary solution.  This won't be necessary once
+-       * we move pxa support into the serial/* driver
++       * we move pxa support into the serial driver
+        * Save the FF UART 
+        */
+       SAVE(FFIER);
+@@ -176,7 +177,7 @@
+       /* 
+        * Temporary solution.  This won't be necessary once
+-       * we move pxa support into the serial/* driver.
++       * we move pxa support into the serial driver.
+        * Restore the FF UART.
+        */
+       RESTORE(FFMCR);
+@@ -209,6 +210,12 @@
+       return virt_to_phys(sp);
+ }
++#ifndef CONFIG_APM
++/*
++ * This code is only needed if we don't compile in APM support.
++ * If we compile APM support in, then this code is in pm-common.c
++ */
++
+ #ifdef CONFIG_SYSCTL
+ /*
+  * ARGH!  ACPI people defined CTL_ACPI in linux/acpi.h rather than
+@@ -263,3 +270,6 @@
+ __initcall(pm_init);
+ #endif
++#endif
++
++EXPORT_SYMBOL(pm_do_suspend);
+--- linux-2.4.21/arch/arm/mach-pxa/pxa_usb.h~pxa-usb
++++ linux-2.4.21/arch/arm/mach-pxa/pxa_usb.h
+@@ -39,6 +39,7 @@
+ int pxa_usb_xmitter_avail( void );
+ int pxa_usb_send(char *buf, int len, usb_callback_t callback);
+ void sa110a_usb_send_reset(void);
++void pxa_usb_send_reset(void);
+ /* in usb_recev.c */
+ int pxa_usb_recv(char *buf, int len, usb_callback_t callback);
+--- /dev/null
++++ linux-2.4.21/arch/arm/mach-pxa/ramses.c
+@@ -0,0 +1,844 @@
++/*
++ *  linux/arch/arm/mach-pxa/ramses.c
++ *  
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License version 2 as
++ *  published by the Free Software Foundation.
++ *
++ *  Copyright (c) 2002,2003,2004 by M&N Logistik-Lösungen Online GmbH
++ *  written by Holger Schurig
++ * 
++ *  2001-09-13: Cliff Brake <cbrake@accelent.com>
++ *              Initial code
++ *
++ *  2002-10-09: adaptions to ramses
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/sched.h>
++#include <linux/ioport.h>
++#include <linux/pm.h>
++#include <linux/delay.h>
++#ifdef CONFIG_APM
++#include <linux/apm_bios.h>
++#endif
++#define USE_UCB
++//#define PFI_LED
++#define PFI_TURNOFF
++
++#include <asm/types.h>
++#include <asm/setup.h>
++#include <asm/memory.h>
++#include <asm/mach-types.h>
++#include <asm/hardware.h>
++#include <asm/irq.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/mach/irq.h>
++#include <asm/arch/irq.h>
++#include <asm/arch-pxa/pxa-regs.h>
++
++#ifdef USE_UCB
++#include "../drivers/misc/ucb1x00.h"
++#endif
++
++#include "generic.h"
++
++
++/* shadow registers for write only registers */
++u16 ramses_control_shadow = 
++      RAMSES_CONTROL_LED_BLUE_ +
++      RAMSES_CONTROL_LED_ORANGE_ +
++      RAMSES_CONTROL_SCANNER_WAKE_ +
++      RAMSES_CONTROL_SCANNER_TRIG_;
++
++/* various flags the change the behavior of the kernel */
++unsigned int ramses_flags =
++      RAMSES_FLAGS_KEY_SCAN +
++      RAMSES_FLAGS_KEY_SUSPEND +
++      RAMSES_FLAGS_KEY_OFF;
++
++
++/******************************************************************/
++/*  Corevoltage settings                                          */
++/******************************************************************/
++
++int ramses_corevolt_shadow = 150;
++
++void ramses_set_corevolt(int volt)
++{
++      int val = 0;
++      switch (volt) {
++      case 150:
++              val = 5;
++              break;
++      case 135:
++              val = 8;
++              break;
++      case 125:
++              val = 10;
++              break;
++      case 115:
++              val = 12;
++              break;
++      case 105:
++              val = 14;
++              break;
++      }
++      if (val) {      
++              ramses_corevolt_shadow = volt;
++              RAMSES_COREVOLT = val;
++              RAMSES_CPLD_PERIPH_PWR |= CORE_VAR_EN;
++      }
++}
++
++
++/******************************************************************/
++/*  LCD stuff                                                     */
++/******************************************************************/
++
++u16 ramses_lcd_type;
++
++void ramses_lcd_power_on(void)
++{
++      //printk("--> ramses_lcd_power_on\n");
++
++      /* 1. VCC */
++      RAMSES_CPLD_LCD |= RAMSES_LCD_VCC;
++
++      /* 2. Signal */
++
++        /* 3. the PWM */
++      CKEN |= (CKEN0_PWM0 | CKEN1_PWM1);
++
++        /* 4. nDISPOFF (done at backlight_on time) */
++        RAMSES_CPLD_LCD |= RAMSES_LCD_DISPOFF;
++}
++
++
++void ramses_lcd_power_off(void)
++{
++      //printk("--> ramses_lcd_power_off\n");
++      if (RAMSES_CPLD_LCD & RAMSES_LCD_DISPOFF) {
++              //printk("--> turn bl off first\n");
++              ramses_lcd_backlight_off();
++      }
++
++      /* 1. nDISPOFF (just to be sure) */
++      RAMSES_CPLD_LCD &= ~RAMSES_LCD_DISPOFF;
++
++      // for Torisan: wait until all has been sent out
++      if (ramses_lcd_type == 2) {
++              int i;
++              for (i=0; i<33; i++)
++                      udelay(1500);
++      }
++
++        /* 2. disable the PWM */
++      set_GPIO_mode(GPIO16_PWM0 | GPIO_OUT);
++      set_GPIO_mode(GPIO17_PWM1 | GPIO_OUT);
++      CKEN &= ~(CKEN0_PWM0 | CKEN1_PWM1);
++
++        /* 3. SIGNAL */
++
++        /* 4. VCC */
++      RAMSES_CPLD_LCD &= ~RAMSES_LCD_VCC;
++}
++
++
++void ramses_lcd_backlight_on(void)
++{
++      int i;
++
++      //printk("--> ramses_lcd_backlight_on\n");
++      if ((ramses_control_shadow & RAMSES_CONTROL_LCD_BLIGHT) != 0)
++              return;
++      //printk("    state: %d\n", ramses_control_shadow & RAMSES_CONTROL_LCD_BLIGHT);
++
++      set_GPIO_mode(GPIO17_PWM1 | GPIO_OUT);
++
++        /* 4. nDISPOFF */
++        RAMSES_CPLD_LCD |= RAMSES_LCD_DISPOFF;
++
++      /* Backlight can be turned on at any time */
++      RAMSES_LCD_BLIGHT_ON();
++
++      for (i=0; i<33; i++)
++              udelay(1500);
++      set_GPIO_mode(GPIO16_PWM0_MD);
++      set_GPIO_mode(GPIO17_PWM1_MD);
++}
++
++
++void ramses_lcd_backlight_off(void)
++{
++      int i;
++
++      //printk("--> ramses_lcd_backlight_off\n");
++      if ((ramses_control_shadow & RAMSES_CONTROL_LCD_BLIGHT) == 0)
++              return;
++      //printk("    state: %d\n", ramses_control_shadow & RAMSES_CONTROL_LCD_BLIGHT);
++
++      set_GPIO_mode(GPIO17_PWM1 | GPIO_OUT);
++      for (i=0; i<100; i++)
++              udelay(1500);
++
++      /* Backlight can be turned off at any time */
++      RAMSES_LCD_BLIGHT_OFF();
++      udelay(1500);
++
++      /* 1. nDISPOFF */
++      if (ramses_lcd_type != 2)
++              RAMSES_CPLD_LCD &= ~RAMSES_LCD_DISPOFF;
++
++      //set_GPIO_mode(GPIO16_PWM0 | GPIO_IN);
++      //set_GPIO_mode(GPIO17_PWM1 | GPIO_IN);
++}
++
++
++void ramses_lcd_set_brightness(int b)
++{
++      if (b > 255) b = 255;
++      if (b < 0)   b = 0;
++      PWM_PWDUTY1 = 510-(b<<1);
++}
++
++
++int ramses_lcd_get_brightness(void)
++{
++      return 255-(PWM_PWDUTY1 >> 1);
++}
++
++
++void ramses_lcd_set_contrast(int c)
++{
++      if (c > 255) c = 255;
++      if (c < 0)   c = 0;
++      PWM_PWDUTY0 = 542-c;
++}
++
++
++int ramses_lcd_get_contrast(void)
++{
++      return 542-PWM_PWDUTY0;
++}
++
++
++void  ramses_lcd_set_intensity(int i)
++{
++      //printk("--> ramses_lcd_set_intensity(%d)\n", i);
++      if (i) {
++              ramses_lcd_backlight_on();
++      } else {
++              ramses_lcd_backlight_off();
++      }
++}
++
++
++int ramses_lcd_get_intensity(void)
++{
++      return ramses_control_shadow & RAMSES_CONTROL_LCD_BLIGHT;
++}
++
++
++
++
++
++/******************************************************************/
++/*  HDQ  communication                                            */
++/******************************************************************/
++
++#define GPIO_HDQ 2
++
++#define HDQ_LO        GPCR(GPIO_HDQ) = GPIO_bit(GPIO_HDQ)
++#define HDQ_HI        GPSR(GPIO_HDQ) = GPIO_bit(GPIO_HDQ)
++#define HDQ_GET       (GPLR(GPIO_HDQ) & (1 << GPIO_HDQ))
++
++#define MAXLOOPS 800
++#define MAXTRIES 3
++
++
++static void hdq_break(void)
++{
++      HDQ_LO;
++      set_GPIO_mode(GPIO_HDQ | GPIO_OUT);
++      udelay(220);
++      HDQ_HI;
++      udelay(50);
++}
++
++
++/**
++ * Send data on the 1-bit wire.
++ *
++ * LSB first. Depending on the bit, do the low phase short or
++ * small. The used timings in usec's are made so that our send
++ * stuff has exactly the timing that the BQ2050 battery sends
++ * us back.
++*/
++static void hdq_put_data(unsigned char cmd) 
++{
++      unsigned char mask = 1;
++
++      HDQ_HI;
++      set_GPIO_mode(GPIO_HDQ | GPIO_OUT);
++
++      while (1) {
++              HDQ_LO;
++              udelay(cmd & mask ? 37 : 115);
++              HDQ_HI;
++              udelay(cmd & mask ? 163 : 85);
++              if (mask == 0x80) break;
++              mask = mask << 1;
++      }
++      set_GPIO_mode(GPIO_HDQ | GPIO_IN);
++}
++
++
++/**
++ * Receive data on the 1-bit wire.
++ *
++ * Little state-machine with two states (yuck) that measures the time
++ * in the low-state. If it exceeds some value, then the bit was a 0,
++ * otherwise it's a 1.
++*/
++static int hdq_get_data(void)
++{
++      enum { ST_WAITLOW, ST_LOW };
++
++      int i;
++      int lastlow = 0;
++      int state = ST_WAITLOW;
++      unsigned char mask = 1;
++      unsigned char d = 0;
++      
++      for (i=0; i<MAXLOOPS; i++) {
++              if (state==ST_WAITLOW) {
++                      if (HDQ_GET == 0) {
++                              lastlow = i;
++                              state = ST_LOW;
++                      }
++              } else
++              if (state == ST_LOW) {
++                      if (HDQ_GET) {
++                              // 34 must be changed if the udelay(2) changes!
++                              if (i-lastlow < 34) {
++                                      d = d | mask;
++                              }
++                              if (mask == 0x80) break;
++                              mask = mask << 1;
++                              state = ST_WAITLOW;
++                      }
++              }
++              udelay(2);
++      }
++      if (i==MAXLOOPS) {
++              //printk("no respone after %d\n", i);
++              return -1;
++      } else {
++              //printk("done after %d: %d %x\n", i, d, d);
++              return d;
++      }
++}
++
++
++static int hdq_get_reg_once(unsigned char reg)
++{
++      int d = -1;
++      int i;
++      
++      reg &= 0x7f;
++
++      for (i=0; i<MAXTRIES; i++) {
++              hdq_break();
++              hdq_put_data(reg);
++              d = hdq_get_data();
++              if (d != -1)
++                      break;
++              //printk("hdq_get_reg_once try again: %d\n", i);
++      }
++
++      return d;
++}
++
++/**
++ * The HDQ protocol communication is so bad that we can't really
++ * be sure that we got something usable. So we call hdq_get_reg_once()
++ * twice and compare if we got the same value twice. If not, we try
++ * again. And again, and again ...  up to MAXTRIES times.
++ */
++int ramses_hdq_get_reg(unsigned char reg)
++{
++      int i,d1,d2;
++
++      d1 = hdq_get_reg_once(reg);
++      for (i=0; i<MAXTRIES; i++) {
++              d2 = hdq_get_reg_once(reg);
++              if (d1 == d2)
++                      return d2;
++              d1 = d2;
++      }
++      printk("no response from battery\n");
++      return -1;
++}
++
++
++
++/******************************************************************/
++/*  Power Management                                              */
++/******************************************************************/
++
++#ifdef CONFIG_PM
++static int
++ramses_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
++{
++    static int old_shadow;
++    static int old_ctrl0;
++    static int old_ctrl1;
++    static int old_perval0;
++    static int old_perval1;
++    static int old_duty0;
++    static int old_duty1;
++
++    switch (req) {
++    case PM_SUSPEND:
++      old_shadow  = ramses_control_shadow;
++      old_ctrl0   = PWM_CTRL0;
++      old_ctrl1   = PWM_CTRL1;
++      old_perval0 = PWM_PERVAL0;
++      old_perval1 = PWM_PERVAL1;
++      old_duty0   = PWM_PWDUTY0;
++      old_duty1   = PWM_PWDUTY1;
++
++      // RAMSES_LED_BLUE_OFF();
++      // RAMSES_LED_ORANGE_OFF();
++      RAMSES_UART_OFF();
++      // RAMSES_SCANNER_OFF();
++      // RAMSES_USB_BUS_OFF();
++      // printk("shadow: %08x -> %08x\n", old_shadow, ramses_control_shadow);
++
++      RAMSES_CPLD_PERIPH_PWR &= ~PER_PWR_EN;
++      break;
++
++    case PM_RESUME:
++      RAMSES_CPLD_PERIPH_PWR |= PER_PWR_EN;
++      ramses_control_shadow = old_shadow;
++      PWM_CTRL0   = old_ctrl0;
++      PWM_CTRL1   = old_ctrl1;
++      PWM_PERVAL0 = old_perval0;
++      PWM_PERVAL1 = old_perval1;
++      PWM_PWDUTY0 = old_duty0;
++      PWM_PWDUTY1 = old_duty1;
++
++        break;
++    }
++    return 0;
++}
++
++#endif
++
++
++
++static void pf_interrupt(int irq, void *dummy, struct pt_regs *fp)
++{
++#ifdef PFI_LED
++      RAMSES_LED_BLUE_ON();
++      RAMSES_LED_ORANGE_ON();
++#endif
++#ifdef PFI_TURNOFF
++      // Make sure we can't be turned on by setting low onto the CPLD's columns
++      RAMSES_CPLD_KB_COL_LOW = 0;
++      RAMSES_CPLD_KB_COL_HIGH = 0;
++
++      // turn power off
++      RAMSES_POWER_OFF();
++
++      // wait until VCC fades
++      while (1) { }
++#endif
++}
++
++
++void ramses_shut_off(void)
++{
++      // Make sure we can't be turned on by setting low onto the CPLD's columns
++      RAMSES_CPLD_KB_COL_LOW = 0;
++      RAMSES_CPLD_KB_COL_HIGH = 0;
++      //printk("--> ramses_shut_off calling ramses_lcd_backlight_off\n");
++      ramses_lcd_backlight_off();
++      //printk("--> ramses_shut_off calling ramses_lcd_power_off\n");
++      ramses_lcd_power_off();
++
++      // turn power off
++      RAMSES_POWER_OFF();
++
++      // wait until voltage fades
++      while (1) {}
++}
++
++
++
++
++#ifdef CONFIG_APM
++static int ramses_get_power_status(u_char *ac_line_status,
++                                u_char *battery_status,
++                                u_char *battery_flag,
++                                u_char *battery_percentage,
++                                u_short *battery_life)
++{
++#ifdef USE_UCB
++      int adc3;
++      struct ucb1x00 *ucb = ucb1x00_get();
++      
++      ucb1x00_adc_enable(ucb);
++      adc3 = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD3, 0);
++      ucb1x00_adc_disable(ucb);
++
++      /*
++       * when charged:        0..430
++       * when discharging:    0..340
++       */
++
++#define CHG_LO 165
++#define CHG_HI 420
++#define OFF_LO 60
++#define OFF_HI 350
++      if ((RAMSES_CPLD_MISC_STATUS & RAMSES_CHG_STS) == 0) {
++              // in Docking-Station
++              if (adc3 > CHG_HI) adc3 = CHG_HI;
++              if (adc3 < CHG_LO) adc3 = CHG_LO;
++              adc3 -= CHG_LO;
++              *battery_percentage = adc3 * 100 / (CHG_HI-CHG_LO);
++              *ac_line_status = 0x01;
++      } else {
++              // offline
++              if (adc3 > OFF_HI) adc3 = OFF_HI;
++              if (adc3 < OFF_LO) adc3 = OFF_LO;
++              adc3 -= OFF_LO;
++              *battery_percentage = adc3 * 100 / (OFF_HI-OFF_LO);
++              *ac_line_status = 0x00;
++      }
++
++      if (*battery_percentage > 100)
++              *battery_percentage = 100;
++
++      if (*ac_line_status) {
++              *battery_status =    3;         // charging
++              *battery_flag   = 1<<3;
++      } else
++      if (*battery_percentage >= 30) {
++              *battery_status =    0;         // high
++              *battery_flag   = 1<<0;
++      } else          
++      if (*battery_percentage >= 15) {
++              *battery_status =    1;         // low
++              *battery_flag   = 1<<1;
++      } else {
++              *battery_status =    2;         // critical
++              *battery_flag   = 1<<2;
++      }
++
++      // assume 5.5 hours operation, 330 minutes
++      *battery_life = (*battery_percentage * 330 / 100) | 0x8000;
++#endif
++
++
++#ifdef USE_HDQ
++#error HDQ
++      // SAE is something like mAh * 10
++      int sae, sael;
++
++      sael = ramses_hdq_get_reg(HDQ_SAEL);
++      sae  = ramses_hdq_get_reg(HDQ_SAEH);
++
++      if (sae == -1 || sael == -1) {
++              //printk("ramses: could not read HDQ_SAE\n");
++              *ac_line_status     = 0xff;
++              *battery_status     = 0xff;
++              *battery_flag       = 0xff;
++              *battery_percentage = 0xff;
++              *battery_life       = -1;
++              return 0;
++      }
++
++      sae = (sae << 16) + sael;
++      if (sae > 27000) {
++              printk("ramses: capped HDQ_SAE from %d to 27000\n", sae);
++              sae = 27000;
++      }
++
++      if (sae < 4000) {
++              *battery_status =    2;         // critical
++              *battery_flag   = 1<<2;
++      } else
++      if (sae < 10000) {
++              *battery_status =    1;         // low
++              *battery_flag   = 1<<1;
++      } else {
++              *battery_status =    0;         // high
++              *battery_flag   = 1<<0;
++      }
++
++      if ((RAMSES_CPLD_MISC_STATUS & RAMSES_CHG_STS) == 0) {
++              *battery_status =    3;         // charging
++              *battery_flag   = 1<<3;
++              *ac_line_status = 0x01;         // online
++      } else {
++              *ac_line_status = 0x00;         // offline
++      }
++
++      *battery_percentage = sae / 270;
++      *battery_life = (sae / 56) | 0x8000;
++#endif
++
++
++#if !defined(USE_UCB) && !defined(USE_HDQ)
++#error NONE
++        *ac_line_status     = 0xff;
++        *battery_status     = 0xff;
++        *battery_flag       = 0xff;
++        *battery_percentage = 0xff;
++        *battery_life       = -1;
++#endif
++
++      return 0;
++}
++#endif
++
++
++
++
++/******************************************************************/
++/*  Initialisation                                                */
++/******************************************************************/
++
++static struct map_desc ramses_io_desc[] __initdata = {
++ /* virtual               physical              length                domain     r  w  c  b */
++  { RAMSES_IDE_BASE,      RAMSES_IDE_PHYS,      RAMSES_IDE_SIZE,      DOMAIN_IO, 0, 1, 0, 0 }, 
++  { RAMSES_ETH_BASE,      RAMSES_ETH_PHYS,      RAMSES_ETH_SIZE,      DOMAIN_IO, 0, 1, 0, 0 },
++  { RAMSES_COREVOLT_BASE, RAMSES_COREVOLT_PHYS, RAMSES_COREVOLT_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
++  { RAMSES_CPLD_BASE,     RAMSES_CPLD_PHYS,     RAMSES_CPLD_SIZE,     DOMAIN_IO, 0, 1, 0, 0 },
++  { RAMSES_CONTROL_BASE,  RAMSES_CONTROL_PHYS,  RAMSES_CONTROL_SIZE,  DOMAIN_IO, 0, 1, 0, 0 },
++  LAST_DESC
++};
++
++
++
++
++
++/*
++ * Uncompressing Linux...... done, booting the kernel.
++ * Linux version 2.4.19-rmk4-pxa1-mn ...
++ * CPU: Intel XScale-PXA250 revision 4
++ * Machine: Ramses
++ * fixup_ramses()
++ */
++
++static void __init
++fixup_ramses(struct machine_desc *desc, struct param_struct *params,
++              char **cmdline, struct meminfo *mi)
++{
++      SET_BANK (0, 0xa0000000,128*1024*1024);
++      mi->nr_banks = 1;
++}
++
++
++
++
++/*
++ * fixup_ramses()
++ * ramses_map_io()
++ */
++
++static void __init ramses_map_io(void)
++{
++      u16 smc_eeprom_read(long ioaddr, u16 location);
++
++      pxa_map_io();
++      iotable_init(ramses_io_desc);
++
++#ifdef IPAQ
++      // set power managament stuff
++        PGSR0 = GPSRx_SleepValue;
++        PGSR1 = GPSRy_SleepValue;
++        PGSR2 = GPSRz_SleepValue;
++        PWER = PWER_GPIO0 | PWER_RTC;
++        PFER = PWER_GPIO0 | PWER_RTC;
++        PRER = 0;
++#endif
++
++      ramses_lcd_type = smc_eeprom_read(RAMSES_ETH_BASE+0x300, RAMSES_LCD_TYPE_OFFSET);
++      // here we could make a special case about ramses_lcd_type == 0xffff
++      ramses_flags |= (ramses_lcd_type & RAMSES_FLAGS_LCD_FBTURN);
++}
++
++
++
++
++/*
++ * ramses_map_io()
++ * Memory clock: 99.53MHz (*27)
++ * Run Mode clock: 199.07MHz (*2)
++ * Turbo Mode clock: 398.13MHz (*2.0, active) * On node 0 totalpages: 16384
++ * zone(0): 32768 pages.
++ * zone(1): 0 pages.
++ * zone(2): 0 pages.
++ * Kernel command line: root=/dev/nfsroot ...
++ * ramses_init_irq()
++ */
++
++static void __init ramses_init_irq(void)
++{
++      set_GPIO_IRQ_edge(21, GPIO_FALLING_EDGE);               // UCB 1400
++
++      RAMSES_SCANNER_OFF();
++      RAMSES_GSM_OFF();
++      RAMSES_GSM_RESET_OFF();
++      RAMSES_GSM_BOOT_OFF();
++      pxa_init_irq();
++}
++
++
++
++
++/*
++ * ramses_init_irq()
++ * Console: colour dummy device 80x30
++ * serial_console_init
++ * serial_console_setup
++ * Calibrating delay loop... 397.31 BogoMIPS
++ * Memory: 128MB = 128MB total
++ * Memory: 127872KB available (1355K code, 272K data, 112K init)
++ * Dentry cache hash table entries: 16384 (order: 5, 131072 bytes)
++ * Inode cache hash table entries: 8192 (order: 4, 65536 bytes)
++ * Mount-cache hash table entries: 2048 (order: 2, 16384 bytes)
++ * Buffer-cache hash table entries: 8192 (order: 3, 32768 bytes)
++ * Page-cache hash table entries: 32768 (order: 5, 131072 bytes)
++ * POSIX conformance testing by UNIFIX
++ * Linux NET4.0 for Linux 2.4
++ * Based upon Swansea University Computer Society NET3.039
++ * Initializing RT netlink socket
++ * ramses_init()
++ */
++
++static int __init ramses_init(void)
++{
++      unsigned int irq_gpio_pin;
++
++      // Set IRQ for Touchpanel (via UCB 1400)
++      irq_gpio_pin = IRQ_TO_GPIO_2_80(TOUCH_PANEL_IRQ);
++      set_GPIO_IRQ_edge(irq_gpio_pin, TOUCH_PANEL_IRQ_EDGE);
++
++      // Set IRQ for Power Fail Interrupt
++      set_GPIO_IRQ_edge(1, GPIO_FALLING_EDGE);
++      request_irq(IRQ_GPIO(1), pf_interrupt, 0, "PWR FAIL", NULL);
++
++      // Setup IRQ edge for Ethernet
++      //set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(27), GPIO_RISING_EDGE);
++      set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(ETHERNET_IRQ), ETHERNET_IRQ_EDGE);
++
++      // Configure PWMs for LCD
++      PWM_CTRL0   =   0;
++      PWM_PERVAL0 = 512;
++      PWM_PWDUTY0 = 440;
++      PWM_CTRL1   =   0;
++      PWM_PERVAL1 = 512;
++      PWM_PWDUTY1 = 450;
++
++      // Request Memory Regions of core components
++      request_mem_region(RAMSES_CONTROL_BASE,  RAMSES_CONTROL_SIZE,  "Ramses Control");
++      request_mem_region(RAMSES_CPLD_BASE,     RAMSES_CPLD_SIZE,     "Ramses CPLD");
++      request_mem_region(RAMSES_COREVOLT_BASE, RAMSES_COREVOLT_SIZE, "Ramses Corevolt");
++
++#ifdef CONFIG_PM
++#ifdef PM_DEBUG
++      pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, ramses_pm_callback, "ramses");
++#else
++      pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, ramses_pm_callback);
++#endif
++      //TODO  PWER            (PXA255: 3-25)
++      //TODO  PRER            (PXA255: 3-26)
++      //TODO  PFER            (PXA255: 3-27)
++      //TODO  PSSR            (PXA255: 3-29)
++      //TODO  PGSR0..PGSR2    (PXA255: 3-32)
++#endif
++
++#ifdef CONFIG_APM
++      apm_register_get_power_status(ramses_get_power_status);
++#endif
++
++      PCFR = PCFR_OPDE | PCFR_FS | PCFR_FP;           // PXA255: 3-24
++
++      pm_power_off = ramses_shut_off;
++
++      return 0;
++}
++
++__initcall(ramses_init);
++
++
++
++/*
++ * ramses_init()
++ * Using PXA255 frequency points.
++ * Registering CPU frequency change support.
++ * CPU clock: 398.131 MHz (99.000-400.000 MHz)
++ * Starting kswapd
++ * devfs: v1.12a (20020514) Richard Gooch (rgooch@atnf.csiro.au)
++ * devfs: boot_options: 0x1
++ * pty: 256 Unix98 ptys configured
++ * pxa & ti16c754b serial driver
++ * tts/0 at irq 14 is a PXA UART
++ * tts/1 at irq 13 is a PXA UART
++ * tts/2 at irq 12 is a PXA UART
++ * tts/3 at irq 45 is a TI16750
++ * tts/4 at irq 46 is a TI16750
++ * tts/5 at irq 47 is a TI16750
++ * tts/6 at irq 48 is a TI16750
++ * LAN91C111: You shouldn't use auto-probing with insmod!
++ * SMSC LAN91C111 Driver (v2.2), (Linux Kernel 2.4 + Support for Odd Byte) ...
++ * eth0: SMC91C11xFD(rev:1) at 0xf0100300 IRQ:26 MEMSIZE ...
++ * ac97_codec: AC97 Audio codec, id: 0x5053:0x4304 (Philips UCB1400)
++ * NET4: Linux TCP/IP 1.0 for NET4.0
++ * IP Protocols: ICMP, UDP, TCP
++ * IP: routing cache hash table of 512 buckets, 4Kbytes
++ * TCP: Hash tables configured (established 4096 bind 4096)
++ * IP-Config: ...
++ * NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
++ * NetWinder Floating Point Emulator V0.95 (c) 1998-1999 Rebel.com
++ * Looking up port of RPC 100003/2 on 192.168.233.66
++ * Looking up port of RPC 100005/1 on 192.168.233.66
++ * VFS: Mounted root (nfs filesystem).
++ * Mounted devfs on /dev
++ * Freeing init memory: 68K
++ * INIT: version 2.84 booting
++ */
++
++
++
++MACHINE_START(RAMSES, "Ramses")
++      MAINTAINER("M&N Logistik-Lösungen Online GmbH")
++      BOOT_MEM(0xa0000000, 0x40000000, 0xfc000000)
++      BOOT_PARAMS(0xa0000100)
++      FIXUP(fixup_ramses)
++      MAPIO(ramses_map_io)
++      INITIRQ(ramses_init_irq)
++MACHINE_END
++
++EXPORT_SYMBOL(ramses_lcd_type);
++EXPORT_SYMBOL(ramses_lcd_power_on);
++EXPORT_SYMBOL(ramses_lcd_power_off);
++EXPORT_SYMBOL(ramses_lcd_backlight_on);
++EXPORT_SYMBOL(ramses_lcd_backlight_off);
++EXPORT_SYMBOL(ramses_lcd_set_intensity);
++EXPORT_SYMBOL(ramses_lcd_set_brightness);
++EXPORT_SYMBOL(ramses_lcd_set_contrast);
++EXPORT_SYMBOL(ramses_lcd_get_intensity);
++EXPORT_SYMBOL(ramses_lcd_get_brightness);
++EXPORT_SYMBOL(ramses_lcd_get_contrast);
++EXPORT_SYMBOL(ramses_hdq_get_reg);
++EXPORT_SYMBOL(ramses_set_corevolt);
++EXPORT_SYMBOL(ramses_corevolt_shadow);
+--- linux-2.4.21/arch/arm/mach-pxa/usb-char.c~pxa-usb
++++ linux-2.4.21/arch/arm/mach-pxa/usb-char.c
+@@ -211,7 +211,6 @@
+ static void twiddle_descriptors( void )
+ {
+        desc_t * pDesc = pxa_usb_get_descriptor_ptr();
+-       string_desc_t * pString;
+        pDesc->b.ep1.wMaxPacketSize = make_word_c( RX_PACKET_SIZE );
+        pDesc->b.ep1.bmAttributes   = USB_EP_BULK;
+@@ -220,6 +219,7 @@
+          if ( machine_is_extenex1() ) {
+ #ifdef CONFIG_SA1100_EXTENEX1
++                string_desc_t * pString;
+                 pDesc->dev.idVendor = make_word_c( 0xC9F );
+                 pDesc->dev.idProduct = 1;
+                 pDesc->dev.bcdDevice = make_word_c( 0x0001 );
+--- linux-2.4.21/arch/arm/mach-pxa/usb-eth.c~pxa-usbeth
++++ linux-2.4.21/arch/arm/mach-pxa/usb-eth.c
+@@ -52,6 +52,7 @@
+ #define ETHERNET_VENDOR_ID 0x49f
+ #define ETHERNET_PRODUCT_ID 0x505A
++#define ETHERNET_DEVICE_ID 0x0200
+ #define MAX_PACKET 32768
+ #define MIN(a, b) (((a) < (b)) ? (a) : (b))
+@@ -329,6 +330,7 @@
+                pd->b.ep2.wMaxPacketSize = make_word( usb_wsize );
+                pd->dev.idVendor         = ETHERNET_VENDOR_ID;
+                pd->dev.idProduct     = ETHERNET_PRODUCT_ID;
++               pd->dev.bcdDevice     = ETHERNET_DEVICE_ID;
+                pstr = pxa_usb_kmalloc_string_descriptor( "PXA USB NIC" );
+                if ( pstr ) {
+                         pxa_usb_set_string_descriptor( 1, pstr );
+--- linux-2.4.21/drivers/char/Config.in~i2c-ds1337
++++ linux-2.4.21/drivers/char/Config.in
+@@ -164,6 +164,7 @@
+ if [ "$CONFIG_I2C" != "n" ]; then
+     dep_tristate '  DS1307 RTC' CONFIG_I2C_DS1307 $CONFIG_I2C
++    dep_tristate '  DS1337 RTC' CONFIG_I2C_DS1337 $CONFIG_I2C
+ fi
+ source drivers/l3/Config.in
+--- linux-2.4.21/drivers/char/Makefile~i2c-ds1337
++++ linux-2.4.21/drivers/char/Makefile
+@@ -21,10 +21,11 @@
+ # All of the (potential) objects that export symbols.
+ # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
+-export-objs     :=    busmouse.o console.o keyboard.o sysrq.o \
++export-objs     :=    vt.o busmouse.o console.o keyboard.o sysrq.o \
+                       misc.o pty.o random.o selection.o serial.o \
+                       sonypi.o tty_io.o tty_ioctl.o generic_serial.o \
+-                      au1000_gpio.o hp_psaux.o nvram.o scx200.o
++                      au1000_gpio.o hp_psaux.o nvram.o scx200.o \
++                      input_keyb.o
+ mod-subdirs   :=      joystick ftape drm drm-4.0 pcmcia
+@@ -129,6 +130,11 @@
+   ifeq ($(CONFIG_SA1100_CERF_CPLD),y)
+     KEYBD    += cerf_keyb.o
+   endif
++  ifeq ($(CONFIG_ARCH_RAMSES),y)
++    KEYMAP   = german.o
++    KEYBD    += input_keyb.o
++    obj-m    += sysctl.o
++  endif
+   ifeq ($(CONFIG_ARCH_FORTUNET),y)
+     KEYMAP   := defkeymap.o
+   endif
+@@ -337,6 +343,7 @@
+ # I2C char devices
+ obj-$(CONFIG_I2C_DS1307) += ds1307.o
++obj-$(CONFIG_I2C_DS1337) += ds1337.o
+ subdir-$(CONFIG_MWAVE) += mwave
+ ifeq ($(CONFIG_MWAVE),y)
+@@ -372,4 +379,7 @@
+       set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@
+ qtronixmap.c: qtronixmap.map
++      set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@
++
++german.c: german.map
+       set -e ; loadkeys --mktable $< | sed -e 's/^static *//' > $@
+--- linux-2.4.21/drivers/char/console.c~keyb-module
++++ linux-2.4.21/drivers/char/console.c
+@@ -150,7 +150,7 @@
+ static int con_open(struct tty_struct *, struct file *);
+ static void vc_init(unsigned int console, unsigned int rows,
+                   unsigned int cols, int do_clear);
+-static void blank_screen(unsigned long dummy);
++//static void blank_screen(unsigned long dummy);
+ static void gotoxy(int currcons, int new_x, int new_y);
+ static void save_cur(int currcons);
+ static void reset_terminal(int currcons, int do_clear);
+@@ -158,7 +158,7 @@
+ static void set_vesa_blanking(unsigned long arg);
+ static void set_cursor(int currcons);
+ static void hide_cursor(int currcons);
+-static void unblank_screen_t(unsigned long dummy);
++//static void unblank_screen_t(unsigned long dummy);
+ static void console_callback(void *ignored);
+ static int printable;         /* Is console ready for printing? */
+@@ -167,7 +167,7 @@
+ int console_blanked;
+ static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */
+-static int blankinterval = 10*60*HZ;
++//static int blankinterval = 10*60*HZ;
+ static int vesa_off_interval;
+ static struct tq_struct console_callback_tq = {
+@@ -209,9 +209,9 @@
+  * Hook so that the power management routines can (un)blank
+  * the console on our behalf.
+  */
+-int (*console_blank_hook)(int);
++//int (*console_blank_hook)(int);
+-static struct timer_list console_timer;
++//static struct timer_list console_timer;
+ /*
+  *    Low-Level Functions
+@@ -543,7 +543,7 @@
+ static void set_cursor(int currcons)
+ {
+-    if (!IS_FG || console_blanked || vcmode == KD_GRAPHICS)
++    if (!IS_FG || vcmode == KD_GRAPHICS)
+       return;
+     if (deccm) {
+       if (currcons == sel_cons)
+@@ -1287,7 +1287,7 @@
+                       update_attr(currcons);
+                       break;
+               case 9: /* set blanking interval */
+-                      blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
++                      //blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
+                       poke_blanked_console();
+                       break;
+               case 10: /* set bell frequency in Hz */
+@@ -2575,11 +2575,11 @@
+       if (tty_register_driver(&console_driver))
+               panic("Couldn't register console driver\n");
+-      init_timer(&console_timer);
+-      console_timer.function = blank_screen;
+-      if (blankinterval) {
+-              mod_timer(&console_timer, jiffies + blankinterval);
+-      }
++      //init_timer(&console_timer);
++      //console_timer.function = blank_screen;
++      //if (blankinterval) {
++      //      mod_timer(&console_timer, jiffies + blankinterval);
++      //}
+       /*
+        * kmalloc is not running yet - we use the bootmem allocator.
+@@ -2744,11 +2744,12 @@
+  */
+ static void vesa_powerdown_screen(unsigned long dummy)
+ {
+-      console_timer.function = unblank_screen_t;
++      //console_timer.function = unblank_screen_t;
+       vesa_powerdown();
+ }
++#if 0
+ static void timer_do_blank_screen(int entering_gfx, int from_timer_handler)
+ {
+       int currcons = fg_console;
+@@ -2797,12 +2798,14 @@
+       if (vesa_blank_mode)
+               sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1);
+ }
++#endif
+ void do_blank_screen(int entering_gfx)
+ {
+-      timer_do_blank_screen(entering_gfx, 0);
++      //timer_do_blank_screen(entering_gfx, 0);
+ }
++#if 0
+ /*
+  * This is a timer handler
+  */
+@@ -2810,12 +2813,14 @@
+ {
+       unblank_screen();
+ }
++#endif
+ /*
+  * Called by timer as well as from vt_console_driver
+  */
+ void unblank_screen(void)
+ {
++#if 0
+       int currcons;
+       if (!console_blanked)
+@@ -2842,6 +2847,7 @@
+               /* Low-level driver cannot restore -> do it ourselves */
+               update_screen(fg_console);
+       set_cursor(fg_console);
++#endif
+ }
+ /*
+@@ -2849,11 +2855,12 @@
+  */
+ static void blank_screen(unsigned long dummy)
+ {
+-      timer_do_blank_screen(0, 1);
++      //timer_do_blank_screen(0, 1);
+ }
+ void poke_blanked_console(void)
+ {
++#if 0
+       del_timer(&console_timer);
+       if (!vt_cons[fg_console] || vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
+               return;
+@@ -2863,6 +2870,7 @@
+       } else if (blankinterval) {
+               mod_timer(&console_timer, jiffies + blankinterval);
+       }
++#endif
+ }
+ /*
+@@ -3088,7 +3096,7 @@
+               unblank_screen();
+               break;
+       case PM_SUSPEND:
+-              do_blank_screen(0);
++              //do_blank_screen(0);
+               break;
+       }
+       return 0;
+@@ -3106,7 +3114,8 @@
+ EXPORT_SYMBOL(video_scan_lines);
+ EXPORT_SYMBOL(vc_resize);
+ EXPORT_SYMBOL(fg_console);
+-EXPORT_SYMBOL(console_blank_hook);
++//EXPORT_SYMBOL(console_blank_hook);
++EXPORT_SYMBOL(console_driver);
+ #ifdef CONFIG_VT
+ EXPORT_SYMBOL(vt_cons);
+ #endif
+--- /dev/null
++++ linux-2.4.21/drivers/char/ds1337.c
+@@ -0,0 +1,545 @@
++/*
++ * ds1337.c
++ *
++ * Device driver for Dallas Semiconductor's Real Time Controller DS1337.
++ *
++ * Copyright (C) 2003 M&N Logistik-Lösungen Online GmbH
++ *
++ * 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.
++ *
++ * Documentation for this Chip: http://pdfserv.maxim-ic.com/arpdf/DS1337.pdf
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/version.h>
++
++#include <linux/kernel.h>
++#include <linux/poll.h>
++#include <linux/i2c.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/rtc.h>
++#include <linux/string.h>
++#include <linux/miscdevice.h>
++#include <linux/proc_fs.h>
++
++#include "ds1337.h"
++
++//#define DEBUG 1
++
++#if DEBUG
++static unsigned int rtc_debug = DEBUG;
++#else
++#define rtc_debug 0           /* gcc will remove all the debug code for us */
++#endif
++
++static unsigned short slave_address = DS1337_I2C_SLAVE_ADDR;
++struct i2c_driver ds1337_driver;
++struct i2c_client *ds1337_i2c_client = 0;
++static spinlock_t ds1337_rtc_lock = SPIN_LOCK_UNLOCKED;
++
++static unsigned short ignore[] = { I2C_CLIENT_END };
++static unsigned short normal_addr[] = { DS1337_I2C_SLAVE_ADDR, I2C_CLIENT_END };
++
++static int ds1337_rtc_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
++static int ds1337_rtc_noop(struct inode *inode, struct file *file);
++
++static int ds1337_probe(struct i2c_adapter *adap);
++static int ds1337_detach(struct i2c_client *client);
++static int ds1337_command(struct i2c_client *client, unsigned int cmd, void *arg);
++
++
++static struct i2c_client_address_data addr_data = {
++    .normal_i2c =     normal_addr,
++    .normal_i2c_range =       ignore,
++    .probe =          ignore,
++    .probe_range =    ignore,
++    .ignore =         ignore,
++    .ignore_range =   ignore,
++    .force =          ignore,
++};
++
++static struct file_operations rtc_fops = {
++    .owner =          THIS_MODULE,
++    .ioctl =          ds1337_rtc_ioctl,
++    .open =           ds1337_rtc_noop,
++    .release =                ds1337_rtc_noop,
++};
++
++static struct miscdevice ds1337_rtc_miscdev = {
++    RTC_MINOR,
++    "rtc",
++    &rtc_fops
++};
++
++
++struct i2c_driver ds1337_driver = {
++    .name =           "DS1337",
++    .id =             I2C_DRIVERID_DS1337,
++    .flags =          I2C_DF_NOTIFY,
++    .attach_adapter = ds1337_probe,
++    .detach_client =  ds1337_detach,
++    .command =                ds1337_command
++};
++
++#define DAT(x) ((unsigned int)((x)->data))    /* keep the control register info */
++
++
++static int ds1337_readram(char *buf, int len)
++{
++    unsigned long flags;
++    unsigned char ad[1] = { 0 };
++    int ret;
++    struct i2c_msg msgs[2] = {
++      {ds1337_i2c_client->addr, 0, 1, ad},
++      {ds1337_i2c_client->addr, I2C_M_RD, len, buf}
++    };
++
++    spin_lock_irqsave(&ds1337_rtc_lock, flags);
++    ret = i2c_transfer(ds1337_i2c_client->adapter, msgs, 2);
++    spin_unlock_irqrestore(&ds1337_rtc_lock, flags);
++
++    return ret;
++}
++
++
++static void ds1337_setreg(struct i2c_client *c, unsigned char reg, unsigned char val)
++{
++    unsigned char buf[2];
++    buf[0] = reg;
++    buf[1] = val;
++    i2c_master_send(c, (char *) buf, 2);
++}
++
++static int ds1337_attach(struct i2c_adapter *adap, int addr,
++                       unsigned short flags, int kind)
++{
++    struct i2c_client *c;
++    unsigned char buf[DS1337_MEM_SIZE], ad[1] = { 7 };
++    struct i2c_msg msgs[2] = {
++      {addr, 0, 1, ad},
++      {addr, I2C_M_RD, 1, buf}
++    };
++    int ret;
++
++    if (rtc_debug>1)
++      printk("%s(adap,%d,%d,%d)\n", __FUNCTION__, addr, flags, kind);
++
++    c = (struct i2c_client *) kmalloc(sizeof(*c), GFP_KERNEL);
++    if (!c)
++      return -ENOMEM;
++
++    strcpy(c->name, "DS1337");
++    c->id = ds1337_driver.id;
++    c->flags = 0;
++    c->addr = addr;
++    c->adapter = adap;
++    c->driver = &ds1337_driver;
++    c->data = NULL;
++
++    ret = i2c_transfer(c->adapter, msgs, 2);
++
++    if (ret == 2) {
++      DAT(c) = buf[0];
++    } else
++      printk("ds1337_attach(): i2c_transfer() returned %d.\n", ret);
++
++    ds1337_i2c_client = c;
++
++    ds1337_readram(buf, DS1337_MEM_SIZE);
++
++                                              // set 24 hour mode
++    ds1337_setreg(c, 0x2, buf[2] | DS1337_HOUR24);
++                                              // INTCN sets INTB to alarm2 (disables SQW)
++    ds1337_setreg(c, 0x5, buf[5] & 0x7f);     // clear century
++    ds1337_setreg(c, 0x7, 0x00);              // clear Alarm 1 seconds
++    ds1337_setreg(c, 0x8, 0x00);              // clear Alarm 1 minutes
++    ds1337_setreg(c, 0x9, 0x40);              // clear Alarm 1 hours, 24 hour on
++    ds1337_setreg(c, 0xA, 0x00);              // clear Alarm 1 date
++    ds1337_setreg(c, 0xB, 0x00);              // clear Alarm 2 minutes
++    ds1337_setreg(c, 0xC, 0x40);              // clear Alarm 2 hours, 24 hour on
++    ds1337_setreg(c, 0xD, 0x00);              // clear Alarm 2 date
++    ds1337_setreg(c, 0xe, 4);                 // nEOSC enabled
++    ds1337_setreg(c, 0xf, 0);                 // clear OSF, A2F, A1F
++
++    return i2c_attach_client(c);
++}
++
++
++static int ds1337_probe(struct i2c_adapter *adap)
++{
++    if (rtc_debug>1)
++      printk("%s()\n", __FUNCTION__);
++
++    return i2c_probe(adap, &addr_data, ds1337_attach);
++}
++
++
++static int ds1337_detach(struct i2c_client *client)
++{
++    if (rtc_debug>1)
++      printk("%s()\n", __FUNCTION__);
++
++    i2c_detach_client(client);
++
++    return 0;
++}
++
++
++static void ds1337_convert_to_time(struct rtc_time *dt, char *buf)
++{
++    if (rtc_debug>1)
++      printk("%s()\n", __FUNCTION__);
++
++    dt->tm_sec = BCD_TO_BIN(buf[0]);
++    dt->tm_min = BCD_TO_BIN(buf[1]);
++    dt->tm_hour = DS1337_HOURS_24(buf[2]);
++
++    dt->tm_mday = BCD_TO_BIN(buf[4]);
++    /* dt->tm_mon is zero-based */
++    dt->tm_mon = BCD_TO_BIN(buf[5]) - 1;
++    /* year is 1900 + dt->tm_year */
++    dt->tm_year = BCD_TO_BIN(buf[6]) + 100;
++
++    if (rtc_debug > 2) {
++      printk("ds1337_get_datetime: year = %d\n", dt->tm_year);
++      printk("ds1337_get_datetime: mon  = %d\n", dt->tm_mon);
++      printk("ds1337_get_datetime: mday = %d\n", dt->tm_mday);
++      printk("ds1337_get_datetime: hour = %d\n", dt->tm_hour);
++      printk("ds1337_get_datetime: min  = %d\n", dt->tm_min);
++      printk("ds1337_get_datetime: sec  = %d\n", dt->tm_sec);
++    }
++}
++
++
++static int ds1337_get_datetime(struct i2c_client *client,
++                             struct rtc_time *dt)
++{
++    unsigned char buf[7], addr[1] = { 0 };
++    struct i2c_msg msgs[2] = {
++      {client->addr, 0, 1, addr},
++      {client->addr, I2C_M_RD, 7, buf}
++    };
++    int ret = -EIO;
++
++    if (rtc_debug)
++      printk("%s()\n", __FUNCTION__);
++
++    memset(buf, 0, sizeof(buf));
++
++    ret = i2c_transfer(client->adapter, msgs, 2);
++
++    if (ret == 2) {
++      ds1337_convert_to_time(dt, buf);
++      ret = 0;
++    } else
++      printk("ds1337_get_datetime(), i2c_transfer() returned %d\n", ret);
++
++    return ret;
++}
++
++
++static int ds1337_set_datetime(struct i2c_client *client,
++                             struct rtc_time *dt, int datetoo)
++{
++    unsigned char buf[8];
++    int ret, len = 4;
++
++    if (rtc_debug)
++      printk("%s()\n", __FUNCTION__);
++
++    if (rtc_debug > 2) {
++      printk("ds1337_set_datetime: tm_year = %d\n", dt->tm_year);
++      printk("ds1337_set_datetime: tm_mon  = %d\n", dt->tm_mon);
++      printk("ds1337_set_datetime: tm_mday = %d\n", dt->tm_mday);
++      printk("ds1337_set_datetime: tm_hour = %d\n", dt->tm_hour);
++      printk("ds1337_set_datetime: tm_min  = %d\n", dt->tm_min);
++      printk("ds1337_set_datetime: tm_sec  = %d\n", dt->tm_sec);
++    }
++
++    buf[0] = 0;                       /* register address on DS1337 */
++    buf[1] = (BIN_TO_BCD(dt->tm_sec));
++    buf[2] = (BIN_TO_BCD(dt->tm_min));
++    buf[3] = (BIN_TO_BCD(dt->tm_hour)) | DS1337_HOUR24;
++
++    if (datetoo) {
++      len = 8;
++      /* we skip buf[4] as we don't use day-of-week. */
++      buf[5] = (BIN_TO_BCD(dt->tm_mday));
++      buf[6] = (BIN_TO_BCD(dt->tm_mon + 1));
++      /* The year only ranges from 0-99, we are being passed an offset from 1900,
++       * and the chip calulates leap years based on 2000, thus we adjust by 100.
++       */
++      buf[7] = (BIN_TO_BCD(dt->tm_year - 100));
++    }
++    ret = i2c_master_send(client, (char *) buf, len);
++    if (ret == len)
++      ret = 0;
++    else
++      printk("ds1337_set_datetime(), i2c_master_send() returned %d\n",
++             ret);
++
++
++    return ret;
++}
++
++
++#if 0
++static int ds1337_get_ctrl(struct i2c_client *client, unsigned char *ctrl)
++{
++    *ctrl = DAT(client);
++
++    if (rtc_debug)
++      printk("%s():%d\n", __FUNCTION__, *ctrl);
++
++    return 0;
++}
++
++
++static int ds1337_set_ctrl(struct i2c_client *client, unsigned char *cinfo)
++{
++    unsigned char buf[2];
++    int ret;
++
++    if (rtc_debug)
++      printk("%s(%d)\n", __FUNCTION__, *cinfo);
++
++    buf[0] = 7;                       /* control register address on DS1337 */
++    buf[1] = *cinfo;
++    /* save the control reg info in the client data field so that get_ctrl
++     * function doesn't have to do an I2C transfer to get it.
++     */
++    DAT(client) = buf[1];
++
++    ret = i2c_master_send(client, (char *) buf, 2);
++
++    return ret;
++}
++#endif
++
++
++static int ds1337_command(struct i2c_client *client, unsigned int cmd,
++                        void *arg)
++{
++    if (rtc_debug)
++      printk("%s(client,,%u,arg)\n", __FUNCTION__, cmd);
++
++    switch (cmd) {
++    case DS1337_GETDATETIME:
++      return ds1337_get_datetime(client, arg);
++
++    case DS1337_SETTIME:
++      return ds1337_set_datetime(client, arg, 0);
++
++    case DS1337_SETDATETIME:
++      return ds1337_set_datetime(client, arg, 1);
++
++    default:
++      return -EINVAL;
++    }
++}
++
++
++static int ds1337_rtc_noop(struct inode *inode, struct file *file)
++{
++    return 0;
++}
++
++
++static int ds1337_rtc_ioctl(struct inode *inode, struct file *file,
++                          unsigned int cmd, unsigned long arg)
++{
++    unsigned long flags;
++    struct rtc_time wtime;
++    int status = 0;
++
++    if (rtc_debug)
++      printk("%s()\n", __FUNCTION__);
++
++    switch (cmd) {
++    default:
++    case RTC_UIE_ON:          // mask ints from RTC updates
++    case RTC_UIE_OFF:
++    case RTC_PIE_ON:          // allow periodic interrupts
++    case RTC_PIE_OFF:
++    case RTC_AIE_ON:          // mask alarm int enable bit
++    case RTC_AIE_OFF:
++    case RTC_ALM_SET:
++      /*
++       * This expects a struct rtc_time. Writing 0xff means
++       * "don't care" or "match all". Only the tm_hour,
++       * tm_min and tm_sec are used.
++       */
++    case RTC_ALM_READ:
++      // get_rtc_alm_time(&wtime);
++    case RTC_IRQP_READ:               // Read the periodic IRQ rate
++    case RTC_IRQP_SET:                // Set periodic IRQ rate
++    case RTC_EPOCH_READ:
++      // return put_user (epoch, (unsigned long *)arg);
++    case RTC_EPOCH_SET:
++    case RTC_WKALM_SET:
++    case RTC_WKALM_RD:
++      status = -EINVAL;
++      break;
++
++    case RTC_RD_TIME:
++      spin_lock_irqsave(&ds1337_rtc_lock, flags);
++      ds1337_command(ds1337_i2c_client, DS1337_GETDATETIME, &wtime);
++      spin_unlock_irqrestore(&ds1337_rtc_lock, flags);
++
++      if (copy_to_user((void *) arg, &wtime, sizeof(struct rtc_time)))
++          status = -EFAULT;
++      break;
++
++    case RTC_SET_TIME:
++      if (!capable(CAP_SYS_TIME)) {
++          status = -EACCES;
++          break;
++      }
++
++      if (copy_from_user
++          (&wtime, (struct rtc_time *) arg, sizeof(struct rtc_time))) {
++          status = -EFAULT;
++          break;
++      }
++
++      spin_lock_irqsave(&ds1337_rtc_lock, flags);
++      ds1337_command(ds1337_i2c_client, DS1337_SETDATETIME, &wtime);
++      spin_unlock_irqrestore(&ds1337_rtc_lock, flags);
++      break;
++    }
++
++    return status;
++}
++
++
++static char *ds1337_mon2str(unsigned int mon)
++{
++    char *mon2str[12] = {
++      "Jan", "Feb", "Mar", "Apr", "May", "Jun",
++      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
++    };
++    if (mon > 11)
++      return "error";
++    else
++      return mon2str[mon];
++}
++
++
++static int ds1337_rtc_proc_output(char *buf)
++{
++#define CHECK(ctrl,bit) ((ctrl & bit) ? "yes" : "no")
++
++    unsigned char ram[DS1337_MEM_SIZE];
++    int ret;
++
++    char *p = buf;
++
++    ret = ds1337_readram(ram, DS1337_MEM_SIZE);
++    if (ret > 0) {
++#ifdef DEBUG
++      int i;
++      char text[9];
++#endif
++      struct rtc_time dt;
++
++      p += sprintf(p, "DS1337 (i2c Serial Real Time Clock)\n");
++
++      ds1337_convert_to_time(&dt, ram);
++      p += sprintf(p, "Date/Time: %02d-%s-%04d %02d:%02d:%02d\n",
++                   dt.tm_mday, ds1337_mon2str(dt.tm_mon),
++                   dt.tm_year + 1900, dt.tm_hour, dt.tm_min, dt.tm_sec);
++
++#ifdef DEBUG
++      p += sprintf(p, "RAM dump:\n");
++      text[8] = '\0';
++      for (i = 0; i < DS1337_MEM_SIZE; i++) {
++          if ((i % 8) == 0)
++              p += sprintf(p, "%02X: ", i);
++          p += sprintf(p, "%02X ", ram[i]);
++
++          if ((ram[i] < 32) || (ram[i] > 126))
++              ram[i] = '.';
++          text[i % 8] = ram[i];
++          if ((i % 8) == 7)
++              p += sprintf(p, "%s\n", text);
++      }
++      p += sprintf(p, "\n");
++#endif
++    } else {
++      p += sprintf(p, "Failed to read RTC memory!\n");
++    }
++
++    return p - buf;
++}
++
++
++static int ds1337_rtc_read_proc(char *page, char **start, off_t off,
++                              int count, int *eof, void *data)
++{
++    int len = ds1337_rtc_proc_output(page);
++
++    if (len <= off + count)
++      *eof = 1;
++    *start = page + off;
++    len -= off;
++    if (len > count)
++      len = count;
++    if (len < 0)
++      len = 0;
++    return len;
++}
++
++
++static __init int ds1337_init(void)
++{
++    int retval = 0;
++
++    if (rtc_debug>1)
++      printk("%s()\n", __FUNCTION__);
++
++    if (slave_address != 0xffff) {
++      normal_addr[0] = slave_address;
++    }
++
++    if (normal_addr[0] == 0xffff) {
++      printk(KERN_ERR
++             "I2C: Invalid slave address for DS1337 RTC (%#x)\n",
++             normal_addr[0]);
++      return -EINVAL;
++    }
++
++    retval = i2c_add_driver(&ds1337_driver);
++
++    if (retval == 0) {
++      misc_register(&ds1337_rtc_miscdev);
++      create_proc_read_entry(DS1337_PROC_NAME, 0, 0,
++                             ds1337_rtc_read_proc, NULL);
++      printk("I2C: DS1337 RTC driver loaded\n");
++    }
++    return retval;
++}
++
++
++static __exit void ds1337_exit(void)
++{
++    if (rtc_debug>1)
++      printk("%s()\n", __FUNCTION__);
++
++    remove_proc_entry(DS1337_PROC_NAME, NULL);
++    misc_deregister(&ds1337_rtc_miscdev);
++    i2c_del_driver(&ds1337_driver);
++}
++
++
++module_init(ds1337_init);
++module_exit(ds1337_exit);
++
++MODULE_PARM(slave_address, "i");
++MODULE_PARM_DESC(slave_address, "I2C slave address for DS1337 RTC");
++
++MODULE_AUTHOR("M&N Logistik-Lösungen Online GmbH");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ linux-2.4.21/drivers/char/ds1337.h
+@@ -0,0 +1,43 @@
++/*
++ * ds1337.h
++ *
++ * Copyright (C) 2003 M&N Logistik-Lösungen Online GmbH
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++#ifndef DS1337_H
++#define DS1337_H
++
++#define DS1337_I2C_SLAVE_ADDR 0x68
++//#define DS1337_RAM_ADDR_START       0x10
++//#define DS1337_RAM_ADDR_END 0x10
++#define DS1337_MEM_SIZE               0x10
++
++#define DS1337_PROC_NAME      "driver/ds1337"
++
++struct rtc_mem {
++      unsigned int    loc;
++      unsigned int    nr;
++      unsigned char   *data;
++};
++
++#define DS1337_GETDATETIME    0
++#define DS1337_SETTIME                1
++#define DS1337_SETDATETIME    2
++
++#define DS1337_RATE_1HZ       0x00    /* Rate Select     1 Hz */
++#define DS1337_RATE_4096HZ    0x01    /* Rate Select  4096 kHz */
++#define DS1337_RATE_8192HZ    0x02    /* Rate Select  8192 kHz */
++#define DS1337_RATE_32768HZ   0x03    /* Rate Select 32768 kHz */
++
++#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
++#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
++
++#define DS1337_HOUR12         0x40
++#define DS1337_HOUR24         0x00
++#define DS1337_HOURS_24(val)  BCD_TO_BIN((val & 0x3f))
++
++#endif
+--- /dev/null
++++ linux-2.4.21/drivers/char/german.map
+@@ -0,0 +1,528 @@
++keymaps 0-2,4-6,8-10,12
++keycode   1 = Escape           Escape          
++      alt     keycode   1 = Meta_Escape     
++      shift   alt     keycode   1 = Meta_Escape     
++keycode   2 = one              exclam          
++      alt     keycode   2 = Meta_one        
++      shift   alt     keycode   2 = Meta_exclam     
++keycode   3 = two              quotedbl         twosuperior      nul             
++      alt     keycode   3 = Meta_two        
++      shift   alt     keycode   3 = Meta_quotedbl   
++      control alt     keycode   3 = Meta_nul        
++keycode   4 = three            section          threesuperior    Escape          
++      alt     keycode   4 = Meta_three      
++      control alt     keycode   4 = Meta_Escape     
++keycode   5 = four             dollar          
++      alt     keycode   5 = Meta_four       
++      shift   alt     keycode   5 = Meta_dollar     
++keycode   6 = five             percent         
++      alt     keycode   6 = Meta_five       
++      shift   alt     keycode   6 = Meta_percent    
++keycode   7 = six              ampersand       
++      control keycode   7 = Control_asciicircum
++      alt     keycode   7 = Meta_six        
++      shift   alt     keycode   7 = Meta_ampersand  
++keycode   8 = seven            slash            braceleft       
++      alt     keycode   8 = Meta_seven      
++      shift   alt     keycode   8 = Meta_slash      
++      altgr   alt     keycode   8 = Meta_braceleft  
++keycode   9 = eight            parenleft        bracketleft     
++      alt     keycode   9 = Meta_eight      
++      shift   alt     keycode   9 = Meta_parenleft  
++      altgr   alt     keycode   9 = Meta_bracketleft
++keycode  10 = nine             parenright       bracketright    
++      altgr   control keycode  10 = Control_bracketright
++      alt     keycode  10 = Meta_nine       
++      shift   alt     keycode  10 = Meta_parenright 
++      altgr   alt     keycode  10 = Meta_bracketright
++keycode  11 = zero             equal            braceright      
++      alt     keycode  11 = Meta_zero       
++      shift   alt     keycode  11 = Meta_equal      
++      altgr   alt     keycode  11 = Meta_braceright 
++keycode  12 = ssharp           question         backslash       
++      altgr   control keycode  12 = Control_backslash
++      shift   alt     keycode  12 = Meta_question   
++      altgr   alt     keycode  12 = Meta_backslash  
++keycode  13 = apostrophe       grave           
++      alt     keycode  13 = 0x08b4          
++      shift   alt     keycode  13 = Meta_grave      
++keycode  14 = BackSpace           Delete
++      alt     keycode  14 = Meta_BackSpace  
++      shift   alt     keycode  14 = Meta_Delete     
++keycode  15 = Tab              Tab             
++      alt     keycode  15 = Meta_Tab        
++      shift   alt     keycode  15 = Meta_Tab        
++keycode  16 = +q                +Q                at               Control_q        Control_q        Control_q        Meta_q           Meta_Q           Meta_at          Meta_Control_q  
++keycode  17 = w               
++keycode  18 = +e                +E                currency         Control_e        Control_e        Control_e        Meta_e           Meta_E           Meta_e           Meta_Control_e  
++keycode  19 = r               
++keycode  20 = t               
++keycode  21 = z               
++keycode  22 = u               
++keycode  23 = i               
++keycode  24 = o               
++keycode  25 = p               
++keycode  26 = +udiaeresis       +Udiaeresis      
++keycode  27 = plus             asterisk         asciitilde      
++      alt     keycode  27 = Meta_plus       
++      shift   alt     keycode  27 = Meta_asterisk   
++keycode  28 = Return          
++      alt     keycode  28 = Meta_Control_m  
++keycode  29 = Control         
++keycode  30 = a               
++keycode  31 = s               
++keycode  32 = d               
++keycode  33 = f               
++keycode  34 = g               
++keycode  35 = h               
++keycode  36 = j               
++keycode  37 = k               
++keycode  38 = l               
++keycode  39 = +odiaeresis       +Odiaeresis      
++keycode  40 = +adiaeresis       +Adiaeresis      
++keycode  41 = asciicircum      degree           Meta_asciicircum Control_asciicircum
++      control alt     keycode  41 = Meta_Control_asciicircum
++keycode  42 = Shift           
++keycode  43 = numbersign       apostrophe      
++      alt     keycode  43 = Meta_numbersign 
++      shift   alt     keycode  43 = Meta_apostrophe 
++keycode  44 = y               
++keycode  45 = x               
++keycode  46 = c               
++keycode  47 = v               
++keycode  48 = b               
++keycode  49 = n               
++keycode  50 = +m                +M                mu               Control_m        Control_m        Control_m        Meta_m           Meta_M           Meta_m           Meta_Control_m  
++keycode  51 = comma            semicolon       
++      alt     keycode  51 = Meta_comma      
++      shift   alt     keycode  51 = Meta_semicolon  
++keycode  52 = period           colon           
++      alt     keycode  52 = Meta_period     
++      shift   alt     keycode  52 = Meta_colon      
++keycode  53 = minus            underscore       Meta_minus      
++      shift   control keycode  53 = Control_underscore
++      alt     keycode  53 = Meta_minus      
++      shift   alt     keycode  53 = Meta_underscore 
++keycode  54 = Shift           
++keycode  55 = KP_Multiply     
++      altgr   keycode  55 = Hex_C           
++keycode  56 = Alt             
++keycode  57 = space            space            Meta_space       nul             
++      alt     keycode  57 = Meta_space      
++      shift   alt     keycode  57 = Meta_space      
++      control alt     keycode  57 = Meta_nul        
++keycode  58 = Caps_Lock       
++keycode  59 = F1               F13              Console_13       F25             
++      altgr   control keycode  59 = F1              
++      alt     keycode  59 = Console_1       
++      control alt     keycode  59 = Console_1       
++keycode  60 = F2               F14              Console_14       F26             
++      altgr   control keycode  60 = F2              
++      alt     keycode  60 = Console_2       
++      control alt     keycode  60 = Console_2       
++keycode  61 = F3               F15              Console_15       F27             
++      altgr   control keycode  61 = F3              
++      alt     keycode  61 = Console_3       
++      control alt     keycode  61 = Console_3       
++keycode  62 = F4               F16              Console_16       F28             
++      altgr   control keycode  62 = F4              
++      alt     keycode  62 = Console_4       
++      control alt     keycode  62 = Console_4       
++keycode  63 = F5               F17              Console_17       F29             
++      altgr   control keycode  63 = F5              
++      alt     keycode  63 = Console_5       
++      control alt     keycode  63 = Console_5       
++keycode  64 = F6               F18              Console_18       F30             
++      altgr   control keycode  64 = F6              
++      alt     keycode  64 = Console_6       
++      control alt     keycode  64 = Console_6       
++keycode  65 = F7               F19              Console_19       F31             
++      altgr   control keycode  65 = F7              
++      alt     keycode  65 = Console_7       
++      control alt     keycode  65 = Console_7       
++keycode  66 = F8               F20              Console_20       F32             
++      altgr   control keycode  66 = F8              
++      alt     keycode  66 = Console_8       
++      control alt     keycode  66 = Console_8       
++keycode  67 = F9               F21              Console_21       F33             
++      altgr   control keycode  67 = F9              
++      alt     keycode  67 = Console_9       
++      control alt     keycode  67 = Console_9       
++keycode  68 = F10              F22              Console_22       F34             
++      altgr   control keycode  68 = F10             
++      alt     keycode  68 = Console_10      
++      control alt     keycode  68 = Console_10      
++keycode  69 = Num_Lock        
++      altgr   keycode  69 = Hex_A           
++keycode  70 = Scroll_Lock      Show_Memory      Show_Registers   Show_State      
++      alt     keycode  70 = Scroll_Lock     
++keycode  71 = KP_7            
++      altgr   keycode  71 = Hex_7           
++      alt     keycode  71 = Ascii_7         
++keycode  72 = KP_8            
++      altgr   keycode  72 = Hex_8           
++      alt     keycode  72 = Ascii_8         
++keycode  73 = KP_9            
++      altgr   keycode  73 = Hex_9           
++      alt     keycode  73 = Ascii_9         
++keycode  74 = KP_Subtract     
++      altgr   keycode  74 = Hex_D           
++keycode  75 = KP_4            
++      altgr   keycode  75 = Hex_4           
++      alt     keycode  75 = Ascii_4         
++keycode  76 = KP_5            
++      altgr   keycode  76 = Hex_5           
++      alt     keycode  76 = Ascii_5         
++keycode  77 = KP_6            
++      altgr   keycode  77 = Hex_6           
++      alt     keycode  77 = Ascii_6         
++keycode  78 = KP_Add          
++      altgr   keycode  78 = Hex_E           
++keycode  79 = KP_1            
++      altgr   keycode  79 = Hex_1           
++      alt     keycode  79 = Ascii_1         
++keycode  80 = KP_2            
++      altgr   keycode  80 = Hex_2           
++      alt     keycode  80 = Ascii_2         
++keycode  81 = KP_3            
++      altgr   keycode  81 = Hex_3           
++      alt     keycode  81 = Ascii_3         
++keycode  82 = KP_0            
++      altgr   keycode  82 = Hex_0           
++      alt     keycode  82 = Ascii_0         
++keycode  83 = KP_Comma        
++      altgr   control keycode  83 = Boot            
++      control alt     keycode  83 = Boot            
++#keycode  84 = Last_Console    
++keycode  85 =
++keycode  86 = less             greater          bar             
++      alt     keycode  86 = Meta_less       
++      shift   alt     keycode  86 = Meta_greater    
++      altgr   alt     keycode  86 = Meta_bar        
++keycode  87 = F11              F23              Console_23       F35             
++      altgr   control keycode  87 = F11             
++      alt     keycode  87 = Console_11      
++      control alt     keycode  87 = Console_11      
++keycode  88 = F12              F24              Console_24       F36             
++      altgr   control keycode  88 = F12             
++      alt     keycode  88 = Console_12      
++      control alt     keycode  88 = Console_12      
++keycode  89 = slash            question         degree          
++      alt     keycode  89 = Meta_slash      
++      shift   alt     keycode  89 = Meta_question   
++keycode  90 =
++keycode  91 =
++keycode  92 =
++keycode  93 =
++keycode  94 =
++keycode  95 =
++keycode  96 = KP_Enter        
++      altgr   keycode  96 = Hex_F           
++keycode  97 = Control         
++keycode  98 = KP_Divide       
++      altgr   keycode  98 = Hex_B           
++keycode  99 = Compose         
++keycode 100 = AltGr           
++      alt     keycode 100 = Compose         
++keycode 101 = Break           
++keycode 102 = Find            
++keycode 103 = Up              
++      alt     keycode 103 = KeyboardSignal  
++keycode 104 = Prior           
++      shift   keycode 104 = Scroll_Backward 
++keycode 105 = Left            
++#     alt     keycode 105 = Decr_Console    
++keycode 106 = Right           
++#     alt     keycode 106 = Incr_Console    
++keycode 107 = Select          
++keycode 108 = Down            
++keycode 109 = Next            
++      shift   keycode 109 = Scroll_Forward  
++keycode 110 = Insert          
++keycode 111 = Remove          
++      altgr   control keycode 111 = Boot            
++      control alt     keycode 111 = Boot            
++keycode 112 = Macro           
++      shift   alt     keycode 112 = VoidSymbol      
++      altgr   alt     keycode 112 = VoidSymbol      
++keycode 113 = F13             
++      shift   alt     keycode 113 = VoidSymbol      
++      altgr   alt     keycode 113 = VoidSymbol      
++keycode 114 = F14             
++      shift   alt     keycode 114 = VoidSymbol      
++      altgr   alt     keycode 114 = VoidSymbol      
++keycode 115 = Help            
++      shift   alt     keycode 115 = VoidSymbol      
++      altgr   alt     keycode 115 = VoidSymbol      
++keycode 116 = Do              
++      shift   alt     keycode 116 = VoidSymbol      
++      altgr   alt     keycode 116 = VoidSymbol      
++keycode 117 = F17             
++      shift   alt     keycode 117 = VoidSymbol      
++      altgr   alt     keycode 117 = VoidSymbol      
++keycode 118 = KP_MinPlus      
++      shift   alt     keycode 118 = VoidSymbol      
++      altgr   alt     keycode 118 = VoidSymbol      
++keycode 119 = Pause           
++keycode 120 =
++keycode 121 =
++keycode 122 =
++keycode 123 =
++keycode 124 =
++#keycode 125 = Decr_Console    
++#keycode 126 = Incr_Console    
++keycode 127 = Compose         
++string F1 = "\033[[A"
++string F2 = "\033[[B"
++string F3 = "\033[[C"
++string F4 = "\033[[D"
++string F5 = "\033[[E"
++string F6 = "\033[17~"
++string F7 = "\033[18~"
++string F8 = "\033[19~"
++string F9 = "\033[20~"
++string F10 = "\033[21~"
++string F11 = "\033[23~"
++string F12 = "\033[24~"
++string F13 = "\033[25~"
++string F14 = "\033[26~"
++string F15 = "\033[28~"
++string F16 = "\033[29~"
++string F17 = "\033[31~"
++string F18 = "\033[32~"
++string F19 = "\033[33~"
++string F20 = "\033[34~"
++string Find = "\033[1~"
++string Insert = "\033[2~"
++string Remove = "\033[3~"
++string Select = "\033[4~"
++string Prior = "\033[5~"
++string Next = "\033[6~"
++string Macro = "\033[M"
++string Pause = "\033[P"
++compose '!' '!' to '¡'
++compose '"' 'A' to 'Ä'
++compose '"' 'E' to 'Ë'
++compose '"' 'I' to 'Ï'
++compose '"' 'O' to 'Ö'
++compose '"' 'U' to 'Ü'
++compose '"' 'Y' to '¾'
++compose '"' 'a' to 'ä'
++compose '"' 'c' to '©'
++compose '"' 'e' to 'ë'
++compose '"' 'i' to 'ï'
++compose '"' 'o' to 'ö'
++compose '"' 'r' to '®'
++compose '"' 'u' to 'ü'
++compose '"' 'y' to 'ÿ'
++compose '(' 'c' to '©'
++compose '(' 'r' to '®'
++compose '+' '-' to '±'
++compose ',' 'A' to '¡'
++compose ',' 'C' to 'Ç'
++compose ',' 'E' to 'Ê'
++compose ',' 'G' to '«'
++compose ',' 'I' to 'Ç'
++compose ',' 'K' to 'Ó'
++compose ',' 'L' to '¦'
++compose ',' 'N' to 'Ñ'
++compose ',' 'R' to '£'
++compose ',' 'S' to 'ª'
++compose ',' 'T' to 'Þ'
++compose ',' 'U' to 'Ù'
++compose ',' 'a' to '±'
++compose ',' 'c' to 'ç'
++compose ',' 'e' to 'ê'
++compose ',' 'g' to '»'
++compose ',' 'i' to 'ç'
++compose ',' 'k' to 'ó'
++compose ',' 'l' to '¶'
++compose ',' 'n' to 'ñ'
++compose ',' 'r' to '³'
++compose ',' 's' to 'º'
++compose ',' 't' to 'þ'
++compose ',' 'u' to 'ù'
++compose '-' ':' to '÷'
++compose '-' 'A' to 'ª'
++compose '-' 'C' to '¢'
++compose '-' 'D' to 'Ð'
++compose '-' 'E' to '¤'
++compose '-' 'H' to '¡'
++compose '-' 'L' to '£'
++compose '-' 'O' to 'º'
++compose '-' 'T' to '¬'
++compose '-' 'Y' to '¥'
++compose '-' 'a' to 'ª'
++compose '-' 'c' to '¢'
++compose '-' 'd' to 'ð'
++compose '-' 'e' to '¤'
++compose '-' 'h' to '±'
++compose '-' 'l' to '£'
++compose '-' 'l' to '¥'
++compose '-' 'l' to '³'
++compose '-' 'o' to 'º'
++compose '-' 't' to '¼'
++compose '.' '.' to '·'
++compose '.' 'C' to 'Å'
++compose '.' 'C' to 'Õ'
++compose '.' 'E' to 'Ì'
++compose '.' 'I' to '©'
++compose '.' 'Z' to '¯'
++compose '.' 'c' to 'å'
++compose '.' 'c' to 'õ'
++compose '.' 'e' to 'ì'
++compose '.' 'i' to '¹'
++compose '.' 'z' to '¿'
++compose '/' 'D' to 'Ð'
++compose '/' 'L' to '£'
++compose '/' 'O' to 'Ø'
++compose '/' 'T' to '¬'
++compose '/' 'c' to '¢'
++compose '/' 'd' to 'ð'
++compose '/' 'l' to '³'
++compose '/' 'o' to 'ø'
++compose '/' 't' to '¼'
++compose '0' 'A' to 'Å'
++compose '0' 'U' to 'Ù'
++compose '0' 'a' to 'å'
++compose '0' 'u' to 'ù'
++compose '1' '2' to '½'
++compose '1' '4' to '¼'
++compose '3' '4' to '¾'
++compose ':' '-' to '÷'
++compose ':' 'A' to 'Ä'
++compose ':' 'E' to 'Ë'
++compose ':' 'O' to 'Ö'
++compose ':' 'U' to 'Ü'
++compose ':' 'a' to 'ä'
++compose ':' 'e' to 'ë'
++compose ':' 'o' to 'ö'
++compose ':' 'u' to 'ü'
++compose '<' '<' to '«'
++compose '>' '>' to '»'
++compose '?' '?' to '¿'
++compose 'A' 'A' to 'Å'
++compose 'A' 'E' to 'Æ'
++compose 'I' 'J' to '¾'
++compose 'L' '=' to '£'
++compose 'N' 'G' to '½'
++compose 'N' 'H' to 'Ñ'
++compose 'N' 'N' to 'Ñ'
++compose 'N' 'Y' to 'Ñ'
++compose 'N' 'h' to 'Ñ'
++compose 'N' 'n' to 'Ñ'
++compose 'N' 'y' to 'Ñ'
++compose 'O' 'A' to 'Å'
++compose 'O' 'E' to '¼'
++compose 'O' 'e' to '¼'
++compose 'T' 'H' to 'Þ'
++compose 'U' 'U' to 'Ù'
++compose 'Y' '=' to '¥'
++compose '\'' 'A' to 'Á'
++compose '\'' 'C' to 'Æ'
++compose '\'' 'E' to 'É'
++compose '\'' 'I' to 'Í'
++compose '\'' 'L' to 'Å'
++compose '\'' 'N' to 'Ñ'
++compose '\'' 'O' to 'Ó'
++compose '\'' 'R' to 'À'
++compose '\'' 'S' to '¦'
++compose '\'' 'U' to 'Ú'
++compose '\'' 'Y' to 'Ý'
++compose '\'' 'Z' to '¬'
++compose '\'' 'a' to 'á'
++compose '\'' 'c' to 'æ'
++compose '\'' 'e' to 'é'
++compose '\'' 'i' to 'í'
++compose '\'' 'l' to 'å'
++compose '\'' 'n' to 'ñ'
++compose '\'' 'o' to 'ó'
++compose '\'' 'r' to 'à'
++compose '\'' 's' to '¶'
++compose '\'' 'u' to 'ú'
++compose '\'' 'y' to 'ý'
++compose '\'' 'z' to '¼'
++compose '^' '!' to '¡'
++compose '^' '*' to '×'
++compose '^' '.' to '·'
++compose '^' '/' to '÷'
++compose '^' '1' to '¹'
++compose '^' '2' to '²'
++compose '^' '3' to '³'
++compose '^' ':' to '÷'
++compose '^' '?' to '¿'
++compose '^' 'A' to 'Â'
++compose '^' 'C' to 'Ç'
++compose '^' 'D' to 'Ð'
++compose '^' 'E' to 'Ê'
++compose '^' 'G' to 'Ô'
++compose '^' 'H' to '¦'
++compose '^' 'I' to 'Î'
++compose '^' 'J' to '¬'
++compose '^' 'L' to '¥'
++compose '^' 'N' to 'Ñ'
++compose '^' 'R' to 'Ø'
++compose '^' 'S' to '¦'
++compose '^' 'T' to '«'
++compose '^' 'U' to 'Û'
++compose '^' 'Z' to '´'
++compose '^' 'a' to 'â'
++compose '^' 'c' to 'ç'
++compose '^' 'd' to 'ð'
++compose '^' 'e' to 'ê'
++compose '^' 'g' to 'ø'
++compose '^' 'h' to '¶'
++compose '^' 'i' to 'î'
++compose '^' 'j' to '¼'
++compose '^' 'l' to 'µ'
++compose '^' 'n' to 'ñ'
++compose '^' 'o' to 'ô'
++compose '^' 'r' to 'ø'
++compose '^' 's' to '¨'
++compose '^' 't' to '»'
++compose '^' 'u' to 'û'
++compose '^' 'x' to '×'
++compose '^' 'z' to '¸'
++compose '`' 'A' to 'À'
++compose '`' 'E' to 'È'
++compose '`' 'I' to 'Ì'
++compose '`' 'O' to 'Ò'
++compose '`' 'U' to 'Ù'
++compose '`' 'a' to 'à'
++compose '`' 'e' to 'è'
++compose '`' 'i' to 'ì'
++compose '`' 'o' to 'ò'
++compose '`' 'u' to 'ù'
++compose 'a' 'a' to 'å'
++compose 'a' 'e' to 'æ'
++compose 'c' '/' to '¢'
++compose 'c' '=' to '¢'
++compose 'e' '=' to '¤'
++compose 'i' 'j' to 'ÿ'
++compose 'm' 'u' to 'µ'
++compose 'n' 'g' to '¿'
++compose 'n' 'h' to 'ñ'
++compose 'n' 'n' to 'ñ'
++compose 'o' 'a' to 'å'
++compose 'o' 'e' to '½'
++compose 's' 's' to 'ß'
++compose 's' 'z' to 'ß'
++compose 't' 'h' to 'þ'
++compose 'u' 'u' to 'ù'
++compose 'v' 'S' to '¦'
++compose 'v' 'Z' to '´'
++compose 'v' 's' to '¨'
++compose 'v' 'z' to '¸'
++compose 'x' 'x' to '×'
++compose '~' 'A' to 'Ã'
++compose '~' 'G' to '«'
++compose '~' 'I' to '¥'
++compose '~' 'N' to 'Ñ'
++compose '~' 'O' to 'Õ'
++compose '~' 'U' to 'Ý'
++compose '~' 'a' to 'ã'
++compose '~' 'g' to '»'
++compose '~' 'i' to 'µ'
++compose '~' 'n' to 'ñ'
++compose '~' 'o' to 'õ'
++compose '~' 'u' to 'ý'
+--- /dev/null
++++ linux-2.4.21/drivers/char/input_keyb.c
+@@ -0,0 +1,167 @@
++/*
++ * linux/drivers/char/input_keyb.c by Russ Dill <Russ.Dill@asu.edu>
++ * taken from pc_keyb.c
++ *
++ * This code grabs keypresses from the input layer and makes them
++ * available to the console.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++
++#include <linux/config.h>
++#include <linux/module.h>
++
++#include <asm/uaccess.h>
++#include <asm/keyboard.h>
++
++/* Simple translation table for the SysRq keys */
++
++unsigned char input_sysrq_xlate[128] =
++      "\000\0331234567890-=\177\t"                    /* 0x00 - 0x0f */
++      "qwertyuiop[]\r\000as"                          /* 0x10 - 0x1f */
++      "dfghjkl;'`\000\\zxcv"                          /* 0x20 - 0x2f */
++      "bnm,./\000*\000 \000\201\202\203\204\205"      /* 0x30 - 0x3f */
++      "\206\207\210\211\212\000\000789-456+1"         /* 0x40 - 0x4f */
++      "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
++      "\r\000/";                                      /* 0x60 - 0x6f */
++
++/*
++ * Translation of escaped scancodes to keycodes.
++ * This is now user-settable.
++ * The keycodes 1-88,96-111,119 are fairly standard, and
++ * should probably not be changed - changing might confuse X.
++ * X also interprets scancode 0x5d (KEY_Begin).
++ *
++ * For 1-88 keycode equals scancode.
++ */
++
++#define E0_KPENTER 96
++#define E0_RCTRL   97
++#define E0_KPSLASH 98
++#define E0_PRSCR   99
++#define E0_RALT    100
++#define E0_BREAK   101  /* (control-pause) */
++#define E0_HOME    102
++#define E0_UP      103
++#define E0_PGUP    104
++#define E0_LEFT    105
++#define E0_RIGHT   106
++#define E0_END     107
++#define E0_DOWN    108
++#define E0_PGDN    109
++#define E0_INS     110
++#define E0_DEL     111
++
++#define E1_PAUSE   119
++
++/*
++ * New microsoft keyboard is rumoured to have
++ * e0 5b (left window button), e0 5c (right window button),
++ * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
++ * [or: Windows_L, Windows_R, TaskMan]
++ */
++#define E0_MSLW       125
++
++static unsigned char e0_keys[128] = {
++  0, 0, 0, 0, 0, 0, 0, 0,                           /* 0x00-0x07 */
++  0, 0, 0, 0, 0, 0, 0, 0,                           /* 0x08-0x0f */
++  0, 0, 0, 0, 0, 0, 0, 0,                           /* 0x10-0x17 */
++  0, 0, 0, 0, 0, E0_RCTRL, 0, 0,                    /* 0x18-0x1f */
++  0, 0, 0, 0, 0, 0, 0, 0,                           /* 0x20-0x27 */
++  0, 0, 0, 0, 0, 0, 0, 0,                           /* 0x28-0x2f */
++  0, 0, 0, 0, 0, 0, 0, E0_PRSCR,                    /* 0x30-0x37 */
++  E0_RALT, 0, 0, 0, 0, 0, 0, 0,                             /* 0x38-0x3f */
++  0, 0, 0, 0, 0, 0, E0_BREAK, E0_HOME,                      /* 0x40-0x47 */
++  E0_UP, E0_PGUP, 0, E0_LEFT, 0, E0_RIGHT, 0, E0_END, /* 0x48-0x4f */
++  E0_DOWN, E0_PGDN, 0, 0, 0, 0, 0, 0,               /* 0x50-0x57 */
++  0, 0, 0, E0_MSLW, 0, 0, 0, 0,                             /* 0x58-0x5f */
++  0, 0, 0, 0, 0, 0, 0, 0,                           /* 0x60-0x67 */
++  0, 0, 0, 0, 0, 0, 0, 0,                           /* 0x68-0x6f */
++  0, 0, 0, 0, 0, 0, 0, 0,                           /* 0x70-0x77 */
++  0, 0, 0, 0, 0, 0, 0, 0                            /* 0x78-0x7f */
++};
++
++int input_setkeycode(unsigned int scancode, unsigned int keycode)
++{
++      if (scancode > 255 || keycode > 127) return -EINVAL;
++      e0_keys[scancode - 128] = keycode;
++      return 0;
++}
++
++int input_getkeycode(unsigned int scancode)
++{
++      return scancode > 255 ? -EINVAL : e0_keys[scancode - 128];
++}
++
++#define KBD_REPORT_UNKN
++int input_translate(unsigned char scancode, unsigned char *keycode,
++                  char raw_mode)
++{
++      static int prev_scancode;
++
++      /* special prefix scancodes.. */
++      if (scancode == 0xe0 || scancode == 0xe1) {
++              prev_scancode = scancode;
++              return 0;
++      }
++      if (prev_scancode) {
++        /*
++         * usually it will be 0xe0, but a Pause key generates
++         * e1 1d 45 e1 9d c5 when pressed, and nothing when released
++         */
++        if (prev_scancode != 0xe0) {
++            if (prev_scancode == 0xe1 && scancode == 0x1d) {
++                prev_scancode = 0x100;
++                return 0;
++            } else if (prev_scancode == 0x100 && scancode == 0x45) {
++                *keycode = E1_PAUSE;
++                prev_scancode = 0;
++            } else {
++#ifdef KBD_REPORT_UNKN
++                if (!raw_mode)
++                  printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
++#endif
++                prev_scancode = 0;
++                return 0;
++            }
++        } else {
++            prev_scancode = 0;
++
++            if (e0_keys[scancode])
++              *keycode = e0_keys[scancode];
++            else {
++#ifdef KBD_REPORT_UNKN
++                if (!raw_mode)
++                  printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
++                         scancode);
++#endif
++                return 0;
++            }
++        }
++      } else
++        *keycode = scancode;
++      return 1;
++}
++
++char input_unexpected_up(unsigned char keycode)
++{
++      return 0200;
++}
++
++/* Allow for loadable keyboard drivers */
++EXPORT_SYMBOL(input_setkeycode);
++EXPORT_SYMBOL(input_unexpected_up);
++EXPORT_SYMBOL(input_translate);
++EXPORT_SYMBOL(input_sysrq_xlate);
++EXPORT_SYMBOL(input_getkeycode);
++EXPORT_SYMBOL(k_setkeycode);
++EXPORT_SYMBOL(k_unexpected_up);
++EXPORT_SYMBOL(k_translate);
++EXPORT_SYMBOL(k_getkeycode);
++#ifdef CONFIG_MAGIC_SYSRQ
++EXPORT_SYMBOL(k_sysrq_key);
++EXPORT_SYMBOL(k_sysrq_xlate);
++#endif
+--- linux-2.4.21/drivers/char/keyboard.c~wedge
++++ linux-2.4.21/drivers/char/keyboard.c
+@@ -77,6 +77,7 @@
+ void (*kbd_ledfunc)(unsigned int led);
+ EXPORT_SYMBOL(handle_scancode);
+ EXPORT_SYMBOL(kbd_ledfunc);
++EXPORT_SYMBOL(key_maps);
+ EXPORT_SYMBOL(kbd_refresh_leds);
+ extern void ctrl_alt_del(void);
+--- linux-2.4.21/drivers/char/serial.c~ramses-serial
++++ linux-2.4.21/drivers/char/serial.c
+@@ -1,138 +1,8 @@
+-/*
+- *  linux/drivers/char/serial.c
+- *
+- *  Copyright (C) 1991, 1992  Linus Torvalds
+- *  Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 
+- *            1998, 1999  Theodore Ts'o
+- *
+- *  Extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92.  Now
+- *  much more extensible to support other serial cards based on the
+- *  16450/16550A UART's.  Added support for the AST FourPort and the
+- *  Accent Async board.  
+- *
+- *  set_serial_info fixed to set the flags, custom divisor, and uart
+- *    type fields.  Fix suggested by Michael K. Johnson 12/12/92.
+- *
+- *  11/95: TIOCMIWAIT, TIOCGICOUNT by Angelo Haritsis <ah@doc.ic.ac.uk>
+- *
+- *  03/96: Modularised by Angelo Haritsis <ah@doc.ic.ac.uk>
+- *
+- *  rs_set_termios fixed to look also for changes of the input
+- *      flags INPCK, BRKINT, PARMRK, IGNPAR and IGNBRK.
+- *                                            Bernd Anhäupl 05/17/96.
+- *
+- *  1/97:  Extended dumb serial ports are a config option now.  
+- *         Saves 4k.   Michael A. Griffith <grif@acm.org>
+- * 
+- *  8/97: Fix bug in rs_set_termios with RTS
+- *        Stanislav V. Voronyi <stas@uanet.kharkov.ua>
+- *
+- *  3/98: Change the IRQ detection, use of probe_irq_o*(),
+- *      suppress TIOCSERGWILD and TIOCSERSWILD
+- *      Etienne Lorrain <etienne.lorrain@ibm.net>
+- *
+- *  4/98: Added changes to support the ARM architecture proposed by
+- *      Russell King
+- *
+- *  5/99: Updated to include support for the XR16C850 and ST16C654
+- *        uarts.  Stuart MacDonald <stuartm@connecttech.com>
+- *
+- *  8/99: Generalized PCI support added.  Theodore Ts'o
+- * 
+- *  3/00: Rid circular buffer of redundant xmit_cnt.  Fix a
+- *      few races on freeing buffers too.
+- *      Alan Modra <alan@linuxcare.com>
+- *
+- *  5/00: Support for the RSA-DV II/S card added.
+- *      Kiyokazu SUTO <suto@ks-and-ks.ne.jp>
+- * 
+- *  6/00: Remove old-style timer, use timer_list
+- *        Andrew Morton <andrewm@uow.edu.au>
+- *
+- *  7/00: Support Timedia/Sunix/Exsys PCI cards
+- *
+- *  7/00: fix some returns on failure not using MOD_DEC_USE_COUNT.
+- *      Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+- *
+- * 10/00: add in optional software flow control for serial console.
+- *      Kanoj Sarcar <kanoj@sgi.com>  (Modified by Theodore Ts'o)
+- *
+- * 02/02: Fix for AMD Elan bug in transmit irq routine, by
+- *        Christer Weinigel <wingel@hog.ctrl-c.liu.se>,
+- *        Robert Schwebel <robert@schwebel.de>,
+- *        Juergen Beisert <jbeisert@eurodsn.de>,
+- *        Theodore Ts'o <tytso@mit.edu>
+- */
+-
+-static char *serial_version = "5.05c";
+-static char *serial_revdate = "2001-07-08";
+-
+-/*
+- * Serial driver configuration section.  Here are the various options:
+- *
+- * CONFIG_HUB6
+- *            Enables support for the venerable Bell Technologies
+- *            HUB6 card.
+- *
+- * CONFIG_SERIAL_MANY_PORTS
+- *            Enables support for ports beyond the standard, stupid
+- *            COM 1/2/3/4.
+- *
+- * CONFIG_SERIAL_MULTIPORT
+- *            Enables support for special multiport board support.
+- *
+- * CONFIG_SERIAL_SHARE_IRQ
+- *            Enables support for multiple serial ports on one IRQ
+- *
+- * CONFIG_SERIAL_DETECT_IRQ
+- *            Enable the autodetection of IRQ on standart ports
+- *
+- * SERIAL_PARANOIA_CHECK
+- *            Check the magic number for the async_structure where
+- *            ever possible.
+- *
+- * CONFIG_SERIAL_ACPI
+- *            Enable support for serial console port and serial 
+- *            debug port as defined by the SPCR and DBGP tables in 
+- *            ACPI 2.0.
+- */
++#undef DEBUG
+ #include <linux/config.h>
+ #include <linux/version.h>
+-#undef SERIAL_PARANOIA_CHECK
+-#define CONFIG_SERIAL_NOPAUSE_IO
+-#define SERIAL_DO_RESTART
+-
+-#if 0
+-/* These defines are normally controlled by the autoconf.h */
+-#define CONFIG_SERIAL_MANY_PORTS
+-#define CONFIG_SERIAL_SHARE_IRQ
+-#define CONFIG_SERIAL_DETECT_IRQ
+-#define CONFIG_SERIAL_MULTIPORT
+-#define CONFIG_HUB6
+-#endif
+-
+-#ifdef CONFIG_PCI
+-#define ENABLE_SERIAL_PCI
+-#ifndef CONFIG_SERIAL_SHARE_IRQ
+-#define CONFIG_SERIAL_SHARE_IRQ
+-#endif
+-#ifndef CONFIG_SERIAL_MANY_PORTS
+-#define CONFIG_SERIAL_MANY_PORTS
+-#endif
+-#endif
+-
+-#ifdef CONFIG_SERIAL_ACPI
+-#define ENABLE_SERIAL_ACPI
+-#endif
+-
+-#if defined(CONFIG_ISAPNP)|| (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE))
+-#ifndef ENABLE_SERIAL_PNP
+-#define ENABLE_SERIAL_PNP
+-#endif
+-#endif
+-
+ #ifdef CONFIG_ARCH_PXA
+ #define pxa_port(x) ((x) == PORT_PXA)
+ #define pxa_buggy_port(x) ({ \
+@@ -149,39 +19,16 @@
+ #undef SERIAL_DEBUG_OPEN
+ #undef SERIAL_DEBUG_FLOW
+ #undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+-#undef SERIAL_DEBUG_PCI
+-#undef SERIAL_DEBUG_AUTOCONF
+ /* Sanity checks */
+-#ifdef CONFIG_SERIAL_MULTIPORT
+-#ifndef CONFIG_SERIAL_SHARE_IRQ
+-#define CONFIG_SERIAL_SHARE_IRQ
+-#endif
+-#endif
+-
+-#ifdef CONFIG_HUB6
+-#ifndef CONFIG_SERIAL_MANY_PORTS
+-#define CONFIG_SERIAL_MANY_PORTS
+-#endif
+-#ifndef CONFIG_SERIAL_SHARE_IRQ
+-#define CONFIG_SERIAL_SHARE_IRQ
+-#endif
+-#endif
+-
+ #ifdef MODULE
+ #undef CONFIG_SERIAL_CONSOLE
+ #endif
+-#define CONFIG_SERIAL_RSA
+-
+ #define RS_STROBE_TIME (10*HZ)
+ #define RS_ISR_PASS_LIMIT 256
+-#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
+-#define SERIAL_INLINE
+-#endif
+-  
+ /*
+  * End of serial driver configuration section.
+  */
+@@ -213,53 +60,51 @@
+ #include <linux/ioport.h>
+ #include <linux/mm.h>
+ #include <linux/slab.h>
+-#if (LINUX_VERSION_CODE >= 131343)
+ #include <linux/init.h>
+-#endif
+-#if (LINUX_VERSION_CODE >= 131336)
+ #include <asm/uaccess.h>
+-#endif
+ #include <linux/delay.h>
+ #ifdef CONFIG_SERIAL_CONSOLE
+ #include <linux/console.h>
+ #endif
+-#ifdef ENABLE_SERIAL_PCI
+-#include <linux/pci.h>
+-#endif
+-#ifdef ENABLE_SERIAL_PNP
+-#include <linux/isapnp.h>
+-#endif
+ #ifdef CONFIG_MAGIC_SYSRQ
+ #include <linux/sysrq.h>
+ #endif
+-/*
+- * All of the compatibilty code so we can compile serial.c against
+- * older kernels is hidden in serial_compat.h
+- */
+-#if defined(LOCAL_HEADERS) || (LINUX_VERSION_CODE < 0x020317) /* 2.3.23 */
+-#include "serial_compat.h"
+-#endif
+-
+ #include <asm/system.h>
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/bitops.h>
+-#if defined(CONFIG_MAC_SERIAL)
+-#define SERIAL_DEV_OFFSET     ((_machine == _MACH_prep || _machine == _MACH_chrp) ? 0 : 2)
+-#else
+-#define SERIAL_DEV_OFFSET     0
+-#endif
++#define _INLINE_
+-#ifdef SERIAL_INLINE
+-#define _INLINE_ inline
++/*
++ *  The TI16754 has 4 UARTS. They are selected with nCS3 and some
++ *  address bits:
++ *
++ *                                             12    8    4
++ *  nA8,  nCS[3] for MN_UART_1, address mask 1110 1110 0000 0000 = 0xEE00
++ *  nA9,  nCS[3] for MN_UART_1, address mask 1110 1101 0000 0000 = 0xED00
++ *  nA10, nCS[3] for MN_UART_1, address mask 1110 1011 0000 0000 = 0xEB00
++ *  nA11, nCS[3] for MN_UART_1, address mask 1110 0111 0000 0000 = 0xE700
++ */
++#define RAMSES_UARTA_PHYS (PXA_CS3_PHYS+0xEE00)
++#define RAMSES_UARTB_PHYS (PXA_CS3_PHYS+0xED00)
++#define RAMSES_UARTC_PHYS (PXA_CS3_PHYS+0xEB00)
++#define RAMSES_UARTD_PHYS (PXA_CS3_PHYS+0xE700)
++static void *ramses_uarta;                    // address cookie for UART A
++static void *ramses_uartb;                    // address cookie for UART B
++static void *ramses_uartc;                    // address cookie for UART C/Scanner
++static void *ramses_uartd;                    // address cookie for UART D
++static int ramses_stay_on = 0;
++
++#ifdef DEBUG
++#define DPRINTK(fmt,args...) printk("//HS " fmt, ## args)
++static int show_io = 1;
+ #else
+-#define _INLINE_
++#define DPRINTK(fmt,args...)
++static int show_io = 0;
+ #endif
+-static char *serial_name = "Serial driver";
+-
+ static DECLARE_TASK_QUEUE(tq_serial);
+ static struct tty_driver serial_driver, callout_driver;
+@@ -282,9 +127,6 @@
+  */
+ static struct async_struct *IRQ_ports[NR_IRQS];
+-#ifdef CONFIG_SERIAL_MULTIPORT
+-static struct rs_multiport_struct rs_multiport[NR_IRQS];
+-#endif
+ static int IRQ_timeout[NR_IRQS];
+ #ifdef CONFIG_SERIAL_CONSOLE
+ static struct console sercons;
+@@ -294,8 +136,6 @@
+ static unsigned long break_pressed; /* break, really ... */
+ #endif
+-static unsigned detect_uart_irq (struct serial_state * state);
+-static void autoconfig(struct serial_state * state);
+ static void change_speed(struct async_struct *info, struct termios *old);
+ static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
+@@ -325,46 +165,74 @@
+       { 0, 0}
+ };
+-#if defined(CONFIG_SERIAL_RSA) && defined(MODULE)
+-
+-#define PORT_RSA_MAX 4
+-static int probe_rsa[PORT_RSA_MAX];
+-static int force_rsa[PORT_RSA_MAX];
+-
+-MODULE_PARM(probe_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i");
+-MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
+-MODULE_PARM(force_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i");
+-MODULE_PARM_DESC(force_rsa, "Force I/O ports for RSA");
+-#endif /* CONFIG_SERIAL_RSA  */
+-
+-struct serial_state rs_table[RS_TABLE_SIZE] = {
+-      SERIAL_PORT_DFNS        /* Defined in serial.h */
++static struct serial_state rs_table[] = {
++      {
++              type:                   PORT_PXA,
++              xmit_fifo_size:         32,
++              baud_base:              921600,
++              iomem_base:             (void *)&FFUART,
++              iomem_reg_shift:        2,
++              io_type:                SERIAL_IO_MEM32,
++              irq:                    IRQ_FFUART,
++              flags:                  ASYNC_SKIP_TEST,
++      }, {
++              type:                   PORT_PXA,
++              xmit_fifo_size:         32,
++              baud_base:              921600,
++              iomem_base:             (void *)&BTUART,
++              iomem_reg_shift:        2,
++              io_type:                SERIAL_IO_MEM32,
++              irq:                    IRQ_BTUART,
++              flags:                  ASYNC_SKIP_TEST,
++      }, {
++              type:                   PORT_PXA,
++              xmit_fifo_size:         32,
++              baud_base:              921600,
++              iomem_base:             (void *)&STUART,
++              iomem_reg_shift:        2,
++              io_type:                SERIAL_IO_MEM32,
++              irq:                    IRQ_STUART,
++              flags:                  ASYNC_SKIP_TEST,
++      }, {
++              type:                   PORT_16750,
++              xmit_fifo_size:         64,
++              baud_base:              115200*2,
++              iomem_base:             (void *)0,
++              iomem_reg_shift:        2,
++              io_type:                SERIAL_IO_MEM,
++              irq:                    IRQ_GPIO(7),
++              flags:                  ASYNC_SKIP_TEST,
++      }, {
++              type:                   PORT_16750,
++              xmit_fifo_size:         64,
++              baud_base:              115200*2,
++              iomem_base:             (void *)0,
++              iomem_reg_shift:        2,
++              io_type:                SERIAL_IO_MEM,
++              irq:                    IRQ_GPIO(24),
++              flags:                  ASYNC_SKIP_TEST,
++      }, {
++              type:                   PORT_16750,
++              xmit_fifo_size:         64,
++              baud_base:              115200*2,
++              iomem_base:             (void *)0,
++              iomem_reg_shift:        2,
++              io_type:                SERIAL_IO_MEM,
++              irq:                    IRQ_GPIO(25),
++              flags:                  ASYNC_SKIP_TEST,
++      }, {
++              type:                   PORT_16750,
++              xmit_fifo_size:         64,
++              baud_base:              115200*2,
++              iomem_base:             (void *)0,
++              iomem_reg_shift:        2,
++              io_type:                SERIAL_IO_MEM,
++              irq:                    IRQ_GPIO(26),
++              flags:                  ASYNC_SKIP_TEST,
++      }
+ };
+ #define NR_PORTS      (sizeof(rs_table)/sizeof(struct serial_state))
+-int serial_nr_ports = NR_PORTS;
+-
+-#if (defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP))
+-#define NR_PCI_BOARDS 8
+-
+-static struct pci_board_inst  serial_pci_board[NR_PCI_BOARDS];
+-
+-#ifndef IS_PCI_REGION_IOPORT
+-#define IS_PCI_REGION_IOPORT(dev, r) (pci_resource_flags((dev), (r)) & \
+-                                    IORESOURCE_IO)
+-#endif
+-#ifndef IS_PCI_REGION_IOMEM
+-#define IS_PCI_REGION_IOMEM(dev, r) (pci_resource_flags((dev), (r)) & \
+-                                    IORESOURCE_MEM)
+-#endif
+-#ifndef PCI_IRQ_RESOURCE
+-#define PCI_IRQ_RESOURCE(dev, r) ((dev)->irq_resource[r].start)
+-#endif
+-#ifndef pci_get_subvendor
+-#define pci_get_subvendor(dev) ((dev)->subsystem_vendor)
+-#define pci_get_subdevice(dev)  ((dev)->subsystem_device)
+-#endif
+-#endif        /* ENABLE_SERIAL_PCI || ENABLE_SERIAL_PNP  */
+ #ifndef PREPARE_FUNC
+ #define PREPARE_FUNC(dev)  (dev->prepare)
+@@ -403,39 +271,21 @@
+ #endif
+-static inline int serial_paranoia_check(struct async_struct *info,
+-                                      kdev_t device, const char *routine)
+-{
+-#ifdef SERIAL_PARANOIA_CHECK
+-      static const char *badmagic =
+-              "Warning: bad magic number for serial struct (%s) in %s\n";
+-      static const char *badinfo =
+-              "Warning: null async_struct for (%s) in %s\n";
+-
+-      if (!info) {
+-              printk(badinfo, kdevname(device), routine);
+-              return 1;
+-      }
+-      if (info->magic != SERIAL_MAGIC) {
+-              printk(badmagic, kdevname(device), routine);
+-              return 1;
+-      }
+-#endif
+-      return 0;
+-}
+-
+ static _INLINE_ unsigned int serial_in(struct async_struct *info, int offset)
+ {
++      unsigned int value;
+       switch (info->io_type) {
+-#ifdef CONFIG_HUB6
+-      case SERIAL_IO_HUB6:
+-              outb(info->hub6 - 1 + offset, info->port);
+-              return inb(info->port+1);
+-#endif
+       case SERIAL_IO_MEM:
+-              return readb((unsigned long) info->iomem_base +
++              value = readb((unsigned long) info->iomem_base +
+                            (offset<<info->iomem_reg_shift));
++              udelay(10);
++              if (show_io) printk("in %02x = %02x\n", offset, value);
++              return value;
+       case SERIAL_IO_MEM32:
++              value = readl((unsigned long) info->iomem_base +
++                              (offset<<info->iomem_reg_shift));
++              if (show_io) printk("in %02x = %02x\n", offset, value);
++              return value;
+               return readl((unsigned long) info->iomem_base +
+                            (offset<<info->iomem_reg_shift));
+       default:
+@@ -447,17 +297,14 @@
+                               int value)
+ {
+       switch (info->io_type) {
+-#ifdef CONFIG_HUB6
+-      case SERIAL_IO_HUB6:
+-              outb(info->hub6 - 1 + offset, info->port);
+-              outb(value, info->port+1);
+-              break;
+-#endif
+       case SERIAL_IO_MEM:
++              if (show_io) printk("out %02x, %02x\n", offset, value);
+               writeb(value, (unsigned long) info->iomem_base +
+                             (offset<<info->iomem_reg_shift));
++              udelay(10);
+               break;
+       case SERIAL_IO_MEM32:
++              if (show_io) printk("out %02x, %02x\n", offset, value);
+               writel(value, (unsigned long) info->iomem_base +
+                             (offset<<info->iomem_reg_shift));
+               break;
+@@ -509,9 +356,6 @@
+       struct async_struct *info = (struct async_struct *)tty->driver_data;
+       unsigned long flags;
+-      if (serial_paranoia_check(info, tty->device, "rs_stop"))
+-              return;
+-      
+       save_flags(flags); cli();
+       if (info->IER & UART_IER_THRI) {
+               info->IER &= ~UART_IER_THRI;
+@@ -529,9 +373,6 @@
+       struct async_struct *info = (struct async_struct *)tty->driver_data;
+       unsigned long flags;
+       
+-      if (serial_paranoia_check(info, tty->device, "rs_start"))
+-              return;
+-      
+       save_flags(flags); cli();
+       if (info->xmit.head != info->xmit.tail
+           && info->xmit.buf
+@@ -689,11 +530,7 @@
+ #endif
+               *status = serial_inp(info, UART_LSR);
+       } while ((*status & UART_LSR_DR) && (max_count-- > 0));
+-#if (LINUX_VERSION_CODE > 131394) /* 2.1.66 */
+       tty_flip_buffer_push(tty);
+-#else
+-      queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
+-#endif        
+ }
+ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
+@@ -758,11 +595,6 @@
+                       icount->dsr++;
+               if (status & UART_MSR_DDCD) {
+                       icount->dcd++;
+-#ifdef CONFIG_HARD_PPS
+-                      if ((info->flags & ASYNC_HARDPPS_CD) &&
+-                          (status & UART_MSR_DCD))
+-                              hardpps();
+-#endif
+               }
+               if (status & UART_MSR_DCTS)
+                       icount->cts++;
+@@ -810,120 +642,23 @@
+       }
+ }
+-#ifdef CONFIG_SERIAL_SHARE_IRQ
+-/*
+- * This is the serial driver's generic interrupt routine
+- */
+-static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+-{
+-      int status, iir;
+-      struct async_struct * info;
+-      int pass_counter = 0;
+-      struct async_struct *end_mark = 0;
+-#ifdef CONFIG_SERIAL_MULTIPORT        
+-      int first_multi = 0;
+-      struct rs_multiport_struct *multi;
+-#endif
+-
+-#ifdef SERIAL_DEBUG_INTR
+-      printk("rs_interrupt(%d)...", irq);
+-#endif
+-
+-      info = IRQ_ports[irq];
+-      if (!info)
+-              return;
+-
+-#ifdef CONFIG_SERIAL_MULTIPORT        
+-      multi = &rs_multiport[irq];
+-      if (multi->port_monitor)
+-              first_multi = inb(multi->port_monitor);
+-#endif
+-
+-      do {
+-              if (!info->tty ||
+-                  ((iir=serial_in(info, UART_IIR)) & UART_IIR_NO_INT)) {
+-                      if (!end_mark)
+-                              end_mark = info;
+-                      goto next;
+-              }
+-#ifdef SERIAL_DEBUG_INTR
+-              printk("IIR = %x...", serial_in(info, UART_IIR));
+-#endif
+-              end_mark = 0;
+-
+-              info->last_active = jiffies;
+-
+-              status = serial_inp(info, UART_LSR);
+-#ifdef SERIAL_DEBUG_INTR
+-              printk("status = %x...", status);
+-#endif
+-              if (status & UART_LSR_DR)
+-                      receive_chars(info, &status, regs);
+-              check_modem_status(info);
+-#ifdef CONFIG_MELAN
+-              if ((status & UART_LSR_THRE) ||
+-                      /* for buggy ELAN processors */
+-                      ((iir & UART_IIR_ID) == UART_IIR_THRI))
+-                      transmit_chars(info, 0);
+-#else
+-              if (status & UART_LSR_THRE)
+-                      transmit_chars(info, 0);
+-#endif
+-
+-      next:
+-              info = info->next_port;
+-              if (!info) {
+-                      info = IRQ_ports[irq];
+-                      if (pass_counter++ > RS_ISR_PASS_LIMIT) {
+-#if 0
+-                              printk("rs loop break\n");
+-#endif
+-                              break;  /* Prevent infinite loops */
+-                      }
+-                      continue;
+-              }
+-      } while (end_mark != info);
+-#ifdef CONFIG_SERIAL_MULTIPORT        
+-      if (multi->port_monitor)
+-              printk("rs port monitor (normal) irq %d: 0x%x, 0x%x\n",
+-                     info->state->irq, first_multi,
+-                     inb(multi->port_monitor));
+-#endif
+-#ifdef SERIAL_DEBUG_INTR
+-      printk("end.\n");
+-#endif
+-}
+-#endif /* #ifdef CONFIG_SERIAL_SHARE_IRQ */
+-
+ /*
+  * This is the serial driver's interrupt routine for a single port
+  */
+ static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs)
+ {
+-      int status, iir;
++      int status;
+       int pass_counter = 0;
+       struct async_struct * info;
+-#ifdef CONFIG_SERIAL_MULTIPORT        
+-      int first_multi = 0;
+-      struct rs_multiport_struct *multi;
+-#endif
+       
+ #ifdef SERIAL_DEBUG_INTR
+       printk("rs_interrupt_single(%d)...", irq);
+ #endif
+-
+       info = IRQ_ports[irq];
+       if (!info || !info->tty)
+               return;
+-#ifdef CONFIG_SERIAL_MULTIPORT        
+-      multi = &rs_multiport[irq];
+-      if (multi->port_monitor)
+-              first_multi = inb(multi->port_monitor);
+-#endif
+-
+-      iir = serial_in(info, UART_IIR);
+       do {
+               status = serial_inp(info, UART_LSR);
+ #ifdef SERIAL_DEBUG_INTR
+@@ -932,120 +667,23 @@
+               if (status & UART_LSR_DR)
+                       receive_chars(info, &status, regs);
+               check_modem_status(info);
+-              if ((status & UART_LSR_THRE) ||
+-                  /* For buggy ELAN processors */
+-                  ((iir & UART_IIR_ID) == UART_IIR_THRI))
++              if (status & UART_LSR_THRE)
+                       transmit_chars(info, 0);
+               if (pass_counter++ > RS_ISR_PASS_LIMIT) {
+-#if SERIAL_DEBUG_INTR
++#if 0
+                       printk("rs_single loop break.\n");
+ #endif
+                       break;
+               }
+-              iir = serial_in(info, UART_IIR);
+-#ifdef SERIAL_DEBUG_INTR
+-              printk("IIR = %x...", iir);
+-#endif
+-      } while ((iir & UART_IIR_NO_INT) == 0);
+-      info->last_active = jiffies;
+-#ifdef CONFIG_SERIAL_MULTIPORT        
+-      if (multi->port_monitor)
+-              printk("rs port monitor (single) irq %d: 0x%x, 0x%x\n",
+-                     info->state->irq, first_multi,
+-                     inb(multi->port_monitor));
+-#endif
+-#ifdef SERIAL_DEBUG_INTR
+-      printk("end.\n");
+-#endif
+-}
+-
+-#ifdef CONFIG_SERIAL_MULTIPORT        
+-/*
+- * This is the serial driver's for multiport boards
+- */
+-static void rs_interrupt_multi(int irq, void *dev_id, struct pt_regs * regs)
+-{
+-      int status;
+-      struct async_struct * info;
+-      int pass_counter = 0;
+-      int first_multi= 0;
+-      struct rs_multiport_struct *multi;
+-
+ #ifdef SERIAL_DEBUG_INTR
+-      printk("rs_interrupt_multi(%d)...", irq);
++              printk("IIR = %x...", serial_in(info, UART_IIR));
+ #endif
+-
+-      info = IRQ_ports[irq];
+-      if (!info)
+-              return;
+-      multi = &rs_multiport[irq];
+-      if (!multi->port1) {
+-              /* Should never happen */
+-              printk("rs_interrupt_multi: NULL port1!\n");
+-              return;
+-      }
+-      if (multi->port_monitor)
+-              first_multi = inb(multi->port_monitor);
+-      
+-      while (1) {
+-              if (!info->tty ||
+-                  (serial_in(info, UART_IIR) & UART_IIR_NO_INT))
+-                      goto next;
+-
++      } while (!(serial_in(info, UART_IIR) & UART_IIR_NO_INT));
+               info->last_active = jiffies;
+-
+-              status = serial_inp(info, UART_LSR);
+-#ifdef SERIAL_DEBUG_INTR
+-              printk("status = %x...", status);
+-#endif
+-              if (status & UART_LSR_DR)
+-                      receive_chars(info, &status, regs);
+-              check_modem_status(info);
+-              if (status & UART_LSR_THRE)
+-                      transmit_chars(info, 0);
+-
+-      next:
+-              info = info->next_port;
+-              if (info)
+-                      continue;
+-
+-              info = IRQ_ports[irq];
+-              /*
+-               * The user was a bonehead, and misconfigured their
+-               * multiport info.  Rather than lock up the kernel
+-               * in an infinite loop, if we loop too many times,
+-               * print a message and break out of the loop.
+-               */
+-              if (pass_counter++ > RS_ISR_PASS_LIMIT) {
+-                      printk("Misconfigured multiport serial info "
+-                             "for irq %d.  Breaking out irq loop\n", irq);
+-                      break; 
+-              }
+-              if (multi->port_monitor)
+-                      printk("rs port monitor irq %d: 0x%x, 0x%x\n",
+-                             info->state->irq, first_multi,
+-                             inb(multi->port_monitor));
+-              if ((inb(multi->port1) & multi->mask1) != multi->match1)
+-                      continue;
+-              if (!multi->port2)
+-                      break;
+-              if ((inb(multi->port2) & multi->mask2) != multi->match2)
+-                      continue;
+-              if (!multi->port3)
+-                      break;
+-              if ((inb(multi->port3) & multi->mask3) != multi->match3)
+-                      continue;
+-              if (!multi->port4)
+-                      break;
+-              if ((inb(multi->port4) & multi->mask4) != multi->match4)
+-                      continue;
+-              break;
+-      } 
+ #ifdef SERIAL_DEBUG_INTR
+       printk("end.\n");
+ #endif
+ }
+-#endif
+ /*
+  * -------------------------------------------------------------------
+@@ -1107,22 +745,6 @@
+                       if (!info)
+                               continue;
+                       save_flags(flags); cli();
+-#ifdef CONFIG_SERIAL_SHARE_IRQ
+-                      if (info->next_port) {
+-                              do {
+-                                      serial_out(info, UART_IER, 0);
+-                                      info->IER |= UART_IER_THRI;
+-                                      serial_out(info, UART_IER, info->IER);
+-                                      info = info->next_port;
+-                              } while (info);
+-#ifdef CONFIG_SERIAL_MULTIPORT
+-                              if (rs_multiport[i].port1)
+-                                      rs_interrupt_multi(i, NULL, NULL);
+-                              else
+-#endif
+-                                      rs_interrupt(i, NULL, NULL);
+-                      } else
+-#endif /* CONFIG_SERIAL_SHARE_IRQ */
+                               rs_interrupt_single(i, NULL, NULL);
+                       restore_flags(flags);
+               }
+@@ -1132,11 +754,7 @@
+       if (IRQ_ports[0]) {
+               save_flags(flags); cli();
+-#ifdef CONFIG_SERIAL_SHARE_IRQ
+-              rs_interrupt(0, NULL, NULL);
+-#else
+               rs_interrupt_single(0, NULL, NULL);
+-#endif
+               restore_flags(flags);
+               mod_timer(&serial_timer, jiffies + IRQ_timeout[0]);
+@@ -1177,50 +795,6 @@
+       IRQ_timeout[irq] = (timeout > 3) ? timeout-2 : 1;
+ }
+-#ifdef CONFIG_SERIAL_RSA
+-/* Attempts to turn on the RSA FIFO.  Returns zero on failure */
+-static int enable_rsa(struct async_struct *info)
+-{
+-      unsigned char mode;
+-      int result;
+-      unsigned long flags;
+-
+-      save_flags(flags); cli();
+-      mode = serial_inp(info, UART_RSA_MSR);
+-      result = mode & UART_RSA_MSR_FIFO;
+-
+-      if (!result) {
+-              serial_outp(info, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
+-              mode = serial_inp(info, UART_RSA_MSR);
+-              result = mode & UART_RSA_MSR_FIFO;
+-      }
+-
+-      restore_flags(flags);
+-      return result;
+-}
+-
+-/* Attempts to turn off the RSA FIFO.  Returns zero on failure */
+-static int disable_rsa(struct async_struct *info)
+-{
+-      unsigned char mode;
+-      int result;
+-      unsigned long flags;
+-
+-      save_flags(flags); cli();
+-      mode = serial_inp(info, UART_RSA_MSR);
+-      result = !(mode & UART_RSA_MSR_FIFO);
+-
+-      if (!result) {
+-              serial_outp(info, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
+-              mode = serial_inp(info, UART_RSA_MSR);
+-              result = !(mode & UART_RSA_MSR_FIFO);
+-      }
+-
+-      restore_flags(flags);
+-      return result;
+-}
+-#endif /* CONFIG_SERIAL_RSA */
+-
+ static int startup(struct async_struct * info)
+ {
+       unsigned long flags;
+@@ -1228,9 +802,6 @@
+       void (*handler)(int, void *, struct pt_regs *);
+       struct serial_state *state= info->state;
+       unsigned long page;
+-#ifdef CONFIG_SERIAL_MANY_PORTS
+-      unsigned short ICP;
+-#endif
+       page = get_zeroed_page(GFP_KERNEL);
+       if (!page)
+@@ -1258,6 +829,22 @@
+       printk("starting up ttys%d (irq %d)...", info->line, state->irq);
+ #endif
++      // Special handling to give power to devices
++      switch (info->line) {
++      case 3:
++              //printk("gsm on\n");
++              RAMSES_GSM_ON();
++              break;
++      case 4:
++              //printk("uart on\n");
++              RAMSES_UART_ON();
++              break;
++      case 5:
++              //printk("scanner on\n");
++              RAMSES_SCANNER_ON();
++              break;
++      }
++
+       if (uart_config[state->type].flags & UART_STARTECH) {
+               /* Wake up UART */
+               serial_outp(info, UART_LCR, 0xBF);
+@@ -1305,25 +892,12 @@
+               serial_outp(info, UART_LCR, 0);
+       }
+-#ifdef CONFIG_SERIAL_RSA
+-      /*
+-       * If this is an RSA port, see if we can kick it up to the
+-       * higher speed clock.
+-       */
+-      if (state->type == PORT_RSA) {
+-              if (state->baud_base != SERIAL_RSA_BAUD_BASE &&
+-                  enable_rsa(info))
+-                      state->baud_base = SERIAL_RSA_BAUD_BASE;
+-              if (state->baud_base == SERIAL_RSA_BAUD_BASE)
+-                      serial_outp(info, UART_RSA_FRR, 0);
+-      }
+-#endif
+-
+ #ifdef CONFIG_ARCH_PXA
+       if (state->type == PORT_PXA) {
+               switch ((long)state->iomem_base) {
+                       case (long)&FFUART: CKEN |= CKEN6_FFUART; break;
+                       case (long)&BTUART: CKEN |= CKEN7_BTUART; break;
++                      //HS TODO: cerf keeps the clock on
+                       case (long)&STUART: CKEN |= CKEN5_STUART; break;
+               }
+       }
+@@ -1344,6 +918,7 @@
+       /*
+        * Clear the interrupt registers.
+        */
++      (void) serial_inp(info, UART_IIR);
+       (void) serial_inp(info, UART_LSR);
+       (void) serial_inp(info, UART_RX);
+       (void) serial_inp(info, UART_IIR);
+@@ -1371,18 +946,8 @@
+       if (state->irq && (!IRQ_ports[state->irq] ||
+                         !IRQ_ports[state->irq]->next_port)) {
+               if (IRQ_ports[state->irq]) {
+-#ifdef CONFIG_SERIAL_SHARE_IRQ
+-                      free_irq(state->irq, &IRQ_ports[state->irq]);
+-#ifdef CONFIG_SERIAL_MULTIPORT                                
+-                      if (rs_multiport[state->irq].port1)
+-                              handler = rs_interrupt_multi;
+-                      else
+-#endif
+-                              handler = rs_interrupt;
+-#else
+                       retval = -EBUSY;
+                       goto errout;
+-#endif /* CONFIG_SERIAL_SHARE_IRQ */
+               } else 
+                       handler = rs_interrupt_single;
+@@ -1417,12 +982,6 @@
+       info->MCR = 0;
+       if (info->tty->termios->c_cflag & CBAUD)
+               info->MCR = UART_MCR_DTR | UART_MCR_RTS;
+-#ifdef CONFIG_SERIAL_MANY_PORTS
+-      if (info->flags & ASYNC_FOURPORT) {
+-              if (state->irq == 0)
+-                      info->MCR |= UART_MCR_OUT1;
+-      } else
+-#endif
+       {
+               if (state->irq != 0)
+                       info->MCR |= UART_MCR_OUT2;
+@@ -1437,18 +996,9 @@
+        */
+       info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
+       if (pxa_port(state->type))
+-              info->IER |= UART_IER_UUE | UART_IER_RTOIE;
++              info->IER |= UART_IER_UUE | UART_IER_RTOIE;  //HS TODO: UART_IER_THRI for PXA uarts?
+       serial_outp(info, UART_IER, info->IER); /* enable interrupts */
+       
+-#ifdef CONFIG_SERIAL_MANY_PORTS
+-      if (info->flags & ASYNC_FOURPORT) {
+-              /* Enable interrupts on the AST Fourport board */
+-              ICP = (info->port & 0xFE0) | 0x01F;
+-              outb_p(0x80, ICP);
+-              (void) inb_p(ICP);
+-      }
+-#endif
+-
+       /*
+        * And clear the interrupt registers again for luck.
+        */
+@@ -1469,7 +1019,6 @@
+       /*
+        * Set up the tty->alt_speed kludge
+        */
+-#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
+       if (info->tty) {
+               if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+                       info->tty->alt_speed = 57600;
+@@ -1480,7 +1029,6 @@
+               if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+                       info->tty->alt_speed = 460800;
+       }
+-#endif
+       
+       /*
+        * and set the speed of the serial port
+@@ -1516,6 +1064,30 @@
+              state->irq);
+ #endif
+       
++      switch (info->line) {
++      case 3:
++              if (ramses_stay_on & RAMSES_CONTROL_GSM_PWR) {
++                      //printk("gsm on\n");
++                      RAMSES_GSM_OFF();
++              }
++              //else printk("gsm stays on\n");
++              break;
++      case 4:
++              if (ramses_stay_on & RAMSES_CONTROL_UART_PWR) {
++                      //printk("uart off\n");
++                      RAMSES_UART_OFF();
++              }
++              //else printk("uart stays on\n");
++              break;
++      case 5:
++              if (ramses_stay_on & RAMSES_CONTROL_SCANNER_PWR) {
++                      //printk("scanner off\n");
++                      RAMSES_SCANNER_OFF();
++              }
++              //else printk("scanner on\n");
++              break;
++      }
++
+       save_flags(flags); cli(); /* Disable interrupts */
+       /*
+@@ -1561,13 +1133,6 @@
+       info->IER = 0;
+       serial_outp(info, UART_IER, 0x00);      /* disable all intrs */
+-#ifdef CONFIG_SERIAL_MANY_PORTS
+-      if (info->flags & ASYNC_FOURPORT) {
+-              /* reset interrupts on the AST Fourport board */
+-              (void) inb((info->port & 0xFE0) | 0x01F);
+-              info->MCR |= UART_MCR_OUT1;
+-      } else
+-#endif
+               info->MCR &= ~UART_MCR_OUT2;
+               if (pxa_buggy_port(state->type))
+                       info->MCR ^= UART_MCR_OUT2;
+@@ -1586,16 +1151,6 @@
+                                    UART_FCR_CLEAR_XMIT));
+       serial_outp(info, UART_FCR, 0);
+-#ifdef CONFIG_SERIAL_RSA
+-      /*
+-       * Reset the RSA board back to 115kbps compat mode.
+-       */
+-      if ((state->type == PORT_RSA) &&
+-          (state->baud_base == SERIAL_RSA_BAUD_BASE &&
+-           disable_rsa(info)))
+-              state->baud_base = SERIAL_RSA_BAUD_BASE_LO;
+-#endif
+-      
+ #ifdef CONFIG_ARCH_PXA
+       if (state->type == PORT_PXA
+ #ifdef CONFIG_SERIAL_CONSOLE
+@@ -1634,37 +1189,6 @@
+       restore_flags(flags);
+ }
+-#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
+-static int baud_table[] = {
+-      0, 50, 75, 110, 134, 150, 200, 300,
+-      600, 1200, 1800, 2400, 4800, 9600, 19200,
+-      38400, 57600, 115200, 230400, 460800, 0 };
+-
+-static int tty_get_baud_rate(struct tty_struct *tty)
+-{
+-      struct async_struct * info = (struct async_struct *)tty->driver_data;
+-      unsigned int cflag, i;
+-
+-      cflag = tty->termios->c_cflag;
+-
+-      i = cflag & CBAUD;
+-      if (i & CBAUDEX) {
+-              i &= ~CBAUDEX;
+-              if (i < 1 || i > 2) 
+-                      tty->termios->c_cflag &= ~CBAUDEX;
+-              else
+-                      i += 15;
+-      }
+-      if (i == 15) {
+-              if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+-                      i += 1;
+-              if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+-                      i += 2;
+-      }
+-      return baud_table[i];
+-}
+-#endif
+-
+ /*
+  * This routine is called to set the UART divisor registers to match
+  * the specified baud rate for a serial port.
+@@ -1711,12 +1235,6 @@
+       baud = tty_get_baud_rate(info->tty);
+       if (!baud)
+               baud = 9600;    /* B0 transition handled in rs_set_termios */
+-#ifdef CONFIG_SERIAL_RSA
+-      if ((info->state->type == PORT_RSA) &&
+-          (info->state->baud_base != SERIAL_RSA_BAUD_BASE) &&
+-          enable_rsa(info))
+-              info->state->baud_base = SERIAL_RSA_BAUD_BASE;
+-#endif
+       baud_base = info->state->baud_base;
+       if (info->state->type == PORT_16C950) {
+               if (baud <= baud_base)
+@@ -1778,10 +1296,6 @@
+       if (uart_config[info->state->type].flags & UART_USE_FIFO) {
+               if ((info->state->baud_base / quot) < 2400)
+                       fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
+-#ifdef CONFIG_SERIAL_RSA
+-              else if (info->state->type == PORT_RSA)
+-                      fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14;
+-#endif
+               else
+                       fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
+       }
+@@ -1864,9 +1378,6 @@
+       struct async_struct *info = (struct async_struct *)tty->driver_data;
+       unsigned long flags;
+-      if (serial_paranoia_check(info, tty->device, "rs_put_char"))
+-              return;
+-
+       if (!tty || !info->xmit.buf)
+               return;
+@@ -1888,9 +1399,6 @@
+       struct async_struct *info = (struct async_struct *)tty->driver_data;
+       unsigned long flags;
+                               
+-      if (serial_paranoia_check(info, tty->device, "rs_flush_chars"))
+-              return;
+-
+       if (info->xmit.head == info->xmit.tail
+           || tty->stopped
+           || tty->hw_stopped
+@@ -1900,8 +1408,6 @@
+       save_flags(flags); cli();
+       info->IER |= UART_IER_THRI;
+       serial_out(info, UART_IER, info->IER);
+-      if (pxa_buggy_port(info->state->type))
+-              rs_interrupt_single(info->state->irq, NULL, NULL);
+       restore_flags(flags);
+ }
+@@ -1912,9 +1418,6 @@
+       struct async_struct *info = (struct async_struct *)tty->driver_data;
+       unsigned long flags;
+                               
+-      if (serial_paranoia_check(info, tty->device, "rs_write"))
+-              return 0;
+-
+       if (!tty || !info->xmit.buf || !tmp_buf)
+               return 0;
+@@ -1978,11 +1481,6 @@
+           && !(info->IER & UART_IER_THRI)) {
+               info->IER |= UART_IER_THRI;
+               serial_out(info, UART_IER, info->IER);
+-              if (pxa_buggy_port(info->state->type)) {
+-                      save_flags(flags); cli();
+-                      rs_interrupt_single(info->state->irq, NULL, NULL);
+-                      restore_flags(flags);
+-              }
+       }
+       return ret;
+ }
+@@ -1991,8 +1489,6 @@
+ {
+       struct async_struct *info = (struct async_struct *)tty->driver_data;
+-      if (serial_paranoia_check(info, tty->device, "rs_write_room"))
+-              return 0;
+       return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
+ }
+@@ -2000,8 +1496,6 @@
+ {
+       struct async_struct *info = (struct async_struct *)tty->driver_data;
+                               
+-      if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))
+-              return 0;
+       return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
+ }
+@@ -2010,8 +1504,6 @@
+       struct async_struct *info = (struct async_struct *)tty->driver_data;
+       unsigned long flags;
+       
+-      if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
+-              return;
+       save_flags(flags); cli();
+       info->xmit.head = info->xmit.tail = 0;
+       restore_flags(flags);
+@@ -2032,16 +1524,11 @@
+ {
+       struct async_struct *info = (struct async_struct *)tty->driver_data;
+-      if (serial_paranoia_check(info, tty->device, "rs_send_char"))
+-              return;
+-
+       info->x_char = ch;
+       if (ch) {
+               /* Make sure transmit interrupts are on */
+               info->IER |= UART_IER_THRI;
+               serial_out(info, UART_IER, info->IER);
+-              if (pxa_buggy_port(info->state->type))
+-                      rs_interrupt_single(info->state->irq, NULL, NULL);
+       }
+ }
+@@ -2064,9 +1551,6 @@
+              tty->ldisc.chars_in_buffer(tty));
+ #endif
+-      if (serial_paranoia_check(info, tty->device, "rs_throttle"))
+-              return;
+-      
+       if (I_IXOFF(tty))
+               rs_send_xchar(tty, STOP_CHAR(tty));
+@@ -2089,9 +1573,6 @@
+              tty->ldisc.chars_in_buffer(tty));
+ #endif
+-      if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))
+-              return;
+-      
+       if (I_IXOFF(tty)) {
+               if (info->x_char)
+                       info->x_char = 0;
+@@ -2134,7 +1615,6 @@
+       tmp.close_delay = state->close_delay;
+       tmp.closing_wait = state->closing_wait;
+       tmp.custom_divisor = state->custom_divisor;
+-      tmp.hub6 = state->hub6;
+       tmp.io_type = state->io_type;
+       if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
+               return -EFAULT;
+@@ -2160,8 +1640,7 @@
+               new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
+       change_irq = new_serial.irq != state->irq;
+-      change_port = (new_port != ((int) state->port)) ||
+-              (new_serial.hub6 != state->hub6);
++      change_port = (new_port != ((int) state->port));
+   
+       if (!capable(CAP_SYS_ADMIN)) {
+               if (change_irq || change_port ||
+@@ -2198,7 +1677,6 @@
+       if (new_serial.type) {
+               for (i = 0 ; i < NR_PORTS; i++)
+                       if ((state != &rs_table[i]) &&
+-                          (rs_table[i].io_type == SERIAL_IO_PORT) &&
+                           (rs_table[i].port == new_port) &&
+                           rs_table[i].type)
+                               return -EADDRINUSE;
+@@ -2220,18 +1698,11 @@
+       state->custom_divisor = new_serial.custom_divisor;
+       state->close_delay = new_serial.close_delay * HZ/100;
+       state->closing_wait = new_serial.closing_wait * HZ/100;
+-#if (LINUX_VERSION_CODE > 0x20100)
+       info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+-#endif
+       info->xmit_fifo_size = state->xmit_fifo_size =
+               new_serial.xmit_fifo_size;
+       if ((state->type != PORT_UNKNOWN) && state->port) {
+-#ifdef CONFIG_SERIAL_RSA
+-              if (old_state.type == PORT_RSA)
+-                      release_region(state->port + UART_RSA_BASE, 16);
+-              else
+-#endif
+               release_region(state->port,8);
+       }
+       state->type = new_serial.type;
+@@ -2243,31 +1714,19 @@
+               shutdown(info);
+               state->irq = new_serial.irq;
+               info->port = state->port = new_port;
+-              info->hub6 = state->hub6 = new_serial.hub6;
+-              if (info->hub6)
+-                      info->io_type = state->io_type = SERIAL_IO_HUB6;
+-              else if (info->io_type == SERIAL_IO_HUB6)
+-                      info->io_type = state->io_type = SERIAL_IO_PORT;
+       }
+       if ((state->type != PORT_UNKNOWN) && state->port) {
+-#ifdef CONFIG_SERIAL_RSA
+-              if (state->type == PORT_RSA)
+-                      request_region(state->port + UART_RSA_BASE,
+-                                     16, "serial_rsa(set)");
+-              else
+-#endif
+                       request_region(state->port,8,"serial(set)");
+       }
+       
+ check_and_exit:
+-      if ((!state->port && !state->iomem_base) || !state->type)
++      if (!state->port || !state->type)
+               return 0;
+       if (info->flags & ASYNC_INITIALIZED) {
+               if (((old_state.flags & ASYNC_SPD_MASK) !=
+                    (state->flags & ASYNC_SPD_MASK)) ||
+                   (old_state.custom_divisor != state->custom_divisor)) {
+-#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
+                       if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+                               info->tty->alt_speed = 57600;
+                       if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+@@ -2276,7 +1735,6 @@
+                               info->tty->alt_speed = 230400;
+                       if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+                               info->tty->alt_speed = 460800;
+-#endif
+                       change_speed(info, 0);
+               }
+       } else
+@@ -2414,60 +1872,14 @@
+       return 0;
+ }
+-static int do_autoconfig(struct async_struct * info)
+-{
+-      int irq, retval;
+-      
+-      if (!capable(CAP_SYS_ADMIN))
+-              return -EPERM;
+-      
+-      if (info->state->count > 1)
+-              return -EBUSY;
+-      
+-      shutdown(info);
+-
+-      autoconfig(info->state);
+-      if ((info->state->flags & ASYNC_AUTO_IRQ) &&
+-          (info->state->port != 0  || info->state->iomem_base != 0) &&
+-          (info->state->type != PORT_UNKNOWN)) {
+-              irq = detect_uart_irq(info->state);
+-              if (irq > 0)
+-                      info->state->irq = irq;
+-      }
+-
+-      retval = startup(info);
+-      if (retval)
+-              return retval;
+-      return 0;
+-}
+-
+ /*
+  * rs_break() --- routine which turns the break handling on or off
+  */
+-#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
+-static void send_break(       struct async_struct * info, int duration)
+-{
+-      if (!CONFIGURED_SERIAL_PORT(info))
+-              return;
+-      current->state = TASK_INTERRUPTIBLE;
+-      current->timeout = jiffies + duration;
+-      cli();
+-      info->LCR |= UART_LCR_SBC;
+-      serial_out(info, UART_LCR, info->LCR);
+-      schedule();
+-      info->LCR &= ~UART_LCR_SBC;
+-      serial_out(info, UART_LCR, info->LCR);
+-      sti();
+-}
+-#else
+ static void rs_break(struct tty_struct *tty, int break_state)
+ {
+       struct async_struct * info = (struct async_struct *)tty->driver_data;
+       unsigned long flags;
+       
+-      if (serial_paranoia_check(info, tty->device, "rs_break"))
+-              return;
+-
+       if (!CONFIGURED_SERIAL_PORT(info))
+               return;
+       save_flags(flags); cli();
+@@ -2478,121 +1890,6 @@
+       serial_out(info, UART_LCR, info->LCR);
+       restore_flags(flags);
+ }
+-#endif
+-
+-#ifdef CONFIG_SERIAL_MULTIPORT
+-static int get_multiport_struct(struct async_struct * info,
+-                              struct serial_multiport_struct *retinfo)
+-{
+-      struct serial_multiport_struct ret;
+-      struct rs_multiport_struct *multi;
+-      
+-      multi = &rs_multiport[info->state->irq];
+-
+-      ret.port_monitor = multi->port_monitor;
+-      
+-      ret.port1 = multi->port1;
+-      ret.mask1 = multi->mask1;
+-      ret.match1 = multi->match1;
+-      
+-      ret.port2 = multi->port2;
+-      ret.mask2 = multi->mask2;
+-      ret.match2 = multi->match2;
+-      
+-      ret.port3 = multi->port3;
+-      ret.mask3 = multi->mask3;
+-      ret.match3 = multi->match3;
+-      
+-      ret.port4 = multi->port4;
+-      ret.mask4 = multi->mask4;
+-      ret.match4 = multi->match4;
+-
+-      ret.irq = info->state->irq;
+-
+-      if (copy_to_user(retinfo,&ret,sizeof(*retinfo)))
+-              return -EFAULT;
+-      return 0;
+-}
+-
+-static int set_multiport_struct(struct async_struct * info,
+-                              struct serial_multiport_struct *in_multi)
+-{
+-      struct serial_multiport_struct new_multi;
+-      struct rs_multiport_struct *multi;
+-      struct serial_state *state;
+-      int     was_multi, now_multi;
+-      int     retval;
+-      void (*handler)(int, void *, struct pt_regs *);
+-
+-      if (!capable(CAP_SYS_ADMIN))
+-              return -EPERM;
+-      state = info->state;
+-      
+-      if (copy_from_user(&new_multi, in_multi,
+-                         sizeof(struct serial_multiport_struct)))
+-              return -EFAULT;
+-      
+-      if (new_multi.irq != state->irq || state->irq == 0 ||
+-          !IRQ_ports[state->irq])
+-              return -EINVAL;
+-
+-      multi = &rs_multiport[state->irq];
+-      was_multi = (multi->port1 != 0);
+-      
+-      multi->port_monitor = new_multi.port_monitor;
+-      
+-      if (multi->port1)
+-              release_region(multi->port1,1);
+-      multi->port1 = new_multi.port1;
+-      multi->mask1 = new_multi.mask1;
+-      multi->match1 = new_multi.match1;
+-      if (multi->port1)
+-              request_region(multi->port1,1,"serial(multiport1)");
+-
+-      if (multi->port2)
+-              release_region(multi->port2,1);
+-      multi->port2 = new_multi.port2;
+-      multi->mask2 = new_multi.mask2;
+-      multi->match2 = new_multi.match2;
+-      if (multi->port2)
+-              request_region(multi->port2,1,"serial(multiport2)");
+-
+-      if (multi->port3)
+-              release_region(multi->port3,1);
+-      multi->port3 = new_multi.port3;
+-      multi->mask3 = new_multi.mask3;
+-      multi->match3 = new_multi.match3;
+-      if (multi->port3)
+-              request_region(multi->port3,1,"serial(multiport3)");
+-
+-      if (multi->port4)
+-              release_region(multi->port4,1);
+-      multi->port4 = new_multi.port4;
+-      multi->mask4 = new_multi.mask4;
+-      multi->match4 = new_multi.match4;
+-      if (multi->port4)
+-              request_region(multi->port4,1,"serial(multiport4)");
+-
+-      now_multi = (multi->port1 != 0);
+-      
+-      if (IRQ_ports[state->irq]->next_port &&
+-          (was_multi != now_multi)) {
+-              free_irq(state->irq, &IRQ_ports[state->irq]);
+-              if (now_multi)
+-                      handler = rs_interrupt_multi;
+-              else
+-                      handler = rs_interrupt;
+-
+-              retval = request_irq(state->irq, handler, SA_SHIRQ,
+-                                   "serial", &IRQ_ports[state->irq]);
+-              if (retval) {
+-                      printk("Couldn't reallocate serial interrupt "
+-                             "driver!!\n");
+-              }
+-      }
+-      return 0;
+-}
+-#endif
+ static int rs_ioctl(struct tty_struct *tty, struct file * file,
+                   unsigned int cmd, unsigned long arg)
+@@ -2601,12 +1898,6 @@
+       struct async_icount cprev, cnow;        /* kernel counter temps */
+       struct serial_icounter_struct icount;
+       unsigned long flags;
+-#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
+-      int retval, tmp;
+-#endif
+-      
+-      if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
+-              return -ENODEV;
+       if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+           (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
+@@ -2616,45 +1907,6 @@
+       }
+       
+       switch (cmd) {
+-#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
+-              case TCSBRK:    /* SVID version: non-zero arg --> no break */
+-                      retval = tty_check_change(tty);
+-                      if (retval)
+-                              return retval;
+-                      tty_wait_until_sent(tty, 0);
+-                      if (signal_pending(current))
+-                              return -EINTR;
+-                      if (!arg) {
+-                              send_break(info, HZ/4); /* 1/4 second */
+-                              if (signal_pending(current))
+-                                      return -EINTR;
+-                      }
+-                      return 0;
+-              case TCSBRKP:   /* support for POSIX tcsendbreak() */
+-                      retval = tty_check_change(tty);
+-                      if (retval)
+-                              return retval;
+-                      tty_wait_until_sent(tty, 0);
+-                      if (signal_pending(current))
+-                              return -EINTR;
+-                      send_break(info, arg ? arg*(HZ/10) : HZ/4);
+-                      if (signal_pending(current))
+-                              return -EINTR;
+-                      return 0;
+-              case TIOCGSOFTCAR:
+-                      tmp = C_CLOCAL(tty) ? 1 : 0;
+-                      if (copy_to_user((void *)arg, &tmp, sizeof(int)))
+-                              return -EFAULT;
+-                      return 0;
+-              case TIOCSSOFTCAR:
+-                      if (copy_from_user(&tmp, (void *)arg, sizeof(int)))
+-                              return -EFAULT;
+-
+-                      tty->termios->c_cflag =
+-                              ((tty->termios->c_cflag & ~CLOCAL) |
+-                               (tmp ? CLOCAL : 0));
+-                      return 0;
+-#endif
+               case TIOCMGET:
+                       return get_modem_info(info, (unsigned int *) arg);
+               case TIOCMBIS:
+@@ -2667,9 +1919,6 @@
+               case TIOCSSERIAL:
+                       return set_serial_info(info,
+                                              (struct serial_struct *) arg);
+-              case TIOCSERCONFIG:
+-                      return do_autoconfig(info);
+-
+               case TIOCSERGETLSR: /* Get line status register */
+                       return get_lsr_info(info, (unsigned int *) arg);
+@@ -2679,15 +1928,6 @@
+                               return -EFAULT;
+                       return 0;
+                               
+-#ifdef CONFIG_SERIAL_MULTIPORT
+-              case TIOCSERGETMULTI:
+-                      return get_multiport_struct(info,
+-                                     (struct serial_multiport_struct *) arg);
+-              case TIOCSERSETMULTI:
+-                      return set_multiport_struct(info,
+-                                     (struct serial_multiport_struct *) arg);
+-#endif
+-                      
+               /*
+                * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+                * - mask passed in arg for lines of interest
+@@ -2754,6 +1994,39 @@
+                       printk ("TIOCSER?WILD ioctl obsolete, ignored.\n");
+                       return 0;
++              case TIOCSERSETMULTI:
++                      switch (arg) {
++
++                      // switch devices on
++                      case  2: RAMSES_LCD_BLIGHT_ON(); break;
++                      case  3: RAMSES_GSM_ON(); break;
++                      case  4: RAMSES_UART_ON(); break;
++                      case  5: RAMSES_SCANNER_ON(); break;
++                      case  7: RAMSES_SCANNER_WAKE_ON(); break;
++                      case  8: RAMSES_SCANNER_TRIG_ON(); break;
++                      case  9: RAMSES_GSM_RESET_ON(); break;
++
++                      // switch devices off
++                      case 12: RAMSES_LCD_BLIGHT_OFF(); break;
++                      case 13: RAMSES_GSM_OFF(); break;
++                      case 14: RAMSES_UART_OFF(); break;
++                      case 15: RAMSES_SCANNER_OFF(); break;
++                      case 17: RAMSES_SCANNER_WAKE_OFF(); break;
++                      case 18: RAMSES_SCANNER_TRIG_OFF(); break;
++                      case 19: RAMSES_GSM_RESET_OFF(); break;
++
++                      // disable automatic poweroff on file-handle close
++                      case 23: ramses_stay_on |= RAMSES_CONTROL_GSM_PWR; break;
++                      case 24: ramses_stay_on |= RAMSES_CONTROL_UART_PWR; break;
++                      case 25: ramses_stay_on |= RAMSES_CONTROL_SCANNER_PWR; break;
++
++                      // enable automatic poweroff on file-handle close
++                      case 33: ramses_stay_on &= ~RAMSES_CONTROL_GSM_PWR; break;
++                      case 34: ramses_stay_on &= ~RAMSES_CONTROL_UART_PWR; break;
++                      case 35: ramses_stay_on &= ~RAMSES_CONTROL_SCANNER_PWR; break;
++                      }
++                      return 0;
++
+               default:
+                       return -ENOIOCTLCMD;
+               }
+@@ -2801,18 +2074,6 @@
+               tty->hw_stopped = 0;
+               rs_start(tty);
+       }
+-
+-#if 0
+-      /*
+-       * No need to wake up processes in open wait, since they
+-       * sample the CLOCAL flag once, and don't recheck it.
+-       * XXX  It's not clear whether the current behavior is correct
+-       * or not.  Hence, this may change.....
+-       */
+-      if (!(old_termios->c_cflag & CLOCAL) &&
+-          (tty->termios->c_cflag & CLOCAL))
+-              wake_up_interruptible(&info->open_wait);
+-#endif
+ }
+ /*
+@@ -2831,9 +2092,6 @@
+       struct serial_state *state;
+       unsigned long flags;
+-      if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
+-              return;
+-
+       state = info->state;
+       
+       save_flags(flags); cli();
+@@ -2933,10 +2191,7 @@
+ {
+       struct async_struct * info = (struct async_struct *)tty->driver_data;
+       unsigned long orig_jiffies, char_time;
+-      int lsr;
+-      
+-      if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent"))
+-              return;
++      int lsr, old_show_io;
+       if (info->state->type == PORT_UNKNOWN)
+               return;
+@@ -2974,9 +2229,11 @@
+       printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
+       printk("jiff=%lu...", jiffies);
+ #endif
++      old_show_io = show_io;
++      show_io = 0;
+       while (!((lsr = serial_inp(info, UART_LSR)) & UART_LSR_TEMT)) {
+ #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+-              printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
++              printk("lsr = %02x (jiff=%lu)...", lsr, jiffies);
+ #endif
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout(char_time);
+@@ -2986,8 +2243,9 @@
+                       break;
+       }
+ #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+-      printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
++      printk("lsr = %02x (jiff=%lu)...done\n", lsr, jiffies);
+ #endif
++      show_io = old_show_io;
+ }
+ /*
+@@ -2998,9 +2256,6 @@
+       struct async_struct * info = (struct async_struct *)tty->driver_data;
+       struct serial_state *state = info->state;
+       
+-      if (serial_paranoia_check(info, tty->device, "rs_hangup"))
+-              return;
+-
+       state = info->state;
+       
+       rs_flush_buffer(tty);
+@@ -3036,12 +2291,8 @@
+           (info->flags & ASYNC_CLOSING)) {
+               if (info->flags & ASYNC_CLOSING)
+                       interruptible_sleep_on(&info->close_wait);
+-#ifdef SERIAL_DO_RESTART
+               return ((info->flags & ASYNC_HUP_NOTIFY) ?
+                       -EAGAIN : -ERESTARTSYS);
+-#else
+-              return -EAGAIN;
+-#endif
+       }
+       /*
+@@ -3114,14 +2365,10 @@
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (tty_hung_up_p(filp) ||
+                   !(info->flags & ASYNC_INITIALIZED)) {
+-#ifdef SERIAL_DO_RESTART
+                       if (info->flags & ASYNC_HUP_NOTIFY)
+                               retval = -EAGAIN;
+                       else
+                               retval = -ERESTARTSYS;  
+-#else
+-                      retval = -EAGAIN;
+-#endif
+                       break;
+               }
+               if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+@@ -3223,16 +2470,12 @@
+       }
+       tty->driver_data = info;
+       info->tty = tty;
+-      if (serial_paranoia_check(info, tty->device, "rs_open"))
+-              return -ENODEV;
+ #ifdef SERIAL_DEBUG_OPEN
+       printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
+              info->state->count);
+ #endif
+-#if (LINUX_VERSION_CODE > 0x20100)
+       info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+-#endif
+       /*
+        *      This relies on lock_kernel() stuff so wants tidying for 2.5
+@@ -3254,12 +2497,8 @@
+           (info->flags & ASYNC_CLOSING)) {
+               if (info->flags & ASYNC_CLOSING)
+                       interruptible_sleep_on(&info->close_wait);
+-#ifdef SERIAL_DO_RESTART
+               return ((info->flags & ASYNC_HUP_NOTIFY) ?
+                       -EAGAIN : -ERESTARTSYS);
+-#else
+-              return -EAGAIN;
+-#endif
+       }
+       /*
+@@ -3313,17 +2552,14 @@
+       int     ret;
+       unsigned long flags;
+-      /*
+-       * Return zero characters for ports not claimed by driver.
+-       */
+-      if (state->type == PORT_UNKNOWN) {
+-              return 0;       /* ignore unused ports */
+-      }
+-
+       ret = sprintf(buf, "%d: uart:%s port:%lX irq:%d",
+                     state->line, uart_config[state->type].name, 
+-                    (state->port ? state->port : (long)state->iomem_base),
+-                    state->irq);
++                    state->port, state->irq);
++
++      if (!state->port || (state->type == PORT_UNKNOWN)) {
++              ret += sprintf(buf+ret, "\n");
++              return ret;
++      }
+       /*
+        * Figure out the current RS-232 lines
+@@ -3334,7 +2570,6 @@
+               info->magic = SERIAL_MAGIC;
+               info->port = state->port;
+               info->flags = state->flags;
+-              info->hub6 = state->hub6;
+               info->io_type = state->io_type;
+               info->iomem_base = state->iomem_base;
+               info->iomem_reg_shift = state->iomem_reg_shift;
+@@ -3389,13 +2624,13 @@
+ }
+ static int rs_read_proc(char *page, char **start, off_t off, int count,
+-                      int *eof, void *data)
++               int *eof, void *data)
+ {
+       int i, len = 0, l;
+       off_t   begin = 0;
+-      len += sprintf(page, "serinfo:1.0 driver:%s%s revision:%s\n",
+-                     serial_version, LOCAL_VERSTRING, serial_revdate);
++      len += sprintf(page, "serial: %s\n",
++                     LOCAL_VERSTRING);
+       for (i = 0; i < NR_PORTS && len < 4000; i++) {
+               l = line_info(page + len, &rs_table[i]);
+               len += l;
+@@ -3423,2038 +2658,63 @@
+  */
+ /*
+- * This routine prints out the appropriate serial driver version
+- * number, and identifies which options were configured into this
+- * driver.
+- */
+-static char serial_options[] __initdata =
+-#ifdef CONFIG_HUB6
+-       " HUB-6"
+-#define SERIAL_OPT
+-#endif
+-#ifdef CONFIG_SERIAL_MANY_PORTS
+-       " MANY_PORTS"
+-#define SERIAL_OPT
+-#endif
+-#ifdef CONFIG_SERIAL_MULTIPORT
+-       " MULTIPORT"
+-#define SERIAL_OPT
+-#endif
+-#ifdef CONFIG_SERIAL_SHARE_IRQ
+-       " SHARE_IRQ"
+-#define SERIAL_OPT
+-#endif
+-#ifdef CONFIG_SERIAL_DETECT_IRQ
+-       " DETECT_IRQ"
+-#define SERIAL_OPT
+-#endif
+-#ifdef ENABLE_SERIAL_PCI
+-       " SERIAL_PCI"
+-#define SERIAL_OPT
+-#endif
+-#ifdef ENABLE_SERIAL_PNP
+-       " ISAPNP"
+-#define SERIAL_OPT
+-#endif
+-#ifdef ENABLE_SERIAL_ACPI
+-       " SERIAL_ACPI"
+-#define SERIAL_OPT
+-#endif
+-#ifdef SERIAL_OPT
+-       " enabled\n";
+-#else
+-       " no serial options enabled\n";
+-#endif
+-#undef SERIAL_OPT
+-
+-static _INLINE_ void show_serial_version(void)
+-{
+-      printk(KERN_INFO "%s version %s%s (%s) with%s", serial_name,
+-             serial_version, LOCAL_VERSTRING, serial_revdate,
+-             serial_options);
+-}
+-
+-/*
+- * This routine detect the IRQ of a serial port by clearing OUT2 when
+- * no UART interrupt are requested (IER = 0) (*GPL*). This seems to work at
+- * each time, as long as no other device permanently request the IRQ.
+- * If no IRQ is detected, or multiple IRQ appear, this function returns 0.
+- * The variable "state" and the field "state->port" should not be null.
+- */
+-static unsigned detect_uart_irq (struct serial_state * state)
+-{
+-      int irq;
+-      unsigned long irqs;
+-      unsigned char save_mcr, save_ier;
+-      struct async_struct scr_info; /* serial_{in,out} because HUB6 */
+-
+-#ifdef CONFIG_SERIAL_MANY_PORTS
+-      unsigned char save_ICP=0; /* no warning */
+-      unsigned short ICP=0;
+-
+-      if (state->flags & ASYNC_FOURPORT)  {
+-              ICP = (state->port & 0xFE0) | 0x01F;
+-              save_ICP = inb_p(ICP);
+-              outb_p(0x80, ICP);
+-              (void) inb_p(ICP);
+-      }
+-#endif
+-      scr_info.magic = SERIAL_MAGIC;
+-      scr_info.state = state;
+-      scr_info.port = state->port;
+-      scr_info.flags = state->flags;
+-#ifdef CONFIG_HUB6
+-      scr_info.hub6 = state->hub6;
+-#endif
+-      scr_info.io_type = state->io_type;
+-      scr_info.iomem_base = state->iomem_base;
+-      scr_info.iomem_reg_shift = state->iomem_reg_shift;
+-
+-      /* forget possible initially masked and pending IRQ */
+-      probe_irq_off(probe_irq_on());
+-      save_mcr = serial_inp(&scr_info, UART_MCR);
+-      save_ier = serial_inp(&scr_info, UART_IER);
+-      serial_outp(&scr_info, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
+-      
+-      irqs = probe_irq_on();
+-      serial_outp(&scr_info, UART_MCR, 0);
+-      udelay (10);
+-      if (state->flags & ASYNC_FOURPORT)  {
+-              serial_outp(&scr_info, UART_MCR,
+-                          UART_MCR_DTR | UART_MCR_RTS);
+-      } else {
+-              serial_outp(&scr_info, UART_MCR,
+-                          UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
+-      }
+-      serial_outp(&scr_info, UART_IER, 0x0f); /* enable all intrs */
+-      (void)serial_inp(&scr_info, UART_LSR);
+-      (void)serial_inp(&scr_info, UART_RX);
+-      (void)serial_inp(&scr_info, UART_IIR);
+-      (void)serial_inp(&scr_info, UART_MSR);
+-      serial_outp(&scr_info, UART_TX, 0xFF);
+-      udelay (20);
+-      irq = probe_irq_off(irqs);
+-
+-      serial_outp(&scr_info, UART_MCR, save_mcr);
+-      serial_outp(&scr_info, UART_IER, save_ier);
+-#ifdef CONFIG_SERIAL_MANY_PORTS
+-      if (state->flags & ASYNC_FOURPORT)
+-              outb_p(save_ICP, ICP);
+-#endif
+-      return (irq > 0)? irq : 0;
+-}
+-
+-/*
+- * This is a quickie test to see how big the FIFO is.
+- * It doesn't work at all the time, more's the pity.
+- */
+-static int size_fifo(struct async_struct *info)
+-{
+-      unsigned char old_fcr, old_mcr, old_dll, old_dlm;
+-      int count;
+-
+-      old_fcr = serial_inp(info, UART_FCR);
+-      old_mcr = serial_inp(info, UART_MCR);
+-      serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO |
+-                  UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+-      serial_outp(info, UART_MCR, UART_MCR_LOOP);
+-      serial_outp(info, UART_LCR, UART_LCR_DLAB);
+-      old_dll = serial_inp(info, UART_DLL);
+-      old_dlm = serial_inp(info, UART_DLM);
+-      serial_outp(info, UART_DLL, 0x01);
+-      serial_outp(info, UART_DLM, 0x00);
+-      serial_outp(info, UART_LCR, 0x03);
+-      for (count = 0; count < 256; count++)
+-              serial_outp(info, UART_TX, count);
+-      mdelay(20);
+-      for (count = 0; (serial_inp(info, UART_LSR) & UART_LSR_DR) &&
+-           (count < 256); count++)
+-              serial_inp(info, UART_RX);
+-      serial_outp(info, UART_FCR, old_fcr);
+-      serial_outp(info, UART_MCR, old_mcr);
+-      serial_outp(info, UART_LCR, UART_LCR_DLAB);
+-      serial_outp(info, UART_DLL, old_dll);
+-      serial_outp(info, UART_DLM, old_dlm);
+-
+-      return count;
+-}
+-
+-/*
+- * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
+- * When this function is called we know it is at least a StarTech
+- * 16650 V2, but it might be one of several StarTech UARTs, or one of
+- * its clones.  (We treat the broken original StarTech 16650 V1 as a
+- * 16550, and why not?  Startech doesn't seem to even acknowledge its
+- * existence.)
+- * 
+- * What evil have men's minds wrought...
+- */
+-static void autoconfig_startech_uarts(struct async_struct *info,
+-                                    struct serial_state *state,
+-                                    unsigned long flags)
+-{
+-      unsigned char scratch, scratch2, scratch3, scratch4;
+-
+-      /*
+-       * First we check to see if it's an Oxford Semiconductor UART.
+-       *
+-       * If we have to do this here because some non-National
+-       * Semiconductor clone chips lock up if you try writing to the
+-       * LSR register (which serial_icr_read does)
+-       */
+-      if (state->type == PORT_16550A) {
+-              /*
+-               * EFR [4] must be set else this test fails
+-               *
+-               * This shouldn't be necessary, but Mike Hudson
+-               * (Exoray@isys.ca) claims that it's needed for 952
+-               * dual UART's (which are not recommended for new designs).
+-               */
+-              info->ACR = 0;
+-              serial_out(info, UART_LCR, 0xBF);
+-              serial_out(info, UART_EFR, 0x10);
+-              serial_out(info, UART_LCR, 0x00);
+-              /* Check for Oxford Semiconductor 16C950 */
+-              scratch = serial_icr_read(info, UART_ID1);
+-              scratch2 = serial_icr_read(info, UART_ID2);
+-              scratch3 = serial_icr_read(info, UART_ID3);
+-              
+-              if (scratch == 0x16 && scratch2 == 0xC9 &&
+-                  (scratch3 == 0x50 || scratch3 == 0x52 ||
+-                   scratch3 == 0x54)) {
+-                      state->type = PORT_16C950;
+-                      state->revision = serial_icr_read(info, UART_REV) |
+-                              (scratch3 << 8);
+-                      return;
+-              }
+-      }
+-      
+-      /*
+-       * We check for a XR16C850 by setting DLL and DLM to 0, and
+-       * then reading back DLL and DLM.  If DLM reads back 0x10,
+-       * then the UART is a XR16C850 and the DLL contains the chip
+-       * revision.  If DLM reads back 0x14, then the UART is a
+-       * XR16C854.
+-       * 
+-       */
+-
+-      /* Save the DLL and DLM */
+-
+-      serial_outp(info, UART_LCR, UART_LCR_DLAB);
+-      scratch3 = serial_inp(info, UART_DLL);
+-      scratch4 = serial_inp(info, UART_DLM);
+-
+-      serial_outp(info, UART_DLL, 0);
+-      serial_outp(info, UART_DLM, 0);
+-      scratch2 = serial_inp(info, UART_DLL);
+-      scratch = serial_inp(info, UART_DLM);
+-      serial_outp(info, UART_LCR, 0);
+-
+-      if (scratch == 0x10 || scratch == 0x14) {
+-              if (scratch == 0x10)
+-                      state->revision = scratch2;
+-              state->type = PORT_16850;
+-              return;
+-      }
+-
+-      /* Restore the DLL and DLM */
+-
+-      serial_outp(info, UART_LCR, UART_LCR_DLAB);
+-      serial_outp(info, UART_DLL, scratch3);
+-      serial_outp(info, UART_DLM, scratch4);
+-      serial_outp(info, UART_LCR, 0);
+-      /*
+-       * We distinguish between the '654 and the '650 by counting
+-       * how many bytes are in the FIFO.  I'm using this for now,
+-       * since that's the technique that was sent to me in the
+-       * serial driver update, but I'm not convinced this works.
+-       * I've had problems doing this in the past.  -TYT
+-       */
+-      if (size_fifo(info) == 64)
+-              state->type = PORT_16654;
+-      else
+-              state->type = PORT_16650V2;
+-}
+-
+-/*
+- * This routine is called by rs_init() to initialize a specific serial
+- * port.  It determines what type of UART chip this serial port is
+- * using: 8250, 16450, 16550, 16550A.  The important question is
+- * whether or not this UART is a 16550A or not, since this will
+- * determine whether or not we can use its FIFO features or not.
+- */
+-static void autoconfig(struct serial_state * state)
+-{
+-      unsigned char status1, status2, scratch, scratch2, scratch3;
+-      unsigned char save_lcr, save_mcr;
+-      struct async_struct *info, scr_info;
+-      unsigned long flags;
+-
+-      state->type = PORT_UNKNOWN;
+-
+-#ifdef SERIAL_DEBUG_AUTOCONF
+-      printk("Testing ttyS%d (0x%04lx, 0x%04x)...\n", state->line,
+-             state->port, (unsigned) state->iomem_base);
+-#endif
+-      
+-      if (!CONFIGURED_SERIAL_PORT(state))
+-              return;
+-              
+-      info = &scr_info;       /* This is just for serial_{in,out} */
+-
+-      info->magic = SERIAL_MAGIC;
+-      info->state = state;
+-      info->port = state->port;
+-      info->flags = state->flags;
+-#ifdef CONFIG_HUB6
+-      info->hub6 = state->hub6;
+-#endif
+-      info->io_type = state->io_type;
+-      info->iomem_base = state->iomem_base;
+-      info->iomem_reg_shift = state->iomem_reg_shift;
+-
+-      save_flags(flags); cli();
+-      
+-      if (!(state->flags & ASYNC_BUGGY_UART) &&
+-          !state->iomem_base) {
+-              /*
+-               * Do a simple existence test first; if we fail this,
+-               * there's no point trying anything else.
+-               * 
+-               * 0x80 is used as a nonsense port to prevent against
+-               * false positives due to ISA bus float.  The
+-               * assumption is that 0x80 is a non-existent port;
+-               * which should be safe since include/asm/io.h also
+-               * makes this assumption.
+-               */
+-              scratch = serial_inp(info, UART_IER);
+-              serial_outp(info, UART_IER, 0);
+-#ifdef __i386__
+-              outb(0xff, 0x080);
+-#endif
+-              scratch2 = serial_inp(info, UART_IER);
+-              serial_outp(info, UART_IER, 0x0F);
+-#ifdef __i386__
+-              outb(0, 0x080);
+-#endif
+-              scratch3 = serial_inp(info, UART_IER);
+-              serial_outp(info, UART_IER, scratch);
+-              if (scratch2 || scratch3 != 0x0F) {
+-#ifdef SERIAL_DEBUG_AUTOCONF
+-                      printk("serial: ttyS%d: simple autoconfig failed "
+-                             "(%02x, %02x)\n", state->line, 
+-                             scratch2, scratch3);
+-#endif
+-                      restore_flags(flags);
+-                      return;         /* We failed; there's nothing here */
+-              }
+-      }
+-
+-      save_mcr = serial_in(info, UART_MCR);
+-      save_lcr = serial_in(info, UART_LCR);
+-
+-      /* 
+-       * Check to see if a UART is really there.  Certain broken
+-       * internal modems based on the Rockwell chipset fail this
+-       * test, because they apparently don't implement the loopback
+-       * test mode.  So this test is skipped on the COM 1 through
+-       * COM 4 ports.  This *should* be safe, since no board
+-       * manufacturer would be stupid enough to design a board
+-       * that conflicts with COM 1-4 --- we hope!
+-       */
+-      if (!(state->flags & ASYNC_SKIP_TEST)) {
+-              serial_outp(info, UART_MCR, UART_MCR_LOOP | 0x0A);
+-              status1 = serial_inp(info, UART_MSR) & 0xF0;
+-              serial_outp(info, UART_MCR, save_mcr);
+-              if (status1 != 0x90) {
+-#ifdef SERIAL_DEBUG_AUTOCONF
+-                      printk("serial: ttyS%d: no UART loopback failed\n",
+-                             state->line);
+-#endif
+-                      restore_flags(flags);
+-                      return;
+-              }
+-      }
+-      serial_outp(info, UART_LCR, 0xBF); /* set up for StarTech test */
+-      serial_outp(info, UART_EFR, 0); /* EFR is the same as FCR */
+-      serial_outp(info, UART_LCR, 0);
+-      serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
+-      scratch = serial_in(info, UART_IIR) >> 6;
+-      switch (scratch) {
+-              case 0:
+-                      state->type = PORT_16450;
+-                      break;
+-              case 1:
+-                      state->type = PORT_UNKNOWN;
+-                      break;
+-              case 2:
+-                      state->type = PORT_16550;
+-                      break;
+-              case 3:
+-                      state->type = PORT_16550A;
+-                      break;
+-      }
+-      if (state->type == PORT_16550A) {
+-              /* Check for Startech UART's */
+-              serial_outp(info, UART_LCR, UART_LCR_DLAB);
+-              if (serial_in(info, UART_EFR) == 0) {
+-                      state->type = PORT_16650;
+-              } else {
+-                      serial_outp(info, UART_LCR, 0xBF);
+-                      if (serial_in(info, UART_EFR) == 0)
+-                              autoconfig_startech_uarts(info, state, flags);
+-              }
+-      }
+-      if (state->type == PORT_16550A) {
+-              /* Check for TI 16750 */
+-              serial_outp(info, UART_LCR, save_lcr | UART_LCR_DLAB);
+-              serial_outp(info, UART_FCR,
+-                          UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
+-              scratch = serial_in(info, UART_IIR) >> 5;
+-              if (scratch == 7) {
+-                      /*
+-                       * If this is a 16750, and not a cheap UART
+-                       * clone, then it should only go into 64 byte
+-                       * mode if the UART_FCR7_64BYTE bit was set
+-                       * while UART_LCR_DLAB was latched.
+-                       */
+-                      serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
+-                      serial_outp(info, UART_LCR, 0);
+-                      serial_outp(info, UART_FCR,
+-                                  UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
+-                      scratch = serial_in(info, UART_IIR) >> 5;
+-                      if (scratch == 6)
+-                              state->type = PORT_16750;
+-              }
+-              serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
+-      }
+-#if defined(CONFIG_SERIAL_RSA) && defined(MODULE)
+-      if (state->type == PORT_16550A) {
+-              int i;
+-
+-              for (i = 0 ; i < PORT_RSA_MAX ; ++i) {
+-                      if (!probe_rsa[i] && !force_rsa[i])
+-                              break;
+-                      if (((probe_rsa[i] != state->port) ||
+-                           check_region(state->port + UART_RSA_BASE, 16)) &&
+-                          (force_rsa[i] != state->port))
+-                              continue;
+-                      if (!enable_rsa(info))
+-                              continue;
+-                      state->type = PORT_RSA;
+-                      state->baud_base = SERIAL_RSA_BAUD_BASE;
+-                      break;
+-              }
+-      }
+-#endif
+-      serial_outp(info, UART_LCR, save_lcr);
+-      if (state->type == PORT_16450) {
+-              scratch = serial_in(info, UART_SCR);
+-              serial_outp(info, UART_SCR, 0xa5);
+-              status1 = serial_in(info, UART_SCR);
+-              serial_outp(info, UART_SCR, 0x5a);
+-              status2 = serial_in(info, UART_SCR);
+-              serial_outp(info, UART_SCR, scratch);
+-
+-              if ((status1 != 0xa5) || (status2 != 0x5a))
+-                      state->type = PORT_8250;
+-      }
+-      state->xmit_fifo_size = uart_config[state->type].dfl_xmit_fifo_size;
+-
+-      if (state->type == PORT_UNKNOWN) {
+-              restore_flags(flags);
+-              return;
+-      }
+-
+-      if (info->port) {
+-#ifdef CONFIG_SERIAL_RSA
+-              if (state->type == PORT_RSA)
+-                      request_region(info->port + UART_RSA_BASE, 16,
+-                                     "serial_rsa(auto)");
+-              else
+-#endif
+-                      request_region(info->port,8,"serial(auto)");
+-      }
+-
+-      /*
+-       * Reset the UART.
+-       */
+-#ifdef CONFIG_SERIAL_RSA
+-      if (state->type == PORT_RSA)
+-              serial_outp(info, UART_RSA_FRR, 0);
+-#endif
+-      serial_outp(info, UART_MCR, save_mcr);
+-      serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO |
+-                                   UART_FCR_CLEAR_RCVR |
+-                                   UART_FCR_CLEAR_XMIT));
+-      serial_outp(info, UART_FCR, 0);
+-      (void)serial_in(info, UART_RX);
+-      serial_outp(info, UART_IER, 0);
+-      
+-      restore_flags(flags);
+-}
+-
+-int register_serial(struct serial_struct *req);
+-void unregister_serial(int line);
+-
+-#if (LINUX_VERSION_CODE > 0x20100)
+-EXPORT_SYMBOL(register_serial);
+-EXPORT_SYMBOL(unregister_serial);
+-#else
+-static struct symbol_table serial_syms = {
+-#include <linux/symtab_begin.h>
+-      X(register_serial),
+-      X(unregister_serial),
+-#include <linux/symtab_end.h>
+-};
+-#endif
+-
+-
+-#if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP) 
+-
+-static void __devinit printk_pnp_dev_id(unsigned short vendor,
+-                                   unsigned short device)
+-{
+-      printk("%c%c%c%x%x%x%x",
+-             'A' + ((vendor >> 2) & 0x3f) - 1,
+-             'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
+-             'A' + ((vendor >> 8) & 0x1f) - 1,
+-             (device >> 4) & 0x0f,
+-             device & 0x0f,
+-             (device >> 12) & 0x0f,
+-             (device >> 8) & 0x0f);
+-}
+-
+-static _INLINE_ int get_pci_port(struct pci_dev *dev,
+-                                struct pci_board *board,
+-                                struct serial_struct *req,
+-                                int idx)
+-{
+-      unsigned long port;
+-      int base_idx;
+-      int max_port;
+-      int offset;
+-
+-      base_idx = SPCI_FL_GET_BASE(board->flags);
+-      if (board->flags & SPCI_FL_BASE_TABLE)
+-              base_idx += idx;
+-
+-      if (board->flags & SPCI_FL_REGION_SZ_CAP) {
+-              max_port = pci_resource_len(dev, base_idx) / 8;
+-              if (idx >= max_port)
+-                      return 1;
+-      }
+-                      
+-      offset = board->first_uart_offset;
+-
+-      /* Timedia/SUNIX uses a mixture of BARs and offsets */
+-      /* Ugh, this is ugly as all hell --- TYT */
+-      if(dev->vendor == PCI_VENDOR_ID_TIMEDIA )  /* 0x1409 */
+-              switch(idx) {
+-                      case 0: base_idx=0;
+-                              break;
+-                      case 1: base_idx=0; offset=8;
+-                              break;
+-                      case 2: base_idx=1; 
+-                              break;
+-                      case 3: base_idx=1; offset=8;
+-                              break;
+-                      case 4: /* BAR 2*/
+-                      case 5: /* BAR 3 */
+-                      case 6: /* BAR 4*/
+-                      case 7: base_idx=idx-2; /* BAR 5*/
+-              }
+-
+-      /* Some Titan cards are also a little weird */
+-      if (dev->vendor == PCI_VENDOR_ID_TITAN &&
+-          (dev->device == PCI_DEVICE_ID_TITAN_400L ||
+-           dev->device == PCI_DEVICE_ID_TITAN_800L)) {
+-              switch (idx) {
+-              case 0: base_idx = 1;
+-                      break;
+-              case 1: base_idx = 2;
+-                      break;
+-              default:
+-                      base_idx = 4;
+-                      offset = 8 * (idx - 2);
+-              }
+-              
+-      }
+-  
+-      /* HP's Diva chip puts the 4th/5th serial port further out, and
+-       * some serial ports are supposed to be hidden on certain models.
+-       */
+-      if (dev->vendor == PCI_VENDOR_ID_HP &&
+-                      dev->device == PCI_DEVICE_ID_HP_SAS) {
+-              switch (dev->subsystem_device) {
+-              case 0x104B: /* Maestro */
+-                      if (idx == 3) idx++;
+-                      break;
+-              case 0x1282: /* Everest / Longs Peak */
+-                      if (idx > 0) idx++;
+-                      if (idx > 2) idx++;
+-                      break;
+-              }
+-              if (idx > 2) {
+-                      offset = 0x18;
+-              }
+-      }
+-
+-      port =  pci_resource_start(dev, base_idx) + offset;
+-
+-      if ((board->flags & SPCI_FL_BASE_TABLE) == 0)
+-              port += idx * (board->uart_offset ? board->uart_offset : 8);
+-
+-      if (IS_PCI_REGION_IOPORT(dev, base_idx)) {
+-              req->port = port;
+-              if (HIGH_BITS_OFFSET)
+-                      req->port_high = port >> HIGH_BITS_OFFSET;
+-              else
+-                      req->port_high = 0;
+-              return 0;
+-      }
+-      req->io_type = SERIAL_IO_MEM;
+-      req->iomem_base = ioremap(port, board->uart_offset);
+-      req->iomem_reg_shift = board->reg_shift;
+-      req->port = 0;
+-      return 0;
+-}
+-
+-static _INLINE_ int get_pci_irq(struct pci_dev *dev,
+-                              struct pci_board *board,
+-                              int idx)
+-{
+-      int base_idx;
+-
+-      if ((board->flags & SPCI_FL_IRQRESOURCE) == 0)
+-              return dev->irq;
+-
+-      base_idx = SPCI_FL_GET_IRQBASE(board->flags);
+-      if (board->flags & SPCI_FL_IRQ_TABLE)
+-              base_idx += idx;
+-      
+-      return PCI_IRQ_RESOURCE(dev, base_idx);
+-}
+-
+-/*
+- * Common enabler code shared by both PCI and ISAPNP probes
+- */
+-static void __devinit start_pci_pnp_board(struct pci_dev *dev,
+-                                     struct pci_board *board)
+-{
+-      int k, line;
+-      struct serial_struct serial_req;
+-      int base_baud;
+-
+-       if (PREPARE_FUNC(dev) && (PREPARE_FUNC(dev))(dev) < 0) {
+-             printk("serial: PNP device '");
+-             printk_pnp_dev_id(dev->vendor, dev->device);
+-             printk("' prepare failed\n");
+-             return;
+-       }
+-
+-       if (ACTIVATE_FUNC(dev) && (ACTIVATE_FUNC(dev))(dev) < 0) {
+-             printk("serial: PNP device '");
+-             printk_pnp_dev_id(dev->vendor, dev->device);
+-             printk("' activate failed\n");
+-             return;
+-       }
+-
+-      /*
+-       * Run the initialization function, if any
+-       */
+-      if (board->init_fn && ((board->init_fn)(dev, board, 1) != 0))
+-              return;
+-
+-      /*
+-       * Register the serial board in the array if we need to
+-       * shutdown the board on a module unload or card removal
+-       */
+-      if (DEACTIVATE_FUNC(dev) || board->init_fn) {
+-              for (k=0; k < NR_PCI_BOARDS; k++)
+-                      if (serial_pci_board[k].dev == 0)
+-                              break;
+-              if (k >= NR_PCI_BOARDS)
+-                      return;
+-              serial_pci_board[k].board = *board;
+-              serial_pci_board[k].dev = dev;
+-      }
+-
+-      base_baud = board->base_baud;
+-      if (!base_baud)
+-              base_baud = BASE_BAUD;
+-      memset(&serial_req, 0, sizeof(serial_req));
+-
+-      for (k=0; k < board->num_ports; k++) {
+-              serial_req.irq = get_pci_irq(dev, board, k);
+-              if (get_pci_port(dev, board, &serial_req, k))
+-                      break;
+-              serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
+-#ifdef SERIAL_DEBUG_PCI
+-              printk("Setup PCI/PNP port: port %x, irq %d, type %d\n",
+-                     serial_req.port, serial_req.irq, serial_req.io_type);
+-#endif
+-              line = register_serial(&serial_req);
+-              if (line < 0)
+-                      break;
+-              rs_table[line].baud_base = base_baud;
+-              rs_table[line].dev = dev;
+-      }
+-}
+-#endif        /* ENABLE_SERIAL_PCI || ENABLE_SERIAL_PNP */
+-
+-#ifdef ENABLE_SERIAL_PCI
+-/*
+- * Some PCI serial cards using the PLX 9050 PCI interface chip require
+- * that the card interrupt be explicitly enabled or disabled.  This
+- * seems to be mainly needed on card using the PLX which also use I/O
+- * mapped memory.
+- */
+-static int __devinit
+-pci_plx9050_fn(struct pci_dev *dev, struct pci_board *board, int enable)
+-{
+-      u8 data, *p, irq_config;
+-      int pci_config;
+-
+-      irq_config = 0x41;
+-      pci_config = PCI_COMMAND_MEMORY;
+-      if (dev->vendor == PCI_VENDOR_ID_PANACOM)
+-              irq_config = 0x43;
+-      if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
+-          (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) {
+-              /*
+-               * As the megawolf cards have the int pins active
+-               * high, and have 2 UART chips, both ints must be
+-               * enabled on the 9050. Also, the UARTS are set in
+-               * 16450 mode by default, so we have to enable the
+-               * 16C950 'enhanced' mode so that we can use the deep
+-               * FIFOs
+-               */
+-              irq_config = 0x5b;
+-              pci_config = PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
+-      }
+-      
+-      pci_read_config_byte(dev, PCI_COMMAND, &data);
+-
+-      if (enable)
+-              pci_write_config_byte(dev, PCI_COMMAND,
+-                                    data | pci_config);
+-      
+-      /* enable/disable interrupts */
+-      p = ioremap(pci_resource_start(dev, 0), 0x80);
+-      writel(enable ? irq_config : 0x00, (unsigned long)p + 0x4c);
+-      iounmap(p);
+-
+-      if (!enable)
+-              pci_write_config_byte(dev, PCI_COMMAND,
+-                                    data & ~pci_config);
+-      return 0;
+-}
+-
+-
+-/*
+- * SIIG serial cards have an PCI interface chip which also controls
+- * the UART clocking frequency. Each UART can be clocked independently
+- * (except cards equiped with 4 UARTs) and initial clocking settings
+- * are stored in the EEPROM chip. It can cause problems because this
+- * version of serial driver doesn't support differently clocked UART's
+- * on single PCI card. To prevent this, initialization functions set
+- * high frequency clocking for all UART's on given card. It is safe (I
+- * hope) because it doesn't touch EEPROM settings to prevent conflicts
+- * with other OSes (like M$ DOS).
+- *
+- *  SIIG support added by Andrey Panin <pazke@mail.tp.ru>, 10/1999
+- * 
+- * There is two family of SIIG serial cards with different PCI
+- * interface chip and different configuration methods:
+- *     - 10x cards have control registers in IO and/or memory space;
+- *     - 20x cards have control registers in standard PCI configuration space.
+- *
+- * SIIG initialization functions exported for use by parport_serial.c module.
+- */
+-
+-#define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc)
+-#define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8)
+-
+-int __devinit
+-pci_siig10x_fn(struct pci_dev *dev, struct pci_board *board, int enable)
+-{
+-       u16 data, *p;
+-
+-       if (!enable) return 0;
+-
+-       p = ioremap(pci_resource_start(dev, 0), 0x80);
+-
+-       switch (dev->device & 0xfff8) {
+-               case PCI_DEVICE_ID_SIIG_1S_10x:         /* 1S */
+-                       data = 0xffdf;
+-                       break;
+-               case PCI_DEVICE_ID_SIIG_2S_10x:         /* 2S, 2S1P */
+-                       data = 0xf7ff;
+-                       break;
+-               default:                                /* 1S1P, 4S */
+-                       data = 0xfffb;
+-                       break;
+-       }
+-
+-       writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28);
+-       iounmap(p);
+-       return 0;
+-}
+-EXPORT_SYMBOL(pci_siig10x_fn);
+-
+-#define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc)
+-#define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc)
+-
+-int __devinit
+-pci_siig20x_fn(struct pci_dev *dev, struct pci_board *board, int enable)
+-{
+-       u8 data;
+-
+-       if (!enable) return 0;
+-
+-       /* Change clock frequency for the first UART. */
+-       pci_read_config_byte(dev, 0x6f, &data);
+-       pci_write_config_byte(dev, 0x6f, data & 0xef);
+-
+-       /* If this card has 2 UART, we have to do the same with second UART. */
+-       if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) ||
+-           ((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) {
+-               pci_read_config_byte(dev, 0x73, &data);
+-               pci_write_config_byte(dev, 0x73, data & 0xef);
+-       }
+-       return 0;
+-}
+-EXPORT_SYMBOL(pci_siig20x_fn);
+-
+-/* Added for EKF Intel i960 serial boards */
+-static int __devinit
+-pci_inteli960ni_fn(struct pci_dev *dev,
+-                 struct pci_board *board,
+-                 int enable)
+-{
+-      unsigned long oldval;
+-      
+-      if (!(pci_get_subdevice(dev) & 0x1000))
+-              return(-1);
+-
+-      if (!enable) /* is there something to deinit? */
+-              return(0);
+-   
+-#ifdef SERIAL_DEBUG_PCI
+-      printk(KERN_DEBUG " Subsystem ID %lx (intel 960)\n",
+-             (unsigned long) board->subdevice);
+-#endif
+-      /* is firmware started? */
+-      pci_read_config_dword(dev, 0x44, (void*) &oldval); 
+-      if (oldval == 0x00001000L) { /* RESET value */ 
+-              printk(KERN_DEBUG "Local i960 firmware missing");
+-              return(-1); 
+-      }
+-      return(0);
+-}
+-
+-/*
+- * Timedia has an explosion of boards, and to avoid the PCI table from
+- * growing *huge*, we use this function to collapse some 70 entries
+- * in the PCI table into one, for sanity's and compactness's sake.
+- */
+-static unsigned short timedia_single_port[] = {
+-      0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0 };
+-static unsigned short timedia_dual_port[] = {
+-      0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085,
+-      0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079, 
+-      0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079, 
+-      0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079,
+-      0xD079, 0 };
+-static unsigned short timedia_quad_port[] = {
+-      0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157, 
+-      0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159, 
+-      0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056,
+-      0xB157, 0 };
+-static unsigned short timedia_eight_port[] = {
+-      0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166, 
+-      0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0 };
+-static struct timedia_struct {
+-      int num;
+-      unsigned short *ids;
+-} timedia_data[] = {
+-      { 1, timedia_single_port },
+-      { 2, timedia_dual_port },
+-      { 4, timedia_quad_port },
+-      { 8, timedia_eight_port },
+-      { 0, 0 }
+-};
+-
+-static int __devinit
+-pci_timedia_fn(struct pci_dev *dev, struct pci_board *board, int enable)
+-{
+-      int     i, j;
+-      unsigned short *ids;
+-
+-      if (!enable)
+-              return 0;
+-
+-      for (i=0; timedia_data[i].num; i++) {
+-              ids = timedia_data[i].ids;
+-              for (j=0; ids[j]; j++) {
+-                      if (pci_get_subdevice(dev) == ids[j]) {
+-                              board->num_ports = timedia_data[i].num;
+-                              return 0;
+-                      }
+-              }
+-      }
+-      return 0;
+-}
+-
+-/*
+- * HP's Remote Management Console.  The Diva chip came in several
+- * different versions.  N-class, L2000 and A500 have two Diva chips, each
+- * with 3 UARTs (the third UART on the second chip is unused).  Superdome
+- * and Keystone have one Diva chip with 3 UARTs.  Some later machines have
+- * one Diva chip, but it has been expanded to 5 UARTs.
+- */
+-static int __devinit
+-pci_hp_diva(struct pci_dev *dev, struct pci_board *board, int enable)
+-{
+-      if (!enable)
+-              return 0;
+-
+-      switch (dev->subsystem_device) {
+-      case 0x1049: /* Prelude Diva 1 */
+-      case 0x1223: /* Superdome */
+-      case 0x1226: /* Keystone */
+-      case 0x1282: /* Everest / Longs Peak */
+-              board->num_ports = 3;
+-              break;
+-      case 0x104A: /* Prelude Diva 2 */
+-              board->num_ports = 2;
+-              break;
+-      case 0x104B: /* Maestro */
+-              board->num_ports = 4;
+-              break;
+-      case 0x1227: /* Powerbar */
+-              board->num_ports = 1;
+-              break;
+-      }
+-
+-      return 0;
+-}
+-
+-static int __devinit
+-pci_xircom_fn(struct pci_dev *dev, struct pci_board *board, int enable)
+-{
+-      __set_current_state(TASK_UNINTERRUPTIBLE);
+-      schedule_timeout(HZ/10);
+-      return 0;
+-}
+-
+-/*
+- * This is the configuration table for all of the PCI serial boards
+- * which we support.  It is directly indexed by the pci_board_num_t enum
+- * value, which is encoded in the pci_device_id PCI probe table's
+- * driver_data member.
+- */
+-enum pci_board_num_t {
+-      pbn_b0_1_115200,
+-      pbn_default = 0,
+-
+-      pbn_b0_2_115200,
+-      pbn_b0_4_115200,
+-
+-      pbn_b0_1_921600,
+-      pbn_b0_2_921600,
+-      pbn_b0_4_921600,
+-
+-      pbn_b0_bt_1_115200,
+-      pbn_b0_bt_2_115200,
+-      pbn_b0_bt_1_460800,
+-      pbn_b0_bt_2_460800,
+-      pbn_b0_bt_2_921600,
+-
+-      pbn_b1_1_115200,
+-      pbn_b1_2_115200,
+-      pbn_b1_4_115200,
+-      pbn_b1_8_115200,
+-
+-      pbn_b1_2_921600,
+-      pbn_b1_4_921600,
+-      pbn_b1_8_921600,
+-
+-      pbn_b1_2_1382400,
+-      pbn_b1_4_1382400,
+-      pbn_b1_8_1382400,
+-
+-      pbn_b2_1_115200,
+-      pbn_b2_8_115200,
+-      pbn_b2_4_460800,
+-      pbn_b2_8_460800,
+-      pbn_b2_16_460800,
+-      pbn_b2_4_921600,
+-      pbn_b2_8_921600,
+-
+-      pbn_b2_bt_1_115200,
+-      pbn_b2_bt_2_115200,
+-      pbn_b2_bt_4_115200,
+-      pbn_b2_bt_2_921600,
+-
+-      pbn_panacom,
+-      pbn_panacom2,
+-      pbn_panacom4,
+-      pbn_plx_romulus,
+-      pbn_oxsemi,
+-      pbn_timedia,
+-      pbn_intel_i960,
+-      pbn_sgi_ioc3,
+-      pbn_hp_diva,
+-#ifdef CONFIG_DDB5074
+-      pbn_nec_nile4,
+-#endif
+-#if 0
+-      pbn_dci_pccom8,
+-#endif
+-      pbn_xircom_combo,
+-
+-      pbn_siig10x_0,
+-      pbn_siig10x_1,
+-      pbn_siig10x_2,
+-      pbn_siig10x_4,
+-      pbn_siig20x_0,
+-      pbn_siig20x_2,
+-      pbn_siig20x_4,
+-      
+-      pbn_computone_4,
+-      pbn_computone_6,
+-      pbn_computone_8,
+-};
+-
+-static struct pci_board pci_boards[] __devinitdata = {
+-      /*
+-       * PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
+-       * Offset to get to next UART's registers,
+-       * Register shift to use for memory-mapped I/O,
+-       * Initialization function, first UART offset
+-       */
+-
+-      /* Generic serial board, pbn_b0_1_115200, pbn_default */
+-      { SPCI_FL_BASE0, 1, 115200 },           /* pbn_b0_1_115200,
+-                                                 pbn_default */
+-
+-      { SPCI_FL_BASE0, 2, 115200 },           /* pbn_b0_2_115200 */
+-      { SPCI_FL_BASE0, 4, 115200 },           /* pbn_b0_4_115200 */
+-
+-      { SPCI_FL_BASE0, 1, 921600 },           /* pbn_b0_1_921600 */
+-      { SPCI_FL_BASE0, 2, 921600 },           /* pbn_b0_2_921600 */
+-      { SPCI_FL_BASE0, 4, 921600 },           /* pbn_b0_4_921600 */
+-
+-      { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b0_bt_1_115200 */
+-      { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b0_bt_2_115200 */
+-      { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 460800 }, /* pbn_b0_bt_1_460800 */
+-      { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 460800 }, /* pbn_b0_bt_2_460800 */
+-      { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b0_bt_2_921600 */
+-
+-      { SPCI_FL_BASE1, 1, 115200 },           /* pbn_b1_1_115200 */
+-      { SPCI_FL_BASE1, 2, 115200 },           /* pbn_b1_2_115200 */
+-      { SPCI_FL_BASE1, 4, 115200 },           /* pbn_b1_4_115200 */
+-      { SPCI_FL_BASE1, 8, 115200 },           /* pbn_b1_8_115200 */
+-
+-      { SPCI_FL_BASE1, 2, 921600 },           /* pbn_b1_2_921600 */
+-      { SPCI_FL_BASE1, 4, 921600 },           /* pbn_b1_4_921600 */
+-      { SPCI_FL_BASE1, 8, 921600 },           /* pbn_b1_8_921600 */
+-
+-      { SPCI_FL_BASE1, 2, 1382400 },          /* pbn_b1_2_1382400 */
+-      { SPCI_FL_BASE1, 4, 1382400 },          /* pbn_b1_4_1382400 */
+-      { SPCI_FL_BASE1, 8, 1382400 },          /* pbn_b1_8_1382400 */
+-
+-      { SPCI_FL_BASE2, 1, 115200 },           /* pbn_b2_1_115200 */
+-      { SPCI_FL_BASE2, 8, 115200 },           /* pbn_b2_8_115200 */
+-      { SPCI_FL_BASE2, 4, 460800 },           /* pbn_b2_4_460800 */
+-      { SPCI_FL_BASE2, 8, 460800 },           /* pbn_b2_8_460800 */
+-      { SPCI_FL_BASE2, 16, 460800 },          /* pbn_b2_16_460800 */
+-      { SPCI_FL_BASE2, 4, 921600 },           /* pbn_b2_4_921600 */
+-      { SPCI_FL_BASE2, 8, 921600 },           /* pbn_b2_8_921600 */
+-
+-      { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b2_bt_1_115200 */
+-      { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b2_bt_2_115200 */
+-      { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 115200 }, /* pbn_b2_bt_4_115200 */
+-      { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b2_bt_2_921600 */
+-
+-      { SPCI_FL_BASE2, 2, 921600, /* IOMEM */            /* pbn_panacom */
+-              0x400, 7, pci_plx9050_fn },
+-      { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600,   /* pbn_panacom2 */
+-              0x400, 7, pci_plx9050_fn },
+-      { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600,   /* pbn_panacom4 */
+-              0x400, 7, pci_plx9050_fn },
+-      { SPCI_FL_BASE2, 4, 921600,                        /* pbn_plx_romulus */
+-              0x20, 2, pci_plx9050_fn, 0x03 },
+-              /* This board uses the size of PCI Base region 0 to
+-               * signal now many ports are available */
+-      { SPCI_FL_BASE0 | SPCI_FL_REGION_SZ_CAP, 32, 115200 }, /* pbn_oxsemi */
+-      { SPCI_FL_BASE_TABLE, 1, 921600,                   /* pbn_timedia */
+-              0, 0, pci_timedia_fn },
+-      /* EKF addition for i960 Boards form EKF with serial port */
+-      { SPCI_FL_BASE0, 32, 921600, /* max 256 ports */   /* pbn_intel_i960 */
+-              8<<2, 2, pci_inteli960ni_fn, 0x10000},
+-      { SPCI_FL_BASE0 | SPCI_FL_IRQRESOURCE,             /* pbn_sgi_ioc3 */
+-              1, 458333, 0, 0, 0, 0x20178 },
+-      { SPCI_FL_BASE0, 5, 115200, 8, 0, pci_hp_diva, 0},   /* pbn_hp_diva */
+-#ifdef CONFIG_DDB5074
+-      /*
+-       * NEC Vrc-5074 (Nile 4) builtin UART.
+-       * Conditionally compiled in since this is a motherboard device.
+-       */
+-      { SPCI_FL_BASE0, 1, 520833,                        /* pbn_nec_nile4 */
+-              64, 3, NULL, 0x300 },
+-#endif
+-#if 0 /* PCI_DEVICE_ID_DCI_PCCOM8 ? */                   /* pbn_dci_pccom8 */
+-      { SPCI_FL_BASE3, 8, 115200, 8 },
+-#endif
+-      { SPCI_FL_BASE0, 1, 115200,                       /* pbn_xircom_combo */
+-              0, 0, pci_xircom_fn },
+-
+-      { SPCI_FL_BASE2, 1, 460800,                        /* pbn_siig10x_0 */
+-              0, 0, pci_siig10x_fn },
+-      { SPCI_FL_BASE2, 1, 921600,                        /* pbn_siig10x_1 */
+-              0, 0, pci_siig10x_fn },
+-      { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600,   /* pbn_siig10x_2 */
+-              0, 0, pci_siig10x_fn },
+-      { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600,   /* pbn_siig10x_4 */
+-              0, 0, pci_siig10x_fn },
+-      { SPCI_FL_BASE0, 1, 921600,                        /* pbn_siix20x_0 */
+-              0, 0, pci_siig20x_fn },
+-      { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600,   /* pbn_siix20x_2 */
+-              0, 0, pci_siig20x_fn },
+-      { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 921600,   /* pbn_siix20x_4 */
+-              0, 0, pci_siig20x_fn },
+-
+-      { SPCI_FL_BASE0, 4, 921600, /* IOMEM */            /* pbn_computone_4 */
+-              0x40, 2, NULL, 0x200 },
+-      { SPCI_FL_BASE0, 6, 921600, /* IOMEM */            /* pbn_computone_6 */
+-              0x40, 2, NULL, 0x200 },
+-      { SPCI_FL_BASE0, 8, 921600, /* IOMEM */            /* pbn_computone_8 */
+-              0x40, 2, NULL, 0x200 },
+-};
+-
+-/*
+- * Given a complete unknown PCI device, try to use some heuristics to
+- * guess what the configuration might be, based on the pitiful PCI
+- * serial specs.  Returns 0 on success, 1 on failure.
++ * The serial driver boot-time initialization code!
+  */
+-static int __devinit serial_pci_guess_board(struct pci_dev *dev,
+-                                         struct pci_board *board)
++static int __init rs_init(void)
+ {
+-      int     num_iomem = 0, num_port = 0, first_port = -1;
+       int     i;
++      struct serial_state * state;
+       
+-      /*
+-       * If it is not a communications device or the programming
+-       * interface is greater than 6, give up.
+-       *
+-       * (Should we try to make guesses for multiport serial devices
+-       * later?) 
+-       */
+-      if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) &&
+-          ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) ||
+-          (dev->class & 0xff) > 6)
+-              return 1;
+-
+-      for (i=0; i < 6; i++) {
+-              if (IS_PCI_REGION_IOPORT(dev, i)) {
+-                      num_port++;
+-                      if (first_port == -1)
+-                              first_port = i;
+-              }
+-              if (IS_PCI_REGION_IOMEM(dev, i))
+-                      num_iomem++;
+-      }
++      printk("pxa & ti16c754b serial driver\n");
++      set_GPIO_IRQ_edge(7, GPIO_RISING_EDGE);
++      set_GPIO_IRQ_edge(24, GPIO_RISING_EDGE);
++      set_GPIO_IRQ_edge(25, GPIO_RISING_EDGE);
++      set_GPIO_IRQ_edge(26, GPIO_RISING_EDGE);
+-      /*
+-       * If there is exactly one port of 8 bytes, use it.
+-       */
+-      if (num_port == 1 && pci_resource_len(dev, first_port) == 8) {
+-              board->flags = first_port;
+-              return 0;
++        if (!request_mem_region(RAMSES_UARTA_PHYS, 16*4, "Ramses UART A"))
++                printk(KERN_ERR "unable to reserve region\n");
++        else {
++                ramses_uarta = ioremap_nocache(RAMSES_UARTA_PHYS, 16*4);
++                if (!ramses_uarta)
++                        printk(KERN_ERR "unable to map region\n");
++                else {
++                      //printk("ramses_uarta cookie is: %08x\n", (unsigned int) ramses_uarta);
++                      rs_table[3].iomem_base = ramses_uarta;
+       }
+-
+-      /*
+-       * If there is 1 or 0 iomem regions, and exactly one port, use
+-       * it.
+-       */
+-      if (num_iomem <= 1 && num_port == 1) {
+-              board->flags = first_port;
+-              return 0;
+       }
+-      return 1;
+-}
+-
+-static int __devinit serial_init_one(struct pci_dev *dev,
+-                                   const struct pci_device_id *ent)
+-{
+-      struct pci_board *board, tmp;
+-      int rc;
+-
+-      board = &pci_boards[ent->driver_data];
+-
+-      rc = pci_enable_device(dev);
+-      if (rc) return rc;
+-
+-      if (ent->driver_data == pbn_default &&
+-          serial_pci_guess_board(dev, board))
+-              return -ENODEV;
+-      else if (serial_pci_guess_board(dev, &tmp) == 0) {
+-              printk(KERN_INFO "Redundant entry in serial pci_table.  "
+-                     "Please send the output of\n"
+-                     "lspci -vv, this message (%04x,%04x,%04x,%04x)\n"
+-                     "and the manufacturer and name of "
+-                     "serial board or modem board\n"
+-                     "to serial-pci-info@lists.sourceforge.net.\n",
+-                     dev->vendor, dev->device,
+-                     pci_get_subvendor(dev), pci_get_subdevice(dev));
+-      }
+-                     
+-      start_pci_pnp_board(dev, board);
+-
+-      return 0;
+-}
+-
+-static void __devexit serial_remove_one(struct pci_dev *dev)
+-{
+-      int     i;
+-
+-      /*
+-       * Iterate through all of the ports finding those that belong
+-       * to this PCI device.
+-       */
+-      for(i = 0; i < NR_PORTS; i++) {
+-              if (rs_table[i].dev != dev)
+-                      continue;
+-              unregister_serial(i);
+-              rs_table[i].dev = 0;
++        if (!request_mem_region(RAMSES_UARTB_PHYS, 16*4, "Ramses UART B"))
++                printk(KERN_ERR "unable to reserve region\n");
++        else {
++                ramses_uartb = ioremap_nocache(RAMSES_UARTB_PHYS, 16*4);
++                if (!ramses_uartb)
++                        printk(KERN_ERR "unable to map region\n");
++                else {
++                      //printk("ramses_uartb cookie is: %08x\n", (unsigned int) ramses_uartb);
++                      rs_table[4].iomem_base = ramses_uartb;
+       }
+-      /*
+-       * Now execute any board-specific shutdown procedure
+-       */
+-      for (i=0; i < NR_PCI_BOARDS; i++) {
+-              struct pci_board_inst *brd = &serial_pci_board[i];
+-
+-              if (serial_pci_board[i].dev != dev)
+-                      continue;
+-              if (brd->board.init_fn)
+-                      (brd->board.init_fn)(brd->dev, &brd->board, 0);
+-              if (DEACTIVATE_FUNC(brd->dev))
+-                      (DEACTIVATE_FUNC(brd->dev))(brd->dev);
+-              serial_pci_board[i].dev = 0;
+       }
+-}
+-
+-
+-static struct pci_device_id serial_pci_tbl[] __devinitdata = {
+-      {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
+-              PCI_SUBVENDOR_ID_CONNECT_TECH,
+-              PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
+-              pbn_b1_8_1382400 },
+-      {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
+-              PCI_SUBVENDOR_ID_CONNECT_TECH,
+-              PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
+-              pbn_b1_4_1382400 },
+-      {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
+-              PCI_SUBVENDOR_ID_CONNECT_TECH,
+-              PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
+-              pbn_b1_2_1382400 },
+-      {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+-              PCI_SUBVENDOR_ID_CONNECT_TECH,
+-              PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
+-              pbn_b1_8_1382400 },
+-      {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+-              PCI_SUBVENDOR_ID_CONNECT_TECH,
+-              PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0,
+-              pbn_b1_4_1382400 },
+-      {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+-              PCI_SUBVENDOR_ID_CONNECT_TECH,
+-              PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0,
+-              pbn_b1_2_1382400 },
+-      {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+-              PCI_SUBVENDOR_ID_CONNECT_TECH,
+-              PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485, 0, 0,
+-              pbn_b1_8_921600 },
+-      {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+-              PCI_SUBVENDOR_ID_CONNECT_TECH,
+-              PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, 0, 0,
+-              pbn_b1_8_921600 },
+-      {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+-              PCI_SUBVENDOR_ID_CONNECT_TECH,
+-              PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, 0, 0,
+-              pbn_b1_4_921600 },
+-      {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+-              PCI_SUBVENDOR_ID_CONNECT_TECH,
+-              PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, 0, 0,
+-              pbn_b1_4_921600 },
+-      {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+-              PCI_SUBVENDOR_ID_CONNECT_TECH,
+-              PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, 0, 0,
+-              pbn_b1_2_921600 },
+-      {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+-              PCI_SUBVENDOR_ID_CONNECT_TECH,
+-              PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6, 0, 0,
+-              pbn_b1_8_921600 },
+-      {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+-              PCI_SUBVENDOR_ID_CONNECT_TECH,
+-              PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1, 0, 0,
+-              pbn_b1_8_921600 },
+-      {       PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+-              PCI_SUBVENDOR_ID_CONNECT_TECH,
+-              PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0,
+-              pbn_b1_4_921600 },
+-
+-      {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b2_bt_1_115200 },
+-      {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM2,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b2_bt_2_115200 },
+-      {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM422,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b2_bt_4_115200 },
+-      {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM232,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b2_bt_2_115200 },
+-      {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM4,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b2_bt_4_115200 },
+-      {       PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b2_8_115200 },
+-
+-      {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_b2_bt_2_115200 },
+-      {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_b2_bt_2_921600 },
+-      /* VScom SPCOM800, from sl@s.pl */
+-      {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800, 
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b2_8_921600 },
+-      {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b2_4_921600 },
+-      {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+-              PCI_SUBVENDOR_ID_KEYSPAN,
+-              PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0,
+-              pbn_panacom },
+-      {       PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_QUADMODEM,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_panacom4 },
+-      {       PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_panacom2 },
+-      {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+-              PCI_SUBVENDOR_ID_CHASE_PCIFAST,
+-              PCI_SUBDEVICE_ID_CHASE_PCIFAST4, 0, 0, 
+-              pbn_b2_4_460800 },
+-      {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+-              PCI_SUBVENDOR_ID_CHASE_PCIFAST,
+-              PCI_SUBDEVICE_ID_CHASE_PCIFAST8, 0, 0, 
+-              pbn_b2_8_460800 },
+-      {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+-              PCI_SUBVENDOR_ID_CHASE_PCIFAST,
+-              PCI_SUBDEVICE_ID_CHASE_PCIFAST16, 0, 0, 
+-              pbn_b2_16_460800 },
+-      {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+-              PCI_SUBVENDOR_ID_CHASE_PCIFAST,
+-              PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC, 0, 0, 
+-              pbn_b2_16_460800 },
+-      {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+-              PCI_SUBVENDOR_ID_CHASE_PCIRAS,
+-              PCI_SUBDEVICE_ID_CHASE_PCIRAS4, 0, 0, 
+-              pbn_b2_4_460800 },
+-      {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+-              PCI_SUBVENDOR_ID_CHASE_PCIRAS,
+-              PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0, 
+-              pbn_b2_8_460800 },
+-      /* Megawolf Romulus PCI Serial Card, from Mike Hudson */
+-      /* (Exoray@isys.ca) */
+-      {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
+-              0x10b5, 0x106a, 0, 0,
+-              pbn_plx_romulus },
+-      {       PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b1_4_115200 },
+-      {       PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b1_2_115200 },
+-      {       PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b1_8_115200 },
+-      {       PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b1_8_115200 },
+-      {       PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954,
+-              PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4, 0, 0, 
+-              pbn_b0_4_921600 },
+-      {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b0_4_115200 },
+-      {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b0_bt_2_921600 },
+-
+-      /* Digitan DS560-558, from jimd@esoft.com */
+-      {       PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b1_1_115200 },
+-
+-      /* 3Com US Robotics 56k Voice Internal PCI model 5610 */
+-      {       PCI_VENDOR_ID_USR, 0x1008,
+-              PCI_ANY_ID, PCI_ANY_ID, },
+-
+-      /* Titan Electronic cards */
+-      {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b0_1_921600 },
+-      {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b0_2_921600 },
+-      {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b0_4_921600 },
+-      {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, 
+-              pbn_b0_4_921600 },
+-      {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L,
+-              PCI_ANY_ID, PCI_ANY_ID,
+-              SPCI_FL_BASE1, 1, 921600 },
+-      {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L,
+-              PCI_ANY_ID, PCI_ANY_ID,
+-              SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
+-      /* The 400L and 800L have a custom hack in get_pci_port */
+-      {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L,
+-              PCI_ANY_ID, PCI_ANY_ID,
+-              SPCI_FL_BASE_TABLE, 4, 921600 },
+-      {       PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L,
+-              PCI_ANY_ID, PCI_ANY_ID,
+-              SPCI_FL_BASE_TABLE, 8, 921600 },
+-
+-      {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_siig10x_0 },
+-      {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_siig10x_0 },
+-      {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_siig10x_0 },
+-      {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_siig10x_2 },
+-      {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_siig10x_2 },
+-      {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_siig10x_2 },
+-      {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_siig10x_4 },
+-      {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_siig10x_4 },
+-      {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_siig10x_4 },
+-      {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_siig20x_0 },
+-      {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_siig20x_0 },
+-      {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_siig20x_0 },
+-      {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_siig20x_2 },
+-      {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_siig20x_2 },
+-      {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_siig20x_2 },
+-      {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_siig20x_4 },
+-      {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_siig20x_4 },
+-      {       PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_siig20x_4 },
+-
+-      /* Computone devices submitted by Doug McNash dmcnash@computone.com */
+-      {       PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
+-              PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4,
+-              0, 0, pbn_computone_4 },
+-      {       PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
+-              PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG8,
+-              0, 0, pbn_computone_8 },
+-      {       PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
+-              PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG6,
+-              0, 0, pbn_computone_6 },
+-
+-      {       PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_oxsemi },
+-      {       PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889,
+-              PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0, pbn_timedia },
+-
+-      {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_b0_bt_2_115200 },
+-      {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_b0_bt_2_115200 },
+-      {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_b0_bt_2_115200 },
+-      {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_PLUS,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_b0_bt_2_460800 },
+-      {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_A,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_b0_bt_2_460800 },
+-      {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_B,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_b0_bt_2_460800 },
+-      {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_SSERIAL,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_b0_bt_1_115200 },
+-      {       PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_650,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_b0_bt_1_460800 },
+-
+-      /* RAStel 2 port modem, gerg@moreton.com.au */
+-      {       PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_b2_bt_2_115200 },
+-
+-      /* EKF addition for i960 Boards form EKF with serial port */
+-      {       PCI_VENDOR_ID_INTEL, 0x1960,
+-              0xE4BF, PCI_ANY_ID, 0, 0,
+-              pbn_intel_i960 },
+-
+-      /* Xircom Cardbus/Ethernet combos */
+-      {       PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_xircom_combo },
+-
+-      /*
+-       * Untested PCI modems, sent in from various folks...
+-       */
+-
+-      /* Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de> */
+-      {       PCI_VENDOR_ID_ROCKWELL, 0x1004,
+-              0x1048, 0x1500, 0, 0,
+-              pbn_b1_1_115200 },
+-
+-      {       PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
+-              0xFF00, 0, 0, 0,
+-              pbn_sgi_ioc3 },
+-
+-      /* HP Diva card */
+-      {       PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_SAS,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_hp_diva },
+-      {       PCI_VENDOR_ID_HP, 0x1290,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_b2_1_115200 },
+-
+-#ifdef CONFIG_DDB5074
+-      /*
+-       * NEC Vrc-5074 (Nile 4) builtin UART.
+-       * Conditionally compiled in since this is a motherboard device.
+-       */
+-      {       PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NILE4,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_nec_nile4 },
+-#endif
+-
+-#if 0 /* PCI_DEVICE_ID_DCI_PCCOM8 ? */
+-      {       PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8,
+-              PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+-              pbn_dci_pccom8 },
+-#endif
+-
+-       { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+-       PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xffff00, },
+-       { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+-       PCI_CLASS_COMMUNICATION_MODEM << 8, 0xffff00, },
+-       { 0, }
+-};
+-
+-MODULE_DEVICE_TABLE(pci, serial_pci_tbl);
+-
+-static struct pci_driver serial_pci_driver = {
+-       name:           "serial",
+-       probe:          serial_init_one,
+-       remove:               __devexit_p(serial_remove_one),
+-       id_table:       serial_pci_tbl,
+-};
+-
+-
+-/*
+- * Query PCI space for known serial boards
+- * If found, add them to the PCI device space in rs_table[]
+- *
+- * Accept a maximum of eight boards
+- *
+- */
+-static void __devinit probe_serial_pci(void) 
+-{
+-#ifdef SERIAL_DEBUG_PCI
+-      printk(KERN_DEBUG "Entered probe_serial_pci()\n");
+-#endif
+-
+-      /* Register call PCI serial devices.  Null out
+-       * the driver name upon failure, as a signal
+-       * not to attempt to unregister the driver later
+-       */
+-      if (pci_module_init (&serial_pci_driver) != 0)
+-              serial_pci_driver.name = "";
+-
+-#ifdef SERIAL_DEBUG_PCI
+-      printk(KERN_DEBUG "Leaving probe_serial_pci() (probe finished)\n");
+-#endif
+-      return;
+-}
+-
+-#endif /* ENABLE_SERIAL_PCI */
+-
+-#ifdef ENABLE_SERIAL_PNP
+-
+-struct pnp_board {
+-      unsigned short vendor;
+-      unsigned short device;
+-};
+-
+-static struct pnp_board pnp_devices[] __devinitdata = {
+-      /* Archtek America Corp. */
+-      /* Archtek SmartLink Modem 3334BT Plug & Play */
+-      {       ISAPNP_VENDOR('A', 'A', 'C'), ISAPNP_DEVICE(0x000F) },
+-      /* Anchor Datacomm BV */
+-      /* SXPro 144 External Data Fax Modem Plug & Play */
+-      {       ISAPNP_VENDOR('A', 'D', 'C'), ISAPNP_DEVICE(0x0001) },
+-      /* SXPro 288 External Data Fax Modem Plug & Play */
+-      {       ISAPNP_VENDOR('A', 'D', 'C'), ISAPNP_DEVICE(0x0002) },
+-      /* Rockwell 56K ACF II Fax+Data+Voice Modem */
+-      {       ISAPNP_VENDOR('A', 'K', 'Y'), ISAPNP_DEVICE(0x1021) },
+-      /* AZT3005 PnP SOUND DEVICE */
+-      {       ISAPNP_VENDOR('A', 'Z', 'T'), ISAPNP_DEVICE(0x4001) },
+-      /* Best Data Products Inc. Smart One 336F PnP Modem */
+-      {       ISAPNP_VENDOR('B', 'D', 'P'), ISAPNP_DEVICE(0x3336) },
+-      /*  Boca Research */
+-      /* Boca Complete Ofc Communicator 14.4 Data-FAX */
+-      {       ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x0A49) },
+-      /* Boca Research 33,600 ACF Modem */
+-      {       ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x1400) },
+-      /* Boca 33.6 Kbps Internal FD34FSVD */
+-      {       ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x3400) },
+-      /* Boca 33.6 Kbps Internal FD34FSVD */
+-      {       ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x0A49) },
+-      /* Best Data Products Inc. Smart One 336F PnP Modem */
+-      {       ISAPNP_VENDOR('B', 'D', 'P'), ISAPNP_DEVICE(0x3336) },
+-      /* Computer Peripherals Inc */
+-      /* EuroViVa CommCenter-33.6 SP PnP */
+-      {       ISAPNP_VENDOR('C', 'P', 'I'), ISAPNP_DEVICE(0x4050) },
+-      /* Creative Labs */
+-      /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */
+-      {       ISAPNP_VENDOR('C', 'T', 'L'), ISAPNP_DEVICE(0x3001) },
+-      /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
+-      {       ISAPNP_VENDOR('C', 'T', 'L'), ISAPNP_DEVICE(0x3011) },
+-      /* Creative */
+-      /* Creative Modem Blaster Flash56 DI5601-1 */
+-      {       ISAPNP_VENDOR('D', 'M', 'B'), ISAPNP_DEVICE(0x1032) },
+-      /* Creative Modem Blaster V.90 DI5660 */
+-      {       ISAPNP_VENDOR('D', 'M', 'B'), ISAPNP_DEVICE(0x2001) },
+-      /* FUJITSU */
+-      /* Fujitsu 33600 PnP-I2 R Plug & Play */
+-      {       ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0202) },
+-      /* Fujitsu FMV-FX431 Plug & Play */
+-      {       ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0205) },
+-      /* Fujitsu 33600 PnP-I4 R Plug & Play */
+-      {       ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0206) },
+-      /* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */
+-      {       ISAPNP_VENDOR('F', 'U', 'J'), ISAPNP_DEVICE(0x0209) },
+-      /* Archtek America Corp. */
+-      /* Archtek SmartLink Modem 3334BT Plug & Play */
+-      {       ISAPNP_VENDOR('G', 'V', 'C'), ISAPNP_DEVICE(0x000F) },
+-      /* Hayes */
+-      /* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */
+-      {       ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x0001) },
+-      /* Hayes Optima 336 V.34 + FAX + Voice PnP */
+-      {       ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x000C) },
+-      /* Hayes Optima 336B V.34 + FAX + Voice PnP */
+-      {       ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x000D) },
+-      /* Hayes Accura 56K Ext Fax Modem PnP */
+-      {       ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x5670) },
+-      /* Hayes Accura 56K Ext Fax Modem PnP */
+-      {       ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x5674) },
+-      /* Hayes Accura 56K Fax Modem PnP */
+-      {       ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0x5675) },
+-      /* Hayes 288, V.34 + FAX */
+-      {       ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0xF000) },
+-      /* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */
+-      {       ISAPNP_VENDOR('H', 'A', 'Y'), ISAPNP_DEVICE(0xF001) },
+-      /* IBM */
+-      /* IBM Thinkpad 701 Internal Modem Voice */
+-      {       ISAPNP_VENDOR('I', 'B', 'M'), ISAPNP_DEVICE(0x0033) },
+-      /* Intertex */
+-      /* Intertex 28k8 33k6 Voice EXT PnP */
+-      {       ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xC801) },
+-      /* Intertex 33k6 56k Voice EXT PnP */
+-      {       ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xC901) },
+-      /* Intertex 28k8 33k6 Voice SP EXT PnP */
+-      {       ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xD801) },
+-      /* Intertex 33k6 56k Voice SP EXT PnP */
+-      {       ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xD901) },
+-      /* Intertex 28k8 33k6 Voice SP INT PnP */
+-      {       ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xF401) },
+-      /* Intertex 28k8 33k6 Voice SP EXT PnP */
+-      {       ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xF801) },
+-      /* Intertex 33k6 56k Voice SP EXT PnP */
+-      {       ISAPNP_VENDOR('I', 'X', 'D'), ISAPNP_DEVICE(0xF901) },
+-      /* Kortex International */
+-      /* KORTEX 28800 Externe PnP */
+-      {       ISAPNP_VENDOR('K', 'O', 'R'), ISAPNP_DEVICE(0x4522) },
+-      /* KXPro 33.6 Vocal ASVD PnP */
+-      {       ISAPNP_VENDOR('K', 'O', 'R'), ISAPNP_DEVICE(0xF661) },
+-      /* Lasat */
+-      /* LASAT Internet 33600 PnP */
+-      {       ISAPNP_VENDOR('L', 'A', 'S'), ISAPNP_DEVICE(0x4040) },
+-      /* Lasat Safire 560 PnP */
+-      {       ISAPNP_VENDOR('L', 'A', 'S'), ISAPNP_DEVICE(0x4540) },
+-      /* Lasat Safire 336  PnP */
+-      {       ISAPNP_VENDOR('L', 'A', 'S'), ISAPNP_DEVICE(0x5440) },
+-      /* Microcom, Inc. */
+-      /* Microcom TravelPorte FAST V.34 Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x281) },
+-      /* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0336) },
+-      /* Microcom DeskPorte FAST EP 28.8 Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0339) },
+-      /* Microcom DeskPorte 28.8P Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0342) },
+-      /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0500) },
+-      /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0501) },
+-      /* Microcom DeskPorte 28.8S Internal Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'N', 'P'), ISAPNP_DEVICE(0x0502) },
+-      /* Motorola */
+-      /* Motorola BitSURFR Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1105) },
+-      /* Motorola TA210 Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1111) },
+-      /* Motorola HMTA 200 (ISDN) Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1114) },
+-      /* Motorola BitSURFR Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1115) },
+-      /* Motorola Lifestyle 28.8 Internal */
+-      {       ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1190) },
+-      /* Motorola V.3400 Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1501) },
+-      /* Motorola Lifestyle 28.8 V.34 Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1502) },
+-      /* Motorola Power 28.8 V.34 Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1505) },
+-      /* Motorola ModemSURFR External 28.8 Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1509) },
+-      /* Motorola Premier 33.6 Desktop Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x150A) },
+-      /* Motorola VoiceSURFR 56K External PnP */
+-      {       ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x150F) },
+-      /* Motorola ModemSURFR 56K External PnP */
+-      {       ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1510) },
+-      /* Motorola ModemSURFR 56K Internal PnP */
+-      {       ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1550) },
+-      /* Motorola ModemSURFR Internal 28.8 Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1560) },
+-      /* Motorola Premier 33.6 Internal Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x1580) },
+-      /* Motorola OnlineSURFR 28.8 Internal Plug & Play */
+-      {       ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x15B0) },
+-      /* Motorola VoiceSURFR 56K Internal PnP */
+-      {       ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x15F0) },
+-      /* Com 1 */
+-      /*  Deskline K56 Phone System PnP */
+-      {       ISAPNP_VENDOR('M', 'V', 'X'), ISAPNP_DEVICE(0x00A1) },
+-      /* PC Rider K56 Phone System PnP */
+-      {       ISAPNP_VENDOR('M', 'V', 'X'), ISAPNP_DEVICE(0x00F2) },
+-      /* Pace 56 Voice Internal Plug & Play Modem */
+-      {       ISAPNP_VENDOR('P', 'M', 'C'), ISAPNP_DEVICE(0x2430) },
+-      /* Generic */
+-      /* Generic standard PC COM port  */
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0500) },
+-      /* Generic 16550A-compatible COM port */
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0501) },
+-      /* Compaq 14400 Modem */
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC000) },
+-      /* Compaq 2400/9600 Modem */
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC001) },
+-      /* Dial-Up Networking Serial Cable between 2 PCs */
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC031) },
+-      /* Dial-Up Networking Parallel Cable between 2 PCs */
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC032) },
+-      /* Standard 9600 bps Modem */
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC100) },
+-      /* Standard 14400 bps Modem */
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC101) },
+-      /*  Standard 28800 bps Modem*/
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC102) },
+-      /*  Standard Modem*/
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC103) },
+-      /*  Standard 9600 bps Modem*/
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC104) },
+-      /*  Standard 14400 bps Modem*/
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC105) },
+-      /*  Standard 28800 bps Modem*/
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC106) },
+-      /*  Standard Modem */
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC107) },
+-      /* Standard 9600 bps Modem */
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC108) },
+-      /* Standard 14400 bps Modem */
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC109) },
+-      /* Standard 28800 bps Modem */
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10A) },
+-      /* Standard Modem */
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10B) },
+-      /* Standard 9600 bps Modem */
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10C) },
+-      /* Standard 14400 bps Modem */
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10D) },
+-      /* Standard 28800 bps Modem */
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10E) },
+-      /* Standard Modem */
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC10F) },
+-      /* Standard PCMCIA Card Modem */
+-      {       ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x2000) },
+-      /* Rockwell */
+-      /* Modular Technology */
+-      /* Rockwell 33.6 DPF Internal PnP */
+-      /* Modular Technology 33.6 Internal PnP */
+-      {       ISAPNP_VENDOR('R', 'O', 'K'), ISAPNP_DEVICE(0x0030) },
+-      /* Kortex International */
+-      /* KORTEX 14400 Externe PnP */
+-      {       ISAPNP_VENDOR('R', 'O', 'K'), ISAPNP_DEVICE(0x0100) },
+-      /* Viking Components, Inc */
+-      /* Viking 28.8 INTERNAL Fax+Data+Voice PnP */
+-      {       ISAPNP_VENDOR('R', 'O', 'K'), ISAPNP_DEVICE(0x4920) },
+-      /* Rockwell */
+-      /* British Telecom */
+-      /* Modular Technology */
+-      /* Rockwell 33.6 DPF External PnP */
+-      /* BT Prologue 33.6 External PnP */
+-      /* Modular Technology 33.6 External PnP */
+-      {       ISAPNP_VENDOR('R', 'S', 'S'), ISAPNP_DEVICE(0x00A0) },
+-      /* Viking 56K FAX INT */
+-      {       ISAPNP_VENDOR('R', 'S', 'S'), ISAPNP_DEVICE(0x0262) },
+-      /* SupraExpress 28.8 Data/Fax PnP modem */
+-      {       ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1310) },
+-      /* SupraExpress 33.6 Data/Fax PnP modem */
+-      {       ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1421) },
+-      /* SupraExpress 33.6 Data/Fax PnP modem */
+-      {       ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1590) },
+-      /* SupraExpress 33.6 Data/Fax PnP modem */
+-      {       ISAPNP_VENDOR('S', 'U', 'P'), ISAPNP_DEVICE(0x1760) },
+-      /* Phoebe Micro */
+-      /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */
+-      {       ISAPNP_VENDOR('T', 'E', 'X'), ISAPNP_DEVICE(0x0011) },
+-      /* Archtek America Corp. */
+-      /* Archtek SmartLink Modem 3334BT Plug & Play */
+-      {       ISAPNP_VENDOR('U', 'A', 'C'), ISAPNP_DEVICE(0x000F) },
+-      /* 3Com Corp. */
+-      /* Gateway Telepath IIvi 33.6 */
+-      {       ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0000) },
+-      /*  Sportster Vi 14.4 PnP FAX Voicemail */
+-      {       ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0004) },
+-      /* U.S. Robotics 33.6K Voice INT PnP */
+-      {       ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0006) },
+-      /* U.S. Robotics 33.6K Voice EXT PnP */
+-      {       ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x0007) },
+-      /* U.S. Robotics 33.6K Voice INT PnP */
+-      {       ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x2002) },
+-      /* U.S. Robotics 56K Voice INT PnP */
+-      {       ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x2070) },
+-      /* U.S. Robotics 56K Voice EXT PnP */
+-      {       ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x2080) },
+-      /* U.S. Robotics 56K FAX INT */
+-      {       ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3031) },
+-      /* U.S. Robotics 56K Voice INT PnP */
+-      {       ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3070) },
+-      /* U.S. Robotics 56K Voice EXT PnP */
+-      {       ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3080) },
+-      /* U.S. Robotics 56K Voice INT PnP */
+-      {       ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x3090) },
+-      /* U.S. Robotics 56K Message  */
+-      {       ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9100) },
+-      /*  U.S. Robotics 56K FAX EXT PnP*/
+-      {       ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9160) },
+-      /*  U.S. Robotics 56K FAX INT PnP*/
+-      {       ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9170) },
+-      /*  U.S. Robotics 56K Voice EXT PnP*/
+-      {       ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9180) },
+-      /*  U.S. Robotics 56K Voice INT PnP*/
+-      {       ISAPNP_VENDOR('U', 'S', 'R'), ISAPNP_DEVICE(0x9190) },
+-      {       0, }
+-};
+-
+-static inline void avoid_irq_share(struct pci_dev *dev)
+-{
+-      int i, map = 0x1FF8;
+-      struct serial_state *state = rs_table;
+-      struct isapnp_irq *irq;
+-      struct isapnp_resources *res = dev->sysdata;
+-
+-      for (i = 0; i < NR_PORTS; i++) {
+-              if (state->type != PORT_UNKNOWN)
+-                      clear_bit(state->irq, &map);
+-              state++;
+-      }
+-
+-      for ( ; res; res = res->alt)
+-              for(irq = res->irq; irq; irq = irq->next)
+-                      irq->map = map;
+-}
+-
+-static char *modem_names[] __devinitdata = {
+-       "MODEM", "Modem", "modem", "FAX", "Fax", "fax",
+-       "56K", "56k", "K56", "33.6", "28.8", "14.4",
+-       "33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
+-       "33600", "28800", "14400", "V.90", "V.34", "V.32", 0
+-};
+-
+-static int __devinit check_name(char *name)
+-{
+-       char **tmp = modem_names;
+-
+-       while (*tmp) {
+-               if (strstr(name, *tmp))
+-                       return 1;
+-               tmp++;
++        if (!request_mem_region(RAMSES_UARTC_PHYS, 16*4, "Ramses UART C"))
++                printk(KERN_ERR "unable to reserve region\n");
++        else {
++                ramses_uartc = ioremap_nocache(RAMSES_UARTC_PHYS, 16*4);
++                if (!ramses_uartc)
++                        printk(KERN_ERR "unable to map region\n");
++                else {
++                      //printk("ramses_uartc cookie is: %08x\n", (unsigned int) ramses_uartc);
++                      rs_table[5].iomem_base = ramses_uartc;
+        }
+-       return 0;
+-}
+-
+-static inline int check_compatible_id(struct pci_dev *dev)
+-{
+-       int i;
+-       for (i = 0; i < DEVICE_COUNT_COMPATIBLE; i++)
+-             if ((dev->vendor_compatible[i] ==
+-                  ISAPNP_VENDOR('P', 'N', 'P')) &&
+-                 (swab16(dev->device_compatible[i]) >= 0xc000) &&
+-                 (swab16(dev->device_compatible[i]) <= 0xdfff))
+-                     return 0;
+-       return 1;
+-}
+-
+-/*
+- * Given a complete unknown ISA PnP device, try to use some heuristics to
+- * detect modems. Currently use such heuristic set:
+- *     - dev->name or dev->bus->name must contain "modem" substring;
+- *     - device must have only one IO region (8 byte long) with base adress
+- *       0x2e8, 0x3e8, 0x2f8 or 0x3f8.
+- *
+- * Such detection looks very ugly, but can detect at least some of numerous
+- * ISA PnP modems, alternatively we must hardcode all modems in pnp_devices[]
+- * table.
+- */
+-static int _INLINE_ serial_pnp_guess_board(struct pci_dev *dev,
+-                                        struct pci_board *board)
+-{
+-       struct isapnp_resources *res = (struct isapnp_resources *)dev->sysdata;
+-       struct isapnp_resources *resa;
+-
+-       if (!(check_name(dev->name) || check_name(dev->bus->name)) &&
+-         !(check_compatible_id(dev)))
+-             return 1;
+-
+-       if (!res || res->next)
+-             return 1;
+-
+-       for (resa = res->alt; resa; resa = resa->alt) {
+-             struct isapnp_port *port;
+-             for (port = res->port; port; port = port->next)
+-                     if ((port->size == 8) &&
+-                         ((port->min == 0x2f8) ||
+-                          (port->min == 0x3f8) ||
+-                          (port->min == 0x2e8) ||
+-                          (port->min == 0x3e8)))
+-                             return 0;
+        }
+-
+-       return 1;
+-}
+-
+-static void __devinit probe_serial_pnp(void)
+-{
+-       struct pci_dev *dev = NULL;
+-       struct pnp_board *pnp_board;
+-       struct pci_board board;
+-
+-#ifdef SERIAL_DEBUG_PNP
+-       printk("Entered probe_serial_pnp()\n");
+-#endif
+-       if (!isapnp_present()) {
+-#ifdef SERIAL_DEBUG_PNP
+-               printk("Leaving probe_serial_pnp() (no isapnp)\n");
+-#endif
+-               return;
++        if (!request_mem_region(RAMSES_UARTD_PHYS, 16*4, "Ramses UART D"))
++                printk(KERN_ERR "unable to reserve region\n");
++        else {
++                ramses_uartd = ioremap_nocache(RAMSES_UARTD_PHYS, 16*4);
++                if (!ramses_uartd)
++                        printk(KERN_ERR "unable to map region\n");
++                else {
++                      //printk("ramses_uartd cookie is: %08x\n", (unsigned int) ramses_uartd);
++                      rs_table[6].iomem_base = ramses_uartd;
+        }
+-
+-       isapnp_for_each_dev(dev) {
+-             if (dev->active)
+-                     continue;
+-
+-             memset(&board, 0, sizeof(board));
+-             board.flags = SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT;
+-             board.num_ports = 1;
+-             board.base_baud = 115200;
+-             
+-             for (pnp_board = pnp_devices; pnp_board->vendor; pnp_board++)
+-                     if ((dev->vendor == pnp_board->vendor) &&
+-                         (dev->device == pnp_board->device))
+-                             break;
+-
+-             if (pnp_board->vendor) {
+-                     /* Special case that's more efficient to hardcode */
+-                     if ((pnp_board->vendor == ISAPNP_VENDOR('A', 'K', 'Y') &&
+-                          pnp_board->device == ISAPNP_DEVICE(0x1021)))
+-                             board.flags |= SPCI_FL_NO_SHIRQ;
+-             } else {
+-                     if (serial_pnp_guess_board(dev, &board))
+-                             continue;
+              }
+-             
+-             if (board.flags & SPCI_FL_NO_SHIRQ)
+-                     avoid_irq_share(dev);
+-             start_pci_pnp_board(dev, &board);
+-       }
+-
+-#ifdef SERIAL_DEBUG_PNP
+-       printk("Leaving probe_serial_pnp() (probe finished)\n");
+-#endif
+-       return;
+-}
+-
+-#endif /* ENABLE_SERIAL_PNP */
+-
+-/*
+- * The serial driver boot-time initialization code!
+- */
+-static int __init rs_init(void)
+-{
+-      int i;
+-      struct serial_state * state;
+-
+       init_bh(SERIAL_BH, do_serial_bh);
+       init_timer(&serial_timer);
+       serial_timer.function = rs_timer;
+@@ -5463,10 +2723,6 @@
+       for (i = 0; i < NR_IRQS; i++) {
+               IRQ_ports[i] = 0;
+               IRQ_timeout[i] = 0;
+-#ifdef CONFIG_SERIAL_MULTIPORT
+-              memset(&rs_multiport[i], 0,
+-                     sizeof(struct rs_multiport_struct));
+-#endif
+       }
+ #ifdef CONFIG_SERIAL_CONSOLE
+       /*
+@@ -5480,29 +2736,25 @@
+                               rs_table[i].irq = 0;
+       }
+ #endif
+-      show_serial_version();
+-
+       /* Initialize the tty_driver structure */
+       
+       memset(&serial_driver, 0, sizeof(struct tty_driver));
+       serial_driver.magic = TTY_DRIVER_MAGIC;
+-#if (LINUX_VERSION_CODE > 0x20100)
+       serial_driver.driver_name = "serial";
+-#endif
+-#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
++#if defined(CONFIG_DEVFS_FS)
+       serial_driver.name = "tts/%d";
+ #else
+       serial_driver.name = "ttyS";
+ #endif
+       serial_driver.major = TTY_MAJOR;
+-      serial_driver.minor_start = 64 + SERIAL_DEV_OFFSET;
+-      serial_driver.name_base = SERIAL_DEV_OFFSET;
++      serial_driver.minor_start = 64;
++      serial_driver.name_base = 0;
+       serial_driver.num = NR_PORTS;
+       serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
+       serial_driver.subtype = SERIAL_TYPE_NORMAL;
+       serial_driver.init_termios = tty_std_termios;
+       serial_driver.init_termios.c_cflag =
+-              B9600 | CS8 | CREAD | HUPCL | CLOCAL;
++              B115200 | CS8 | CREAD | HUPCL | CLOCAL;
+       serial_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+       serial_driver.refcount = &serial_refcount;
+       serial_driver.table = serial_table;
+@@ -5524,31 +2776,25 @@
+       serial_driver.stop = rs_stop;
+       serial_driver.start = rs_start;
+       serial_driver.hangup = rs_hangup;
+-#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
+       serial_driver.break_ctl = rs_break;
+-#endif
+-#if (LINUX_VERSION_CODE >= 131343)
+       serial_driver.send_xchar = rs_send_xchar;
+       serial_driver.wait_until_sent = rs_wait_until_sent;
+       serial_driver.read_proc = rs_read_proc;
+-#endif
+       
+       /*
+        * The callout device is just like normal device except for
+        * major number and the subtype code.
+        */
+       callout_driver = serial_driver;
+-#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
++#if defined(CONFIG_DEVFS_FS)
+       callout_driver.name = "cua/%d";
+ #else
+       callout_driver.name = "cua";
+ #endif
+       callout_driver.major = TTYAUX_MAJOR;
+       callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+-#if (LINUX_VERSION_CODE >= 131343)
+       callout_driver.read_proc = 0;
+       callout_driver.proc_entry = 0;
+-#endif
+       if (tty_register_driver(&serial_driver))
+               panic("Couldn't register serial driver\n");
+@@ -5569,53 +2815,23 @@
+               state->icount.frame = state->icount.parity = 0;
+               state->icount.overrun = state->icount.brk = 0;
+               state->irq = irq_cannonicalize(state->irq);
+-              if (state->hub6)
+-                      state->io_type = SERIAL_IO_HUB6;
+               if (state->port && check_region(state->port,8)) {
+                       state->type = PORT_UNKNOWN;
+                       continue;
+               }
+-#ifdef CONFIG_MCA                     
+-              if ((state->flags & ASYNC_BOOT_ONLYMCA) && !MCA_bus)
+-                      continue;
+-#endif                        
+-              if (state->flags & ASYNC_BOOT_AUTOCONF) {
+-                      state->type = PORT_UNKNOWN;
+-                      autoconfig(state);
+-              }
+       }
+       for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
+               if (state->type == PORT_UNKNOWN)
+                       continue;
+-              if (   (state->flags & ASYNC_BOOT_AUTOCONF)
+-                  && (state->flags & ASYNC_AUTO_IRQ)
+-                  && (state->port != 0 || state->iomem_base != 0))
+-                      state->irq = detect_uart_irq(state);
+-              if (state->io_type == SERIAL_IO_MEM) {
+-                      printk(KERN_INFO"ttyS%02d%s at 0x%p (irq = %d) is a %s\n",
+-                             state->line + SERIAL_DEV_OFFSET,
+-                             (state->flags & ASYNC_FOURPORT) ? " FourPort" : "",
+-                             state->iomem_base, state->irq,
+-                             uart_config[state->type].name);
+-              }
+-              else {
+-                      printk(KERN_INFO "ttyS%02d%s at 0x%04lx (irq = %d) is a %s\n",
+-                             state->line + SERIAL_DEV_OFFSET,
+-                             (state->flags & ASYNC_FOURPORT) ? " FourPort" : "",
+-                             state->port, state->irq,
++              printk(KERN_INFO"tts/%d at irq %d is a %s\n",
++                     state->line,
++                     state->irq,
+                              uart_config[state->type].name);
+-              }
+               tty_register_devfs(&serial_driver, 0,
+                                  serial_driver.minor_start + state->line);
+               tty_register_devfs(&callout_driver, 0,
+                                  callout_driver.minor_start + state->line);
+       }
+-#ifdef ENABLE_SERIAL_PCI
+-      probe_serial_pci();
+-#endif
+-#ifdef ENABLE_SERIAL_PNP
+-       probe_serial_pnp();
+-#endif
+       return 0;
+ }
+@@ -5627,6 +2843,8 @@
+ {
+       int i = req->line;
++      printk("%s\n", __FUNCTION__);
++
+       if (i >= NR_IRQS)
+               return(-ENOENT);
+       rs_table[i].magic = 0;
+@@ -5639,7 +2857,6 @@
+       rs_table[i].flags = req->flags;
+       rs_table[i].close_delay = req->close_delay;
+       rs_table[i].io_type = req->io_type;
+-      rs_table[i].hub6 = req->hub6;
+       rs_table[i].iomem_base = req->iomem_base;
+       rs_table[i].iomem_reg_shift = req->iomem_reg_shift;
+       rs_table[i].type = req->type;
+@@ -5726,7 +2943,6 @@
+               info->iomem_base = req->iomem_base;
+               info->iomem_reg_shift = req->iomem_reg_shift;
+       }
+-      autoconfig(state);
+       if (state->type == PORT_UNKNOWN) {
+               restore_flags(flags);
+               printk("register_serial(): autoconfig failed\n");
+@@ -5734,11 +2950,8 @@
+       }
+       restore_flags(flags);
+-      if ((state->flags & ASYNC_AUTO_IRQ) && CONFIGURED_SERIAL_PORT(state))
+-              state->irq = detect_uart_irq(state);
+-
+        printk(KERN_INFO "ttyS%02d at %s 0x%04lx (irq = %d) is a %s\n",
+-            state->line + SERIAL_DEV_OFFSET,
++            state->line,
+             state->iomem_base ? "iomem" : "port",
+             state->iomem_base ? (unsigned long)state->iomem_base :
+             state->port, state->irq, uart_config[state->type].name);
+@@ -5746,7 +2959,7 @@
+                          serial_driver.minor_start + state->line); 
+       tty_register_devfs(&callout_driver, 0,
+                          callout_driver.minor_start + state->line);
+-      return state->line + SERIAL_DEV_OFFSET;
++      return state->line;
+ }
+ /**
+@@ -5785,7 +2998,6 @@
+       int i;
+       struct async_struct *info;
+-      /* printk("Unloading %s: version %s\n", serial_name, serial_version); */
+       del_timer_sync(&serial_timer);
+       save_flags(flags); cli();
+         remove_bh(SERIAL_BH);
+@@ -5803,41 +3015,31 @@
+                       kfree(info);
+               }
+               if ((rs_table[i].type != PORT_UNKNOWN) && rs_table[i].port) {
+-#ifdef CONFIG_SERIAL_RSA
+-                      if (rs_table[i].type == PORT_RSA)
+-                              release_region(rs_table[i].port +
+-                                             UART_RSA_BASE, 16);
+-                      else
+-#endif
+                               release_region(rs_table[i].port, 8);
+               }
+-#if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP)
+-              if (rs_table[i].iomem_base)
+-                      iounmap(rs_table[i].iomem_base);
+-#endif
+-      }
+-#if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP)
+-      for (i=0; i < NR_PCI_BOARDS; i++) {
+-              struct pci_board_inst *brd = &serial_pci_board[i];
+-
+-              if (serial_pci_board[i].dev == 0)
+-                      continue;
+-              if (brd->board.init_fn)
+-                      (brd->board.init_fn)(brd->dev, &brd->board, 0);
+-              if (DEACTIVATE_FUNC(brd->dev))
+-                      (DEACTIVATE_FUNC(brd->dev))(brd->dev);
+       }
+-#endif        
+       if (tmp_buf) {
+               unsigned long pg = (unsigned long) tmp_buf;
+               tmp_buf = NULL;
+               free_page(pg);
+       }
+       
+-#ifdef ENABLE_SERIAL_PCI
+-      if (serial_pci_driver.name[0])
+-              pci_unregister_driver (&serial_pci_driver);
+-#endif
++      if (ramses_uarta) {
++              iounmap(ramses_uarta);
++              release_mem_region(RAMSES_UARTA_PHYS, 16*4);
++      }
++      if (ramses_uartb) {
++              iounmap(ramses_uartb);
++              release_mem_region(RAMSES_UARTB_PHYS, 16*4);
++      }
++      if (ramses_uartc) {
++              iounmap(ramses_uartc);
++              release_mem_region(RAMSES_UARTC_PHYS, 16*4);
++      }
++      if (ramses_uartd) {
++              iounmap(ramses_uartd);
++              release_mem_region(RAMSES_UARTD_PHYS, 16*4);
++      }
+ }
+ module_init(rs_init);
+@@ -5946,7 +3148,7 @@
+       static struct async_struct *info;
+       struct serial_state *state;
+       unsigned cval;
+-      int     baud = 9600;
++      int     baud = 115200;
+       int     bits = 8;
+       int     parity = 'n';
+       int     doflow = 0;
+@@ -5954,6 +3156,8 @@
+       int     quot = 0;
+       char    *s;
++      printk("%s\n", __FUNCTION__);
++
+       if (options) {
+               baud = simple_strtoul(options, NULL, 10);
+               s = options;
+@@ -6028,19 +3232,12 @@
+       info->state = state;
+       info->port = state->port;
+       info->flags = state->flags;
+-#ifdef CONFIG_HUB6
+-      info->hub6 = state->hub6;
+-#endif
+       info->io_type = state->io_type;
+       info->iomem_base = state->iomem_base;
+       info->iomem_reg_shift = state->iomem_reg_shift;
+       quot = state->baud_base / baud;
+       cval = cflag & (CSIZE | CSTOPB);
+-#if defined(__powerpc__) || defined(__alpha__)
+-      cval >>= 8;
+-#else /* !__powerpc__ && !__alpha__ */
+       cval >>= 4;
+-#endif /* !__powerpc__ && !__alpha__ */
+       if (cflag & PARENB)
+               cval |= UART_LCR_PARITY;
+       if (!(cflag & PARODD))
+@@ -6082,9 +3279,14 @@
+  */
+ void __init serial_console_init(void)
+ {
++      printk("%s\n", __FUNCTION__);
++
+       register_console(&sercons);
+ }
+ #endif
++
++EXPORT_SYMBOL(register_serial);
++EXPORT_SYMBOL(unregister_serial);
+ /*
+   Local variables:
+--- /dev/null
++++ linux-2.4.21/drivers/char/sysctl.c
+@@ -0,0 +1,948 @@
++/*
++ *  /proc/sys-board - Interface to the 16 bit latch and other
++ *  ramses-related hardware settings
++ *
++ *  (C) 2002,2003 by M&N Logistik-Lösungen Online GmbH
++ *  written by H.Schurig
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/errno.h>
++#include <linux/sysctl.h>
++#include <linux/crc32.h>
++#include <linux/delay.h>
++#include <linux/pm.h>
++
++#include <asm/io.h>
++#include <asm/arch/ramses.h>
++#include <asm/uaccess.h>
++
++#include "../drivers/misc/ucb1x00.h"
++
++//#define DEBUG
++//define CPLD_LED 1
++//define POTI 1
++
++/*
++ * This is the number for the "board" entry in /proc/sys:
++ */
++#define RAMSES_SYSCTL 1312
++
++/*
++ * These are the numbers for the entries in /etc/sys/board
++ */
++enum {
++      CTL_NAME=991,
++      CTL_CPLD_VERSION,
++      CTL_BOOTLOADER_CRC,
++      CTL_LINUX_CRC,
++      CTL_LED_BLUE,
++      CTL_LED_ORANGE,
++      CTL_UART,
++      CTL_MMC,
++      CTL_POWEROFF,
++      CTL_GSM_POWER,
++      CTL_GSM_RESET,
++      CTL_SCANNER_POWER,
++      CTL_SCANNER_WAKE,
++      CTL_SCANNER_TRIG,
++      CTL_SCANNER_BEAM,
++      CTL_KEY_SCAN,
++      CTL_KEY_SUSPEND,
++      CTL_KEY_OFF,
++      CTL_USBBUS_POWER,
++      CTL_USBCHIP_POWER,
++#ifdef CPLD_LED
++      CTL_LED_CPLD,
++      CTL_LED_CPLD_RED,
++#endif
++      CTL_LCD_VCC,
++      CTL_LCD_DISPOFF,
++      CTL_LCD_BLIGHT,
++#ifdef DEBUG
++      CTL_LCD_PWM0,
++      CTL_LCD_PWM1,
++#endif
++      CTL_LCD_BRIGHTNESS,
++      CTL_LCD_CONTRAST,
++      CTL_LCD_FBTURN,
++      CTL_LCD_TYPE,
++      CTL_CONTROL_SHADOW,
++      CTL_COREVOLT,
++#ifdef POTI
++      CTL_LCD_POTI_NINC,
++      CTL_LCD_POTI_NCS,
++      CTL_LCD_POTI_UP,
++#endif
++#ifdef CONFIG_MCP_UCB1400_TS
++      CTL_ADC0,
++      CTL_ADC1,
++      CTL_ADC2,
++      CTL_ADC3,
++#else
++#error NO UCB
++#endif
++      CTL_CHG_STS,
++      CTL_WALL_IN,
++      CTL_BATT_TMP,
++      CTL_BATT_LMD,
++      CTL_BATT_VSB,
++      CTL_BATT_RCAC,
++      CTL_BATT_CACT,
++      CTL_BATT_SAE,
++      CTL_BATT_DCR,
++};
++
++static const char ramses_board_name[] = "ramses";
++static int dummy_int = 0;
++static char dummy_str[80];
++
++
++
++/******************************************************************/
++/*  ADC  communication                                            */
++/******************************************************************/
++
++
++#ifdef CONFIG_MCP_UCB1400_TS
++static int adc_get(int channel)
++{
++      int val;
++      struct ucb1x00 *ucb = ucb1x00_get();
++      
++      ucb1x00_adc_enable(ucb);
++      val = ucb1x00_adc_read(ucb, channel, 0);
++      ucb1x00_adc_disable(ucb);
++
++      return val;
++}
++#endif
++
++
++
++static int
++ramses_sysctl_handler(ctl_table * ctl, int write, struct file *filp,
++                 void *buffer, size_t * lenp)
++{
++      int *valp = ctl->data;
++      int val;
++      int ret;
++      unsigned crc;
++      void *flash;
++
++#ifdef DEBUG
++      printk("ramses_control_shadow: %04x\n", ramses_control_shadow);
++#endif
++
++      // Update parameters from the real registers
++      switch (ctl->ctl_name) {
++      case CTL_CPLD_VERSION:
++              sprintf(dummy_str,"20%02ld-%02ld-%02ld.%ld\n",
++                      RAMSES_CPLD_YEAR & 0xff,
++                      RAMSES_CPLD_MONTH & 0xff,
++                      RAMSES_CPLD_DAY & 0xff,
++                      RAMSES_CPLD_REV & 0xff);
++              return proc_dostring(ctl,write,filp,buffer,lenp);
++
++      case CTL_BOOTLOADER_CRC:
++              flash = ioremap_nocache(RAMSES_FLASH_PHYS, 0x40000);
++              crc = ether_crc_le(0x40000, flash);
++              iounmap(flash);
++              sprintf(dummy_str,"%08x", crc);
++              return proc_dostring(ctl,write,filp,buffer,lenp);
++
++      case CTL_LINUX_CRC:
++              flash = ioremap_nocache(RAMSES_FLASH_PHYS+0x40000, 3*0x40000);
++              crc = ether_crc_le(3*0x40000, flash);
++              iounmap(flash);
++              sprintf(dummy_str,"%08x", crc);
++              return proc_dostring(ctl,write,filp,buffer,lenp);
++
++      case CTL_LED_BLUE:
++              *valp = (ramses_control_shadow & RAMSES_CONTROL_LED_BLUE_) == 0;
++              break;
++      case CTL_LED_ORANGE:
++              *valp = (ramses_control_shadow & RAMSES_CONTROL_LED_ORANGE_) == 0;
++              break;
++      case CTL_UART:
++              *valp = (ramses_control_shadow & RAMSES_CONTROL_UART_PWR) != 0;
++              break;
++      case CTL_MMC:
++              *valp = (ramses_control_shadow & RAMSES_CONTROL_MMC_PWR) != 0;
++              break;
++      case CTL_POWEROFF:
++              *valp = 0;
++              break;
++      case CTL_GSM_POWER:
++              *valp = (ramses_control_shadow & RAMSES_CONTROL_GSM_PWR) != 0;
++              break;
++      case CTL_GSM_RESET:
++              *valp = (ramses_control_shadow & RAMSES_CONTROL_GSM_RESET) != 0;
++              break;
++
++      case CTL_SCANNER_POWER:
++              *valp = (ramses_control_shadow & RAMSES_CONTROL_SCANNER_PWR) != 0;
++              break;
++      case CTL_SCANNER_WAKE:
++              *valp = (ramses_control_shadow & RAMSES_CONTROL_SCANNER_WAKE_) == 0;
++              break;
++      case CTL_SCANNER_TRIG:
++              *valp = (ramses_control_shadow & RAMSES_CONTROL_SCANNER_TRIG_) == 0;
++              break;
++      case CTL_SCANNER_BEAM:
++              *valp = ramses_flags & RAMSES_FLAGS_SCANNER_BEAM;
++              break;
++
++      case CTL_KEY_SCAN:
++              *valp = (ramses_flags & RAMSES_FLAGS_KEY_SCAN) != 0;
++              break;
++      case CTL_KEY_SUSPEND:
++              *valp = (ramses_flags & RAMSES_FLAGS_KEY_SUSPEND) != 0;
++              break;
++      case CTL_KEY_OFF:
++              *valp = (ramses_flags & RAMSES_FLAGS_KEY_OFF) != 0;
++              break;
++
++      case CTL_USBBUS_POWER:
++              *valp = (ramses_control_shadow & RAMSES_CONTROL_USB) != 0;
++              break;
++      case CTL_USBCHIP_POWER:
++              *valp = (RAMSES_CPLD_PERIPH_PWR & USB_HOST_PWR_EN) != 0;
++              break;
++#ifdef CPLD_LED
++      case CTL_LED_CPLD:
++              *valp = (RAMSES_CPLD_LED_CONTROL & CPLD_LED1) == 0;
++              break;
++      case CTL_LED_CPLD_RED:
++              *valp = (RAMSES_CPLD_LED_CONTROL & CPLD_LED2) == 0;
++              break;
++#endif
++      case CTL_LCD_BLIGHT:
++              *valp = (ramses_control_shadow & RAMSES_CONTROL_LCD_BLIGHT) != 0;
++              break;
++      case CTL_LCD_VCC:
++              *valp = (RAMSES_CPLD_LCD & RAMSES_LCD_VCC) != 0;
++              break;
++      case CTL_LCD_DISPOFF:
++              *valp = (RAMSES_CPLD_LCD & RAMSES_LCD_DISPOFF) != 0;
++              break;
++#ifdef DEBUG
++      case CTL_LCD_PWM0:
++              *valp = PWM_PWDUTY0;
++              break;
++      case CTL_LCD_PWM1:
++#ifdef OLDCODE
++              *valp = ramses_lcd_pwm1_shadow;
++#else
++              *valp = PWM_PWDUTY1;
++#endif
++              break;
++#endif
++      case CTL_LCD_BRIGHTNESS:
++              *valp = ramses_lcd_get_brightness();
++              break;
++      case CTL_LCD_CONTRAST:
++              *valp = ramses_lcd_get_contrast();
++              break;
++      case CTL_LCD_FBTURN:
++              *valp = (ramses_flags & RAMSES_FLAGS_LCD_FBTURN) != 0;
++              break;
++      case CTL_LCD_TYPE:
++              *valp = ramses_lcd_type;
++              break;
++
++      case CTL_CONTROL_SHADOW:
++              sprintf(dummy_str,"%04x", ramses_control_shadow);
++              return proc_dostring(ctl,write,filp,buffer,lenp);
++
++      case CTL_COREVOLT:
++              *valp = ramses_corevolt_shadow;
++              break;
++
++#ifdef POTI
++      case CTL_LCD_POTI_NINC:
++              *valp = (RAMSES_CPLD_LCD & RAMSES_LCD_PINC) != 0;
++              break;
++      case CTL_LCD_POTI_NCS:
++              *valp = (RAMSES_CPLD_LCD & RAMSES_LCD_PCS) != 0;
++              break;
++      case CTL_LCD_POTI_UP:
++              *valp = (RAMSES_CPLD_LCD & RAMSES_LCD_PUP) != 0;
++              break;
++#endif
++
++#ifdef CONFIG_MCP_UCB1400_TS
++      case CTL_ADC0:
++              *valp = adc_get(UCB_ADC_INP_AD0);
++              break;
++      case CTL_ADC1:
++              *valp = adc_get(UCB_ADC_INP_AD1);
++              break;
++      case CTL_ADC2:
++              *valp = adc_get(UCB_ADC_INP_AD2);
++              break;
++      case CTL_ADC3:
++              *valp = adc_get(UCB_ADC_INP_AD3);
++              break;
++#endif
++
++      case CTL_CHG_STS:
++              *valp = (RAMSES_CPLD_MISC_STATUS & RAMSES_CHG_STS) == 0;
++              break;
++      case CTL_WALL_IN:
++              *valp = (RAMSES_CPLD_MISC_STATUS & RAMSES_WALL_IN) != 0;
++              break;
++
++      case CTL_BATT_TMP:
++              *valp = ramses_hdq_get_reg(HDQ_TMP) >> 4;
++              break;
++      case CTL_BATT_LMD:
++              *valp = ramses_hdq_get_reg(HDQ_LMD);
++              break;
++      case CTL_BATT_VSB:
++              *valp = ramses_hdq_get_reg(HDQ_VSB);
++              break;
++      case CTL_BATT_RCAC:
++              *valp = ramses_hdq_get_reg(HDQ_RCAC) & 0x7f;
++              break;
++      case CTL_BATT_CACT:
++              *valp = ramses_hdq_get_reg(HDQ_CACT);
++              break;
++      case CTL_BATT_SAE:
++              *valp = ramses_hdq_get_reg(HDQ_SAEH) << 8 | ramses_hdq_get_reg(HDQ_SAEL);
++              break;
++      case CTL_BATT_DCR:
++              *valp = ramses_hdq_get_reg(HDQ_DCR);
++              break;
++
++      default:
++              // Just ignore unsupported parameters
++              break;
++      }
++
++      // Save old state
++      val = *valp;
++
++      // Perform the generic integer operation        
++      if ((ret = proc_dointvec(ctl, write, filp, buffer, lenp)) != 0)
++              return (ret);
++
++      // Write changes out to the registers
++      if (write && *valp != val) {
++
++              val = *valp;
++              switch (ctl->ctl_name) {
++
++              case CTL_LED_BLUE:
++                      if (val)
++                              RAMSES_LED_BLUE_ON()
++                      else
++                              RAMSES_LED_BLUE_OFF();
++                      break;
++
++              case CTL_LED_ORANGE:
++                      if (val)
++                              RAMSES_LED_ORANGE_ON()
++                      else
++                              RAMSES_LED_ORANGE_OFF();
++                      break;
++
++              case CTL_UART:
++                      if (val)
++                              RAMSES_UART_ON()
++                      else
++                              RAMSES_UART_OFF();
++                      break;
++
++              case CTL_MMC:
++                      if (val)
++                              RAMSES_MMC_ON()
++                      else
++                              RAMSES_MMC_OFF();
++                      break;
++
++              case CTL_POWEROFF:
++                      if (val)
++                              pm_power_off();
++                      break;
++
++              case CTL_GSM_POWER:
++                      if (val)
++                              RAMSES_GSM_ON()
++                      else
++                              RAMSES_GSM_OFF();
++                      break;
++
++              case CTL_GSM_RESET:
++                      if (val)
++                              RAMSES_GSM_RESET_ON()
++                      else
++                              RAMSES_GSM_RESET_OFF();
++                      break;
++
++              case CTL_SCANNER_POWER:
++                      if (val)
++                              RAMSES_SCANNER_ON()
++                      else
++                              RAMSES_SCANNER_OFF();
++                      break;
++
++              case CTL_SCANNER_WAKE:
++                      if (val)
++                              RAMSES_SCANNER_WAKE_ON()
++                      else
++                              RAMSES_SCANNER_WAKE_OFF();
++                      break;
++
++              case CTL_SCANNER_TRIG:
++                      if (val)
++                              RAMSES_SCANNER_TRIG_ON()
++                      else
++                              RAMSES_SCANNER_TRIG_OFF();
++                      break;
++
++              case CTL_SCANNER_BEAM:
++                      if (val)
++                              ramses_flags |= RAMSES_FLAGS_SCANNER_BEAM;
++                      else
++                              ramses_flags &= ~RAMSES_FLAGS_SCANNER_BEAM;
++                      break;
++
++              case CTL_KEY_SCAN:
++                      if (val)
++                              ramses_flags |= RAMSES_FLAGS_KEY_SCAN;
++                      else
++                              ramses_flags &= ~RAMSES_FLAGS_KEY_SCAN;
++                      break;
++
++              case CTL_KEY_SUSPEND:
++                      if (val)
++                              ramses_flags |= RAMSES_FLAGS_KEY_SUSPEND;
++                      else
++                              ramses_flags &= ~RAMSES_FLAGS_KEY_SUSPEND;
++                      break;
++
++              case CTL_KEY_OFF:
++                      if (val)
++                              ramses_flags |= RAMSES_FLAGS_KEY_OFF;
++                      else
++                              ramses_flags &= ~RAMSES_FLAGS_KEY_OFF;
++                      break;
++
++              case CTL_USBBUS_POWER:
++                      if (val)
++                              RAMSES_USB_BUS_ON()
++                      else
++                              RAMSES_USB_BUS_OFF();
++                      break;
++
++              case CTL_USBCHIP_POWER:
++                      if (val)
++                              RAMSES_CPLD_PERIPH_PWR |= USB_HOST_PWR_EN;
++                      else
++                              RAMSES_CPLD_PERIPH_PWR &= ~USB_HOST_PWR_EN;
++                      break;
++
++#ifdef CPLD_LED
++              case CTL_LED_CPLD:
++                      if (val)
++                              RAMSES_CPLD_LED_CONTROL &= ~CPLD_LED1;
++                      else
++                              RAMSES_CPLD_LED_CONTROL |= CPLD_LED1;
++                      break;
++
++              case CTL_LED_CPLD_RED:
++                      if (val)
++                              RAMSES_CPLD_LED_CONTROL &= ~CPLD_LED2;
++                      else
++                              RAMSES_CPLD_LED_CONTROL |= CPLD_LED2;
++                      break;
++#endif
++
++              case CTL_LCD_BLIGHT:
++                      if (val)
++                              ramses_lcd_backlight_on();
++                      else
++                              ramses_lcd_backlight_off();
++                      break;
++
++              case CTL_LCD_VCC:
++                      if (val)
++                              RAMSES_CPLD_LCD |= RAMSES_LCD_VCC;
++                      else
++                              RAMSES_CPLD_LCD &= ~RAMSES_LCD_VCC;
++                      break;
++
++              case CTL_LCD_DISPOFF:
++                      if (val)
++                              RAMSES_CPLD_LCD |= RAMSES_LCD_DISPOFF;
++                      else
++                              RAMSES_CPLD_LCD &= ~RAMSES_LCD_DISPOFF;
++                      break;
++
++#ifdef DEBUG
++              case CTL_LCD_PWM0:
++                      PWM_PWDUTY0 = val;
++                      break;
++
++              case CTL_LCD_PWM1:
++#ifdef OLDCODE
++                      ramses_lcd_set_pwm1(val);
++#else
++                      PWM_PWDUTY1 = val;
++#endif
++                      break;
++#endif
++
++              case CTL_LCD_BRIGHTNESS:
++                      ramses_lcd_set_brightness(val);
++                      break;
++
++              case CTL_LCD_CONTRAST:
++                      ramses_lcd_set_contrast(val);
++                      break;
++
++              case CTL_LCD_FBTURN:
++                      if (val)
++                              ramses_flags |= RAMSES_FLAGS_LCD_FBTURN;
++                      else
++                              ramses_flags &= ~RAMSES_FLAGS_LCD_FBTURN;
++                      break;
++
++              case CTL_COREVOLT:
++                      ramses_set_corevolt(val);
++                      break;
++
++#ifdef POTI
++              case CTL_LCD_POTI_NCS:
++                      if (val)
++                              RAMSES_CPLD_LCD |= RAMSES_LCD_PCS;
++                      else
++                              RAMSES_CPLD_LCD &= ~RAMSES_LCD_PCS;
++                      break;
++              case CTL_LCD_POTI_NINC:
++                      if (val)
++                              RAMSES_CPLD_LCD |= RAMSES_LCD_PINC;
++                      else
++                              RAMSES_CPLD_LCD &= ~RAMSES_LCD_PINC;
++                      break;
++              case CTL_LCD_POTI_UP:
++                      if (val)
++                              RAMSES_CPLD_LCD |= RAMSES_LCD_PUP;
++                      else
++                              RAMSES_CPLD_LCD &= ~RAMSES_LCD_PUP;
++                      break;
++#endif
++
++              default:
++                      // Just ignore unsupported parameters
++                      break;
++              }
++      }
++
++#ifdef DEBUG
++      printk("ramses_control_shadow new: %04x\n", ramses_control_shadow);
++#endif
++      return ret;
++}
++
++
++
++static ctl_table ramses_table[] = {
++        {
++       procname:      "sys_name",
++       ctl_name:      CTL_NAME, 
++       data:          &ramses_board_name,
++       maxlen:        sizeof(ramses_board_name),
++         proc_handler:        &proc_dostring,
++       mode:          0444,           // read-only
++      }, {
++       procname:      "sys_cpldver",
++       ctl_name:      CTL_CPLD_VERSION, 
++       data:          &dummy_str,
++       maxlen:        sizeof(dummy_str),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0444,           // read-only
++      }, {
++       procname:      "sys_bootcrc",
++       ctl_name:      CTL_BOOTLOADER_CRC, 
++       data:          &dummy_str,
++       maxlen:        sizeof(dummy_str),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0444,           // read-only
++      }, {
++       procname:      "sys_linuxcrc",
++       ctl_name:      CTL_LINUX_CRC, 
++       data:          &dummy_str,
++       maxlen:        sizeof(dummy_str),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0444,           // read-only
++      }, {
++       procname:      "led_blue",
++       ctl_name:      CTL_LED_BLUE,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "led_orange",
++       ctl_name:      CTL_LED_ORANGE,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "pwr_uart",
++       ctl_name:      CTL_UART,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "pwr_mmc",
++       ctl_name:      CTL_MMC,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "pwr_off",
++       ctl_name:      CTL_POWEROFF,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "gsm_power",
++       ctl_name:      CTL_GSM_POWER,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "gsm_reset",
++       ctl_name:      CTL_GSM_RESET,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "scanner_power",
++       ctl_name:      CTL_SCANNER_POWER, 
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "scanner_wake",
++       ctl_name:      CTL_SCANNER_WAKE,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "scanner_trig",
++       ctl_name:      CTL_SCANNER_TRIG,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "scanner_beam",
++       ctl_name:      CTL_SCANNER_BEAM,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "key_scan",
++       ctl_name:      CTL_KEY_SCAN,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "key_suspend",
++       ctl_name:      CTL_KEY_SUSPEND,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "key_off",
++       ctl_name:      CTL_KEY_OFF,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "usb_bus_power",
++       ctl_name:      CTL_USBBUS_POWER,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "usb_chip_power",
++       ctl_name:      CTL_USBCHIP_POWER,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      },
++#if LED_CPLD
++      {
++       procname:      "led_cpld",
++       ctl_name:      CTL_LED_CPLD,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "led_cpld_red",
++       ctl_name:      CTL_LED_CPLD_RED,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, 
++#endif        
++      {
++       procname:      "lcd_backlight",
++       ctl_name:      CTL_LCD_BLIGHT,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "lcd_vcc",
++       ctl_name:      CTL_LCD_VCC,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "lcd_dispoff",
++       ctl_name:      CTL_LCD_DISPOFF,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "lcd_brightness",
++       ctl_name:      CTL_LCD_BRIGHTNESS,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "lcd_contrast",
++       ctl_name:      CTL_LCD_CONTRAST,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "lcd_fbturn",
++       ctl_name:      CTL_LCD_FBTURN,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "lcd_type",
++       ctl_name:      CTL_LCD_TYPE,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0444,
++      },
++#ifdef POTI
++      {
++       procname:      "lcd_poti_ncs",
++       ctl_name:      CTL_LCD_POTI_NCS,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "lcd_poti_ninc",
++       ctl_name:      CTL_LCD_POTI_NINC,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "lcd_poti_up",
++       ctl_name:      CTL_LCD_POTI_UP,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      },
++#endif
++#ifdef DEBUG
++      {
++       procname:      "lcd_pwm0",
++       ctl_name:      CTL_LCD_PWM0,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      }, {
++       procname:      "lcd_pwm1",
++       ctl_name:      CTL_LCD_PWM1,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      },
++#endif
++      {
++       procname:      "sys_shadowreg",
++       ctl_name:      CTL_CONTROL_SHADOW,
++       data:          &dummy_str,
++       maxlen:        sizeof(dummy_str),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0444,
++      },
++      {
++       procname:      "pwr_corevolt",
++       ctl_name:      CTL_COREVOLT,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0664,
++      },
++#ifdef CONFIG_MCP_UCB1400_TS
++      {
++       procname:      "adc0_vcc",
++       ctl_name:      CTL_ADC0,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0444,
++      }, {
++       procname:      "adc1_ntc",
++       ctl_name:      CTL_ADC1,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0444,
++      }, {
++       procname:      "adc2_goldcap",
++       ctl_name:      CTL_ADC2,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0444,
++      }, {
++       procname:      "adc3_batt",
++       ctl_name:      CTL_ADC3,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0444,
++      },
++#else
++#error No UCB
++#endif
++      {
++       procname:      "pwr_wall_in",
++       ctl_name:      CTL_WALL_IN,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0444,
++      }, {
++       procname:      "batt_charge",
++       ctl_name:      CTL_CHG_STS,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0444,
++      }, {
++       procname:      "batt_temp",
++       ctl_name:      CTL_BATT_TMP,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0444,
++      }, {
++       procname:      "batt_lmd",
++       ctl_name:      CTL_BATT_LMD,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0444,
++      }, {
++       procname:      "batt_vsb",
++       ctl_name:      CTL_BATT_VSB,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0444,
++      }, {
++       procname:      "batt_rcac",
++       ctl_name:      CTL_BATT_RCAC,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0444,
++      }, {
++       procname:      "batt_cact",
++       ctl_name:      CTL_BATT_CACT,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0444,
++      }, {
++       procname:      "batt_sae",
++       ctl_name:      CTL_BATT_SAE,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0444,
++      }, {
++       procname:      "batt_dcr",
++       ctl_name:      CTL_BATT_DCR,
++       data:          &dummy_int,
++       maxlen:        sizeof(int),
++         proc_handler:        &ramses_sysctl_handler,
++       mode:          0444,
++      },
++
++        {0}
++        };
++
++static ctl_table ramses_root_table[] = {
++        {RAMSES_SYSCTL, "board", NULL, 0, 0555, ramses_table},
++        {0}
++        };
++
++
++static struct ctl_table_header *ramses_table_header;
++
++
++static int __init ramses_sysctl_init(void) 
++{
++        ramses_table_header = register_sysctl_table(ramses_root_table, 0);
++        if (!ramses_table_header)
++                return -ENOMEM;
++        return 0;
++}
++
++static void __exit ramses_sysctl_exit(void)
++{
++        unregister_sysctl_table(ramses_table_header);
++}
++
++
++module_init(ramses_sysctl_init);
++module_exit(ramses_sysctl_exit);
++
++MODULE_AUTHOR("Holger Schurig <h.schurig@mn-logistik.de>");
++MODULE_DESCRIPTION("Implements /proc/sys/board");
++MODULE_LICENSE("GPL");
+--- linux-2.4.21/drivers/char/vt.c~linux-vtcomparison
++++ linux-2.4.21/drivers/char/vt.c
+@@ -163,7 +163,9 @@
+       if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
+               return -EFAULT;
+-      if (i >= NR_KEYS || s >= MAX_NR_KEYMAPS)
++      if (i >= NR_KEYS)
++              return -EINVAL;
++      if (s >= MAX_NR_KEYMAPS)
+               return -EINVAL; 
+       switch (cmd) {
+--- linux-2.4.21/drivers/input/Config.in~keyb-input
++++ linux-2.4.21/drivers/input/Config.in
+@@ -7,6 +7,8 @@
+ tristate 'Input core support' CONFIG_INPUT
+ dep_tristate '  Keyboard support' CONFIG_INPUT_KEYBDEV $CONFIG_INPUT
++dep_tristate '    Ramses keyboard' CONFIG_INPUT_RAMSES_KEYB $CONFIG_INPUT_KEYBDEV $CONFIG_ARCH_RAMSES
++dep_tristate '    Ramses wedge' CONFIG_INPUT_RAMSES_WEDGE $CONFIG_INPUT_RAMSES_KEYB
+ dep_tristate '  Mouse support' CONFIG_INPUT_MOUSEDEV $CONFIG_INPUT
+ if [ "$CONFIG_INPUT_MOUSEDEV" != "n" ]; then
+    int '   Horizontal screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024
+--- linux-2.4.21/drivers/input/Makefile~ramses-keyb
++++ linux-2.4.21/drivers/input/Makefile
+@@ -8,7 +8,7 @@
+ # Objects that export symbols.
+-export-objs   := input.o
++export-objs   := input.o ramses_keyb.o
+ # Object file lists.
+@@ -21,10 +21,12 @@
+ obj-$(CONFIG_INPUT)           += input.o
+ obj-$(CONFIG_INPUT_KEYBDEV)   += keybdev.o
++obj-$(CONFIG_INPUT_RAMSES_KEYB)       += ramses_keyb.o
+ obj-$(CONFIG_INPUT_MOUSEDEV)  += mousedev.o
+ obj-$(CONFIG_INPUT_JOYDEV)    += joydev.o
+ obj-$(CONFIG_INPUT_EVDEV)     += evdev.o
+ obj-$(CONFIG_INPUT_MX1TS)     += mx1ts.o
++obj-$(CONFIG_INPUT_RAMSES_WEDGE) += wedge.o
+ # The global Rules.make.
+--- /dev/null
++++ linux-2.4.21/drivers/input/ramses_cellmap.h
+@@ -0,0 +1,34 @@
++static int ramses_cellmap[][8] = {
++   { KEY_A,     KEY_B,     KEY_C,     KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 0
++   { KEY_D,     KEY_E,     KEY_F,     KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 1
++   { KEY_G,     KEY_H,     KEY_I,     KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 2
++   { KEY_J,     KEY_K,     KEY_L,     KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 3
++   { KEY_M,     KEY_N,     KEY_O,     KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 4
++   { KEY_P,     KEY_Q,     KEY_R,     KEY_S,     KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 5
++   { KEY_T,     KEY_U,     KEY_V,     KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 6
++   { KEY_W,     KEY_X,     KEY_Y,     KEY_Z,     KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 7
++   { KEY_AE,    KEY_OE,    KEY_UE,    KEY_SZ,    KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 8
++   { KEY_sA,    KEY_sB,    KEY_sC,    KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 9
++   { KEY_sD,    KEY_sE,    KEY_sF,    KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 10
++   { KEY_sG,    KEY_sH,    KEY_sI,    KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 11
++   { KEY_sJ,    KEY_sK,    KEY_sL,    KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 12
++   { KEY_sM,    KEY_sN,    KEY_sO,    KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 13
++   { KEY_sP,    KEY_sQ,    KEY_sR,    KEY_sS,    KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 14
++   { KEY_sT,    KEY_sU,    KEY_sV,    KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 15
++   { KEY_sW,    KEY_sX,    KEY_sY,    KEY_sZ,    KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 16
++   { KEY_sAE,   KEY_sOE,   KEY_sUE,   KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 17
++   { KEY_COLON, KEY_FSLASH,KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 18
++   { KEY_SEMI,  KEY_BSLASH,KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 19
++   { KEY_COMMA, KEY_STAR,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 20
++   { KEY_UNDERL,KEY_EQUAL, KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 21
++   { KEY_PLUS,  KEY_MINUS, KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 22
++   { KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 24
++   { KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 24
++   { KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 25
++   { KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 26
++   { KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 27
++   { KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 28
++   { KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 29
++   { KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 30
++   { KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop,  KEY_noop },  // 31
++};
+--- /dev/null
++++ linux-2.4.21/drivers/input/ramses_keyb.c
+@@ -0,0 +1,596 @@
++/*
++ *  Keyboard driver using input layer
++ *
++ *  (C) 2002,2003 by M&N Logistik-Lösungen Online GmbH
++ *  written by H.Schurig
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/input.h>
++#include <linux/delay.h>
++
++#include <asm/keyboard.h>
++#include <asm/irq.h>
++#include <linux/keyboard.h>
++
++// Debug
++//#define DEBUG
++//#define DEBUG_DUMP_KEYSTATE
++#ifdef DEBUG
++#  define DPRINTK(fmt, args...)       printk("%s: " fmt, __FUNCTION__ , ## args)
++#  define PRINTK(fmt, args...)        printk(fmt, ## args)
++#else
++#  define DPRINTK(fmt, args...)
++#  define PRINTK(fmt, args...)
++#endif
++
++
++/*
++ * Timeouts
++ */
++#define SCANINTERVAL                  HZ/10
++#define TRIGOFFINTERVAL                       HZ*2
++#define CELLINTERVAL                  HZ+HZ/2
++#define MAPINTERVAL                   15*HZ
++#define SUSPEND_COUNTER                       40
++#define SUSPEND_LED_COUNTER           8
++#define SUSPEND_NOW                   0xffff
++#define KEYBD_MATRIX_SETTLING_TIME_US 100
++
++
++/*
++ * macros for matrix keyboard driver
++ */
++#define KEYBD_MATRIX_NUMBER_INPUTS            7
++#define KEYBD_MATRIX_NUMBER_OUTPUTS           14
++
++#define KEYBD_MATRIX_SET_OUTPUTS(outputs) \
++{\
++      RAMSES_CPLD_KB_COL_LOW = outputs;\
++      RAMSES_CPLD_KB_COL_HIGH = outputs >> 7;\
++}
++
++#define KEYBD_MATRIX_GET_INPUTS(inputs) \
++{\
++      inputs = (RAMSES_CPLD_KB_ROW & 0x7f);\
++}
++
++
++// External functions (are they in some #include file?)
++extern int input_setkeycode(unsigned int scancode, unsigned int keycode);
++extern int input_getkeycode(unsigned int scancode);
++extern int input_translate(unsigned char scancode, unsigned char *keycode,
++                               char raw_mode);
++extern char input_unexpected_up(unsigned char keycode);
++extern unsigned char input_sysrq_xlate[];
++extern int pm_suggest_suspend(void);
++
++// Keyboard-Related definitions
++#define KEYBD_MATRIX_INPUT_MASK               ((1 << KEYBD_MATRIX_NUMBER_INPUTS)-1)
++#define KEYBD_MATRIX_OUTPUT_MASK      ((1 << KEYBD_MATRIX_NUMBER_OUTPUTS)-1)
++
++#include "ramses_scancodes.h"
++#include "ramses_keymap.h"
++#include "ramses_cellmap.h"
++
++
++static char *kbd_name = "Keyboard";
++struct input_dev ramses_kbd_dev;
++static struct timer_list reenable_timer;
++static struct timer_list trigoff_timer;
++static struct tq_struct tq_suspend;
++static __u16 keystate_cur[KEYBD_MATRIX_NUMBER_OUTPUTS];
++static __u16 keystate_prev[KEYBD_MATRIX_NUMBER_OUTPUTS];
++static __u16 keystate_keep[KEYBD_MATRIX_NUMBER_OUTPUTS];      // used for auto-repeat
++static struct timer_list cell_timer;
++static int curr_map = MAP_NORMAL;
++static int cell_key = -1;
++static int cell_sel = -1;
++static struct pm_dev *pm_keyb;
++static int suspend_counter = 0;
++
++
++void ramses_key(int keycode)
++{
++      DPRINTK("keycode: %d 0x%x\n", keycode, keycode);
++      if (KVAL(keycode)) {
++              switch (KMOD(keycode)) {
++                      case KM_SHIFT:
++                              DPRINTK("shift\n");
++                              input_report_key(&ramses_kbd_dev, KEY_LEFTSHIFT, 1);
++                              break;
++                      case KM_CTRL:
++                              DPRINTK("ctrl\n");
++                              input_report_key(&ramses_kbd_dev, KEY_LEFTCTRL,  1);
++                              break;
++                      case KM_ALT:
++                              DPRINTK("alt\n");
++                              input_report_key(&ramses_kbd_dev, KEY_LEFTALT,   1);
++                              break;
++                      case KM_ALTGR:
++                              DPRINTK("altgr\n");
++                              input_report_key(&ramses_kbd_dev, KEY_RIGHTALT,  1);
++                              break;
++                      case KM_ALTCTRL:
++                              DPRINTK("alt+ctrl\n");
++                              input_report_key(&ramses_kbd_dev, KEY_LEFTALT,  1);
++                              input_report_key(&ramses_kbd_dev, KEY_LEFTCTRL, 1);
++                              break;
++              }
++
++              DPRINTK("report: %d 0x%x\n", KVAL(keycode), KVAL(keycode));
++              input_report_key(&ramses_kbd_dev, KVAL(keycode), 1);
++              input_report_key(&ramses_kbd_dev, KVAL(keycode), 0);
++
++              switch (KMOD(keycode)) {
++                      case KM_SHIFT:
++                              input_report_key(&ramses_kbd_dev, KEY_LEFTSHIFT, 0);
++                              break;
++                      case KM_CTRL:
++                              input_report_key(&ramses_kbd_dev, KEY_LEFTCTRL,  0);
++                              break;
++                      case KM_ALT:
++                              input_report_key(&ramses_kbd_dev, KEY_LEFTALT,   0);
++                              break;
++                      case KM_ALTGR:
++                              input_report_key(&ramses_kbd_dev, KEY_RIGHTALT,  0);
++                              break;
++                      case KM_ALTCTRL:
++                              input_report_key(&ramses_kbd_dev, KEY_LEFTALT,  0);
++                              input_report_key(&ramses_kbd_dev, KEY_LEFTCTRL, 0);
++                              break;
++              }
++      }
++}
++
++static void kbd_cell_timer(unsigned long keepmap)
++{
++      int keycode;
++
++      if (cell_sel != -1) {
++              keycode = ramses_cellmap[cell_key][cell_sel];
++              //DPRINTK("key: %d   sel: %d  keycode: %d 0x%x\n", cell_key, cell_sel, keycode, keycode);
++              ramses_key(keycode);
++              cell_sel = -1;
++      }
++
++      if (!keepmap && curr_map!=MAP_NORMAL) {
++              DPRINTK("normal map because of %ld\n", keepmap);
++              curr_map = MAP_NORMAL;
++              RAMSES_LED_BLUE_OFF();
++              RAMSES_LED_ORANGE_OFF();
++      }
++}
++
++static void kbd_setleds(void)
++{
++      if (suspend_counter >= SUSPEND_LED_COUNTER) {
++              if (suspend_counter & 4) {
++                      RAMSES_LED_ORANGE_OFF();
++                      RAMSES_LED_BLUE_ON();
++              } else {
++                      RAMSES_LED_ORANGE_ON();
++                      RAMSES_LED_BLUE_OFF();
++              }
++              return;
++      }
++
++      switch (curr_map) {
++      case MAP_NORMAL:
++              RAMSES_LED_BLUE_OFF();
++              RAMSES_LED_ORANGE_OFF();
++              return;
++
++      case MAP_BLUE:
++              RAMSES_LED_BLUE_ON();
++              RAMSES_LED_ORANGE_OFF();
++              return;
++
++      case MAP_ORANGE:
++              RAMSES_LED_BLUE_OFF();
++              RAMSES_LED_ORANGE_ON();
++              return;
++
++      case MAP_CAPS:
++              RAMSES_LED_BLUE_ON();
++              RAMSES_LED_ORANGE_ON();
++              return;
++      }
++      DPRINTK("unknown map\n");
++}
++
++
++static void kbd_start_scanner(void)
++{
++      RAMSES_SCANNER_TRIG_OFF();
++      RAMSES_SCANNER_WAKE_OFF();
++      RAMSES_SCANNER_TRIG_ON();
++      mod_timer(&trigoff_timer, jiffies + TRIGOFFINTERVAL);
++}
++
++static void kbd_stop_scanner(unsigned long dummy)
++{
++      RAMSES_SCANNER_TRIG_OFF();
++}
++
++static int kbd_dokeycode(unsigned char scancode, int down)
++{
++      int i,keycode;
++
++      //DPRINTK("calling with (%d,%x,%d)\n", scancode, scancode, down);
++      if (scancode >= MAX_SCANCODES) {
++              printk("%s: scancode too big for table\n", __FUNCTION__);
++              return 0;
++      }
++
++      keycode = ramses_keymap[scancode][curr_map];
++
++
++      if (keycode==KEY_SCAN) {
++              if ((ramses_flags & RAMSES_FLAGS_KEY_SCAN) == 0)
++                      return 0;
++              
++              DPRINTK("scan btn\n");
++              if (down) {
++                      if (ramses_flags & RAMSES_FLAGS_SCANNER_BEAM) {
++                              // just turn on laser beam
++                              RAMSES_SCANNER_WAKE_ON();
++                      } else {
++                              kbd_start_scanner();
++                      }
++              } else {
++                      if (ramses_flags & RAMSES_FLAGS_SCANNER_BEAM) {
++                              kbd_start_scanner();
++                      } else {
++                              kbd_stop_scanner(0);
++                      }
++              }
++              return 0;
++      }
++
++
++      if (keycode==KEY_SUSP) {
++              if ((ramses_flags & RAMSES_FLAGS_KEY_SUSPEND) == 0)
++                      return 0;
++
++              if (down) {
++                      suspend_counter++;
++                      if (suspend_counter >= SUSPEND_COUNTER) {
++                              suspend_counter = SUSPEND_NOW;
++                      } 
++              } else {
++                      if (suspend_counter == SUSPEND_NOW) {
++                              curr_map = MAP_NORMAL;
++                              schedule_task(&tq_suspend);
++                      }
++                      suspend_counter = 0;
++              }
++              return down;
++      }
++
++
++      if (keycode==KEY_OFF) {
++              if (down || ((ramses_flags & RAMSES_FLAGS_KEY_OFF) == 0))
++                      return 0;
++              curr_map = MAP_NORMAL;
++              ramses_shut_off();
++              return 0;
++      }
++
++
++      if (!down)
++              return 0;
++
++
++      DPRINTK("curr_map %d scancode %d keycode %d 0x%x typ %d\n", curr_map, scancode, keycode, keycode, KMOD(keycode));
++
++
++      // Cell-Phone keyboard handling
++      if (KMOD(keycode)==KM_CELL) {
++              //DPRINTK("cell phone key %d\n", KVAL(keycode));
++
++              // did we press a different cell-phone key as last time?
++              if (KVAL(keycode)!=cell_key)
++                      kbd_cell_timer(1);
++
++              cell_key = KVAL(keycode);               // store current cell-phone key
++              cell_sel++;                             // increase current sub-key
++              if (ramses_cellmap[cell_key][cell_sel]==0)      // if at end of sub-key list, back off
++                      cell_sel = 0;
++              //DPRINTK("cell_key: %d  cell_sel: %d\n", cell_key, cell_sel);
++                                                      // auto-emit via kbd_cell_timer
++              mod_timer(&cell_timer, jiffies + CELLINTERVAL);
++              return 0;                               // do not revert to keys_normal
++      }
++
++
++      // if we pressed any other key then a cell-phone key, we look if the
++      // current half-pressed cell-phone key should be emitted
++      kbd_cell_timer(1);
++
++
++      switch(keycode) {
++
++      // Keymap handling
++
++      case KEY_NORM:
++              DPRINTK("norm key map\n");
++              curr_map = MAP_NORMAL;
++              return 0;
++
++      case KEY_BLUE:
++              //DPRINTK("blue key map\n");
++              curr_map = MAP_BLUE;
++              mod_timer(&cell_timer, jiffies + MAPINTERVAL); // automatically disable keymap
++              return 0;
++
++      case KEY_ORNG:
++              //DPRINTK("orange key map\n");
++              curr_map = MAP_ORANGE;
++              mod_timer(&cell_timer, jiffies + MAPINTERVAL); // automatically disable keymap
++              return 0;
++
++      case KEY_CAPS:
++              DPRINTK("caps key map\n");
++              curr_map = MAP_CAPS;
++              mod_timer(&cell_timer, jiffies + MAPINTERVAL); // automatically disable keymap
++              return 0;
++
++      case KEY_BRIP:
++              i = ramses_lcd_get_brightness()-6;
++              ramses_lcd_set_brightness(i);
++              mod_timer(&cell_timer, jiffies + MAPINTERVAL); // automatically disable keymap
++              return 0;
++
++      case KEY_BRIM:
++              i = ramses_lcd_get_brightness()+6;
++              ramses_lcd_set_brightness(i);
++              mod_timer(&cell_timer, jiffies + MAPINTERVAL); // automatically disable keymap
++              return 0;
++
++      case KEY_CTRM:
++              i = ramses_lcd_get_contrast()+3;
++              ramses_lcd_set_contrast(i);
++              mod_timer(&cell_timer, jiffies + MAPINTERVAL); // automatically disable keymap
++              return 0;
++
++      case KEY_CTRP:
++              i = ramses_lcd_get_contrast()-3;
++              ramses_lcd_set_contrast(i);
++              mod_timer(&cell_timer, jiffies + MAPINTERVAL); // automatically disable keymap
++              return 0;
++      }
++
++      // normal keys
++
++      ramses_key(keycode);
++
++      if (curr_map!=MAP_NORMAL)
++              DPRINTK("back to normal map\n");
++      curr_map = MAP_NORMAL;
++      RAMSES_LED_BLUE_OFF();
++      RAMSES_LED_ORANGE_OFF();
++      return 0;
++}
++
++
++/**
++ * @param rescan 0 if we look for pressed keys, 1 if we look for released keys
++ *
++ * This routine get's called from the ISR (then rescan is always 0) or from
++ * the reenable_timer function (then rescan is 1).
++ */
++static void kbd_scan_keyboard(unsigned long rescan)
++{
++      int i,n;
++      int cols;
++      unsigned char code;
++      __u16 keystate_xor[KEYBD_MATRIX_NUMBER_OUTPUTS];
++
++
++      // Find out if a key (or more) was pressed down. It's possible that
++      // because of spikes we got an interrupt, but when the IRQ service
++      // routine fired there is currently no detectable key.  If this is
++      // true, then delay some times and re-try, but not too often.
++
++      cols = 0;
++      for(n=0; n<10; n++) {
++              for (i = 0; i < KEYBD_MATRIX_NUMBER_OUTPUTS; i++) {
++                      KEYBD_MATRIX_SET_OUTPUTS( 1 << i );
++                      udelay(KEYBD_MATRIX_SETTLING_TIME_US);
++                      KEYBD_MATRIX_GET_INPUTS(keystate_cur[i]);
++                      if (keystate_cur[i])
++                              cols++;
++              }
++              if (cols || rescan)
++                      break;
++              udelay(KEYBD_MATRIX_SETTLING_TIME_US*50);
++      }
++
++      // if rescan is true, we are in the process of turning on the IRQ.
++      // Ignore any spurious IRQ. However, if we got an IRQ but could not
++      // detect any key, we note this on the console, clear the keystate
++      // completely and make sure the IRQ gets re-enabled via the timer
++      // shortly.
++
++      if (!cols && !rescan) {
++              printk("%s: spurious kbd int\n", __FUNCTION__);
++              for (i = 0; i < KEYBD_MATRIX_NUMBER_OUTPUTS; i++) {
++                      keystate_cur[i] = 0;
++                      keystate_prev[i] = 0;
++              }
++              mod_timer(&reenable_timer, jiffies + SCANINTERVAL);
++              return;
++      }
++
++      pm_access(pm_keyb);
++
++      // Okay, all went well. We now keystate_cur[] may contain the rows
++      // where we had keypresses, e.g.
++      //      0 0 0 2 0 0 0 0 0 0 0 0 0 0
++        // We would see this if DEBUG_DUMP_KEYSTATE is on:
++
++#ifdef DEBUG_DUMP_KEYSTATE
++      cols = 0;
++      for (i = 0; i < KEYBD_MATRIX_NUMBER_OUTPUTS; i++) {
++              printk("%d-%d ",keystate_cur[i], keystate_keep[i]);
++      }
++      printk("\n");
++#endif
++
++      cols = 0;
++      for (i = 0; i < KEYBD_MATRIX_NUMBER_OUTPUTS; i++) {
++
++              // detect which key has changes doing an XOR of old state with new state
++              keystate_xor[i] = keystate_prev[i] ^ keystate_cur[i];
++              //printk("%d: prev %d cur %d xor %d keep %d\n", i, keystate_prev[i], keystate_cur[i], keystate_xor[i], keystate_keep[i]);
++
++              // some key changed, find out which one and do the scancode handling
++              if (keystate_xor[i] || keystate_keep[i]) {
++                      for (n = 0; n < KEYBD_MATRIX_NUMBER_INPUTS; n++)
++                      {
++                              if ( (keystate_keep[i] & keystate_cur[i]) || 
++                                   (keystate_xor[i] & (1 << n))  )
++                              {
++                                      int res;
++                                      code = n * KEYBD_MATRIX_NUMBER_OUTPUTS + i + 1;
++                                      res = kbd_dokeycode(code, keystate_cur[i] & (1 << n) ? 1 : 0);
++                                      kbd_setleds();
++                                      if (res) {
++                                              keystate_keep[i] = 1 << n;
++                                              goto out;
++                                      }
++                              }
++                      }
++              }
++out:
++              keystate_prev[i] = keystate_cur[i];
++      }
++
++
++      // fire reenable time if we are in the ISR
++      if (!rescan)
++              mod_timer(&reenable_timer, jiffies + SCANINTERVAL);
++}
++
++
++
++static void kbd_reenable_timer(unsigned long dummy)
++{
++      // re-scan the keyboard (to detect released keys)
++      kbd_scan_keyboard(1);
++
++      // re-enable interrupts from the CPLD
++      KEYBD_MATRIX_SET_OUTPUTS( KEYBD_MATRIX_OUTPUT_MASK );
++}
++
++
++
++
++
++/**
++ * Referenced by request_irq()
++ */
++static void kbd_interrupt(int irq, void *dummy, struct pt_regs *fp)
++{
++      kbd_scan_keyboard(0);
++}
++
++static void ramseskbd_suspend(void *data)
++{
++      pm_suggest_suspend();
++}
++
++
++static int __init ramseskbd_init(void)
++{
++      int irq_gpio_pin;
++
++      // Activate the normal pc-keycodes for the input-layer-keyboard
++      k_setkeycode    = input_setkeycode;
++      k_getkeycode    = input_getkeycode;
++      k_translate     = input_translate;
++      k_unexpected_up = input_unexpected_up;
++#ifdef CONFIG_MAGIC_SYSRQ
++      k_sysrq_key     = 0x54;
++      k_sysrq_xlate   = input_sysrq_xlate;
++#endif
++
++      // In linux-2.5.x we can do
++      //      init_input_dev(&ramses_kbd_dev);
++      // but here we don't have this on linux-2.4, so we fill it with zeros:
++        memset(&ramses_kbd_dev, 0, sizeof(ramses_kbd_dev));
++      ramses_kbd_dev.name = kbd_name;
++
++      // which events we can produce (only keypresses):
++      ramses_kbd_dev.evbit[0] = BIT(EV_KEY);
++
++      // which keypresses we can produce (all):
++        memset(&ramses_kbd_dev.keybit, 0xff, sizeof(ramses_kbd_dev.keybit));
++
++        // We set the 14 output columns to 0. This stops the CPLD to
++      // generate an IRQ before we finished our setup
++      KEYBD_MATRIX_SET_OUTPUTS(0);
++
++      // Turn all LEDs off, meaning that we have the normal keymap active
++      RAMSES_LED_BLUE_OFF();
++      RAMSES_LED_ORANGE_OFF();
++      // TODO: used leds.c?
++
++      // Now we make sure that the GPIO for our IRQ is programmed correctly
++      irq_gpio_pin = IRQ_TO_GPIO_2_80(RAMSES_KEYBOARD_IRQ);
++      GPDR(irq_gpio_pin) &= ~GPIO_bit(irq_gpio_pin);
++      set_GPIO_IRQ_edge(irq_gpio_pin, RAMSES_KEYBOARD_IRQ_EDGE);
++      request_irq(RAMSES_KEYBOARD_IRQ, kbd_interrupt, 0, kbd_name, NULL);
++
++      // Initialize timer to re-enable IRQs. That's our method of keyboard de-prelling
++      init_timer(&reenable_timer);
++      reenable_timer.function = kbd_reenable_timer;
++
++      init_timer(&trigoff_timer);
++      trigoff_timer.function = kbd_stop_scanner;
++
++      // Initialize to escape the blue mode, so we emit the current cell-phone key
++      init_timer(&cell_timer);
++      cell_timer.function = kbd_cell_timer;
++
++      tq_suspend.routine = ramseskbd_suspend;
++
++      // Register with Power-Management
++#ifdef PM_DEBUG
++        pm_keyb = pm_register(PM_SYS_DEV, PM_SYS_KBC+1, NULL, "ramses_keyb");
++#else
++        pm_keyb = pm_register(PM_SYS_DEV, PM_SYS_KBC+1, NULL);
++#endif
++
++      // Register our keyboard
++      input_register_device(&ramses_kbd_dev);
++
++        // We set the 14 output columns to 1. This allows the CPLD to
++      // generate an IRQ when one of the rows goes high
++      KEYBD_MATRIX_SET_OUTPUTS(KEYBD_MATRIX_OUTPUT_MASK);
++
++      return 0;
++}
++
++
++static void __exit ramseskbd_exit(void)
++{
++      // make IRQs impossible, return the IRQ and unregister us
++      KEYBD_MATRIX_SET_OUTPUTS(0);
++      free_irq(RAMSES_KEYBOARD_IRQ, NULL);
++      pm_unregister(pm_keyb);
++      input_unregister_device(&ramses_kbd_dev);
++}
++
++
++module_init(ramseskbd_init);
++module_exit(ramseskbd_exit);
++
++MODULE_AUTHOR("Holger Schurig <h.schurig@mn-logistik.de>");
++MODULE_DESCRIPTION("Ramses keyboard driver");
++MODULE_LICENSE("GPL");
++EXPORT_SYMBOL(ramses_key);
++EXPORT_SYMBOL(ramses_kbd_dev);
+--- /dev/null
++++ linux-2.4.21/drivers/input/ramses_keymap.h
+@@ -0,0 +1,68 @@
++// Normal Map
++static int ramses_keymap[][6] = {
++/*          Normal      Blue        Orange      Caps        Spare       Spare  */
++/*   0 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*   1 */  {KEY_SUSP,   KEY_SUSP,   KEY_SUSP,   KEY_OFF,    KEY_SUSP,   KEY_SUSP },  
++/*   2 */  {KEY_UP,     KEY_UP,     KEY_PGUP,   KEY_UP,     KEY_noop,   KEY_noop },  
++/*   3 */  {KEY_1,      KEY_SPACE,  KEY_BRIM,   KEY_SPACE,  KEY_noop,   KEY_noop },  
++/*   4 */  {KEY_4,      KEY_ghi ,   KEY_CTRM,   KEY_GHI ,   KEY_noop,   KEY_noop },  
++/*   5 */  {KEY_7,      KEY_pqrs,   KEY_cel7,   KEY_PQRS,   KEY_noop,   KEY_noop },  
++/*   6 */  {KEY_DOT,    KEY_uml,    KEY_celP,   KEY_UML,    KEY_noop,   KEY_noop },  
++/*   7 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*   8 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*   9 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  10 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  11 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  12 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  13 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  14 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  15 */  {KEY_ENTER,  KEY_ENTER,  KEY_ENTER,  KEY_ENTER,  KEY_ENTER,  KEY_ENTER},
++/*  16 */  {KEY_DOWN,   KEY_DOWN,   KEY_PGDN,   KEY_DOWN,   KEY_noop,   KEY_noop },  
++/*  17 */  {KEY_2,      KEY_abc ,   KEY_BRIP,   KEY_ABC ,   KEY_noop,   KEY_noop },  
++/*  18 */  {KEY_5,      KEY_jkl ,   KEY_CTRP,   KEY_JKL,    KEY_noop,   KEY_noop },  
++/*  19 */  {KEY_8,      KEY_tuv ,   KEY_cel8,   KEY_TUV,    KEY_noop,   KEY_noop },  
++
++/*          Normal      Blue        Orange      Caps        Spare       Spare  */
++/*  20 */  {KEY_0,      KEY_TAB,    KEY_cel0,   KEY_BTAB,   KEY_noop,   KEY_noop },  
++/*  21 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  22 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  23 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  24 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  25 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  26 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  27 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  28 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  29 */  {KEY_ESC,    KEY_ESC,    KEY_ESC,    KEY_ESC,    KEY_ESC,    KEY_ESC  },
++/*  30 */  {KEY_RIGHT,  KEY_RIGHT,  KEY_END,    KEY_C2,     KEY_noop,   KEY_noop },  
++/*  31 */  {KEY_3,      KEY_def,    KEY_FXIT,   KEY_DEF,    KEY_noop,   KEY_noop },  
++/*  32 */  {KEY_6,      KEY_mno ,   KEY_FRST,   KEY_MNO,    KEY_noop,   KEY_noop },  
++/*  33 */  {KEY_9,      KEY_wxyz,   KEY_cel9,   KEY_WXYZ,   KEY_noop,   KEY_noop },  
++/*  34 */  {KEY_BACKSPACE,KEY_ATSIGN,KEY_BAR,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  35 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  36 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  37 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  38 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  39 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++
++/*          Normal      Blue        Orange      Caps        Spare       Spare  */
++/*  40 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  41 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  42 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  43 */  {KEY_SCAN,   KEY_SCAN,   KEY_SCAN,   KEY_SCAN,   KEY_SCAN,   KEY_SCAN },  
++/*  44 */  {KEY_LEFT,   KEY_LEFT,   KEY_HOME,   KEY_C1,     KEY_noop,   KEY_noop },  
++/*  45 */  {KEY_OFF,    KEY_OFF,    KEY_OFF,    KEY_OFF,    KEY_OFF,    KEY_OFF  },  
++/*  46 */  {KEY_F1,     KEY_F4,     KEY_F7,     KEY_F10,    KEY_noop,   KEY_noop },  
++/*  47 */  {KEY_F2,     KEY_F5,     KEY_F8,     KEY_F11,    KEY_noop,   KEY_noop },  
++/*  48 */  {KEY_F3,     KEY_F6,     KEY_F9,     KEY_F12,    KEY_noop,   KEY_noop },  
++/*  49 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  50 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  51 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  52 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  53 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  54 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  55 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  56 */  {KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop,   KEY_noop },  
++/*  57 */  {KEY_SCAN,   KEY_SCAN,   KEY_SCAN,   KEY_SCAN,   KEY_SCAN,   KEY_SCAN },  
++/*  58 */  {KEY_BLUE,   KEY_NORM,   KEY_CAPS,   KEY_NORM,   KEY_NORM,   KEY_NORM },  
++/*  59 */  {KEY_ORNG,   KEY_CAPS,   KEY_NORM,   KEY_NORM,   KEY_NORM,   KEY_NORM },  
++};
+--- /dev/null
++++ linux-2.4.21/drivers/input/ramses_scancodes.h
+@@ -0,0 +1,134 @@
++#ifndef _RAMSES_SCANCODES_H
++#define _RAMSES_SCANCODES_H
++
++#define KMOD(a) (a & 0xff00)
++#undef KVAL
++#define KVAL(a) (a & 0x00ff)
++
++// which modifiers to send before/after
++#define KM_SPECIAL 0x300
++#define KM_CELL    0x400
++#define KM_SHIFT   0x500
++#define KM_ALT     0x600
++#define KM_CTRL    0x700
++#define KM_ALTGR   0x800
++#define KM_ALTCTRL 0x900
++
++// or special keys
++#define KEY_noop      KM_SPECIAL + 0
++#define KEY_OFF               KM_SPECIAL + 1
++#define KEY_SUSP      KM_SPECIAL + 2
++#define KEY_SCAN      KM_SPECIAL + 3
++#define KEY_CTRM      KM_SPECIAL + 4
++#define KEY_CTRP      KM_SPECIAL + 5
++#define KEY_BRIM      KM_SPECIAL + 6
++#define KEY_BRIP      KM_SPECIAL + 7
++
++#define KEY_NORM      KM_SPECIAL + 10
++#define KEY_BLUE      KM_SPECIAL + 11
++#define KEY_ORNG      KM_SPECIAL + 12
++#define KEY_CAPS      KM_SPECIAL + 13 
++
++
++// our cell-phone like keys
++#define KEY_abc               KM_CELL + 0
++#define KEY_def               KM_CELL + 1
++#define KEY_ghi               KM_CELL + 2
++#define KEY_jkl               KM_CELL + 3
++#define KEY_mno               KM_CELL + 4
++#define KEY_pqrs      KM_CELL + 5
++#define KEY_tuv               KM_CELL + 6
++#define KEY_wxyz      KM_CELL + 7
++#define KEY_uml               KM_CELL + 8
++#define KEY_ABC               KM_CELL + 9
++#define KEY_DEF               KM_CELL + 10
++#define KEY_GHI               KM_CELL + 11
++#define KEY_JKL               KM_CELL + 12
++#define KEY_MNO               KM_CELL + 13
++#define KEY_PQRS      KM_CELL + 14
++#define KEY_TUV               KM_CELL + 15
++#define KEY_WXYZ      KM_CELL + 16
++#define KEY_UML               KM_CELL + 17
++#define KEY_cel7      KM_CELL + 18
++#define KEY_cel8      KM_CELL + 19
++#define KEY_cel9      KM_CELL + 20
++#define KEY_celP      KM_CELL + 21
++#define KEY_cel0      KM_CELL + 22
++
++// Shift-Keys
++#define KEY_sA                KM_SHIFT + KEY_A
++#define KEY_sB                KM_SHIFT + KEY_B
++#define KEY_sC                KM_SHIFT + KEY_C
++#define KEY_sD                KM_SHIFT + KEY_D
++#define KEY_sE                KM_SHIFT + KEY_E
++#define KEY_sF                KM_SHIFT + KEY_F
++#define KEY_sG                KM_SHIFT + KEY_G
++#define KEY_sH                KM_SHIFT + KEY_H
++#define KEY_sI                KM_SHIFT + KEY_I
++#define KEY_sJ                KM_SHIFT + KEY_J
++#define KEY_sK                KM_SHIFT + KEY_K
++#define KEY_sL                KM_SHIFT + KEY_L
++#define KEY_sM                KM_SHIFT + KEY_M
++#define KEY_sN                KM_SHIFT + KEY_N
++#define KEY_sO                KM_SHIFT + KEY_O
++#define KEY_sP                KM_SHIFT + KEY_P
++#define KEY_sQ                KM_SHIFT + KEY_Q
++#define KEY_sR                KM_SHIFT + KEY_R
++#define KEY_sS                KM_SHIFT + KEY_S
++#define KEY_sT                KM_SHIFT + KEY_T
++#define KEY_sU                KM_SHIFT + KEY_U
++#define KEY_sV                KM_SHIFT + KEY_V
++#define KEY_sW                KM_SHIFT + KEY_W
++#define KEY_sX                KM_SHIFT + KEY_X
++#define KEY_sY                KM_SHIFT + KEY_Y
++#define KEY_sZ                KM_SHIFT + KEY_Z
++
++// Umlaute
++#define KEY_sAE               KM_SHIFT + 40
++#define KEY_sOE               KM_SHIFT + 39
++#define KEY_sUE               KM_SHIFT + 26
++#define KEY_AE                40
++#define KEY_OE                39
++#define KEY_UE                26
++#define KEY_SZ                12
++
++// AS400-Keys
++#define KEY_FRST      KM_ALT + KEY_R
++#define KEY_FXIT      KM_ALT + KEY_X
++
++// Console-Switch
++#define KEY_C1                KM_ALTCTRL + KEY_F1
++#define KEY_C2                KM_ALTCTRL + KEY_F2
++
++// additional keys from the german keyboard
++#undef KEY_MINUS
++#undef KEY_EQUAL
++#undef KEY_Y
++#undef KEY_Z
++#define KEY_Y         44
++#define KEY_Z         21
++#define KEY_STAR      55
++#define KEY_COLON     KM_SHIFT + 52
++#define KEY_UNDERL    KM_SHIFT + 53
++#define KEY_ATSIGN    KM_ALTGR + 16
++#define KEY_BAR               KM_ALTGR + 86
++#define KEY_EQUAL     KM_SHIFT + 11
++#define KEY_SEMI      KM_SHIFT + 51
++#define KEY_BSLASH    KM_ALTGR + 12
++#define KEY_FSLASH    KM_SHIFT + KEY_7
++#define KEY_MINUS     53
++#define KEY_PLUS      27
++#define KEY_GAENSE    KM_SHIFT + 3
++#define KEY_PARA      KM_SHIFT + 4
++#define KEY_HASH      43
++#define KEY_PGUP      KEY_PAGEUP
++#define KEY_PGDN      KEY_PAGEDOWN
++#define KEY_BTAB      KM_SHIFT + KEY_TAB
++
++#define MAP_NORMAL 0
++#define MAP_BLUE   1
++#define MAP_ORANGE 2
++#define MAP_CAPS   3
++#define MAX_SCANCODES 100
++
++#endif
+--- /dev/null
++++ linux-2.4.21/drivers/input/wedge.c
+@@ -0,0 +1,241 @@
++/*
++ *  Virtual keyboard wedge using input layer
++ *
++ *  (C) 2002,2003 by M&N Logistik-Lösungen Online GmbH
++ *  written by H.Schurig
++ *
++ *  Creates a misc char device /dev/misc/wedge. Any output to this
++ *  device will be translated (via a german keyboard map) into scancodes
++ *  and re-submitted into the keyboard channel. Any console, X-Windows
++ *  or Qt/Embedded application will be able to receive this info.
++ */
++
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/miscdevice.h>
++#include <linux/input.h>
++
++#include <linux/types.h>
++#include <linux/keyboard.h>
++#include <linux/kd.h>
++
++#include <asm/uaccess.h>
++
++
++// Debug
++//#define DEBUG 1
++#ifdef DEBUG
++#  define DPRINTK(fmt, args...)       printk("%s: " fmt, __FUNCTION__ , ## args)
++#  define PRINTK(fmt, args...)        printk(fmt, ## args)
++#else
++#  define DPRINTK(fmt, args...)
++#  define PRINTK(fmt, args...)
++#endif
++
++
++// Defines
++#define KBD_STUFF_MAX_BYTES   512
++
++// Für den IOCTL
++#define       WEDGE_RAWKEY_DOWN       _IOW('w', 0x72, unsigned long)
++#define       WEDGE_RAWKEY_UP         _IOW('w', 0x73, unsigned long)
++#define       WEDGE_TS_ABS_X          _IOW('w', 0x74, unsigned long)
++#define       WEDGE_TS_ABS_Y          _IOW('w', 0x75, unsigned long)
++#define       WEDGE_TS_ABS_PRESSURE   _IOW('w', 0x76, unsigned long)
++
++// Externs
++#define MAX_NR_KEYMAPS  256
++extern void ramses_key(int keycode);
++extern unsigned short *key_maps[MAX_NR_KEYMAPS];
++extern struct input_dev ramses_kbd_dev;
++extern void ucb1x00_ts_evt_add(void *, u16 pressure, u16 x, u16 y);
++
++// for special keys
++struct wedge_lookup_t {
++      u_short c;
++      u_short keysym;
++};
++
++struct wedge_lookup_t wedge_lookup[] = {
++      { 0x0a, 0x001c, },
++      { 0x2f, 0x0508, },
++};
++
++
++
++
++static void *outbuf;
++
++static int wedge_open(struct inode *inode, struct file *filp)
++{
++      int ret;
++
++      ret = -ENXIO;
++      outbuf = kmalloc(KBD_STUFF_MAX_BYTES, GFP_KERNEL);
++      if (!outbuf)
++              goto out;
++
++      ret = 0;
++
++out:
++      if (ret) {
++              kfree(outbuf);
++      }
++      return ret;
++}
++
++
++static int wedge_close(struct inode *inode, struct file *filp)
++{
++      kfree(outbuf);
++      return 0;
++}
++
++
++static int wedge_search_map(u_short map[], int c)
++{
++      int i;
++
++      for (i=0; i<NR_KEYS; i++) {
++              if (map[i] == (c | 0xf000))
++                      return i;
++              if (map[i] == (c | 0xfb00))
++                      return i;
++      }
++
++      return 0;
++}
++
++
++static void wedge_handle_char(int c)
++{
++      int i;
++      unsigned int maps;
++      u_short *map;
++
++      DPRINTK("wedge_handle_char(0x%0x)\n", c);
++
++      for (i=0; i < sizeof(wedge_lookup)/sizeof(wedge_lookup[0]); i++) {
++              if (wedge_lookup[i].c == c) {
++                      ramses_key(wedge_lookup[i].keysym);
++                      return;
++              }
++      }
++
++
++      i = 0;
++      for (maps=0; maps<MAX_NR_KEYMAPS; maps++) {
++              map = key_maps[maps];
++              if (!map)
++                      continue;
++              if ((i = wedge_search_map(map, c))) {
++                      switch(maps) {
++                              case 0:
++                                      break;
++                              case 1:
++                                      i |= 0x500;     // KT_SHIFT from ramses_scancodes.h
++                                      break;
++                              case 2:
++                                      i |= 0x800;     // KT_ALTGR from ramses_scancodes.h
++                                      break;
++                              case 4:
++                                      i |= 0x700;     // KT_CTRL from ramses_scancodes.h
++                                      break;
++                              default:
++                                      DPRINTK("unknown map for char %d %d\n", c, maps);
++                      }
++                      DPRINTK("ramses_key(0x%x)\n", i);
++                      ramses_key(i);
++                      return;
++              }
++      }
++
++      DPRINTK("entry for char %02x missing\n", c);
++}
++
++
++
++static ssize_t wedge_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
++{
++      const char *p = buf;
++      char c;
++
++      //DPRINTK("count=%d\n", count);
++      while (count) {
++              if (copy_from_user(&c, p, sizeof(c)))
++                      return -EFAULT;
++
++              p++;
++              count--;
++
++              wedge_handle_char( (int)c & 0xff);
++
++      }
++      return p - buf;
++}
++
++
++int wedge_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
++{
++      static u16 x;
++      static u16 y;
++      static u16 p;
++
++      switch (cmd) {
++      case WEDGE_RAWKEY_DOWN:
++              DPRINTK("send down raw key\n");
++              input_report_key(&ramses_kbd_dev, arg, 1);
++              return 0;
++      case WEDGE_RAWKEY_UP:
++              DPRINTK("send up raw key\n");
++              input_report_key(&ramses_kbd_dev, arg, 0);
++              return 0;
++      case WEDGE_TS_ABS_X:
++              x = arg;
++              return 0;
++      case WEDGE_TS_ABS_Y:
++              y = arg;
++              return 0;
++      case WEDGE_TS_ABS_PRESSURE:
++              p = arg;
++              ucb1x00_ts_evt_add(NULL, arg, y, x);
++              return 0;
++      }
++      return -EINVAL;
++}
++
++
++static struct file_operations wedge_fops = {
++      owner:          THIS_MODULE,
++      write:          wedge_write,
++      open:           wedge_open,
++      release:        wedge_close,
++      ioctl:          wedge_ioctl,
++};
++
++
++static struct miscdevice wedge_miscdev = {
++      minor:  MISC_DYNAMIC_MINOR,
++      name:   "wedge",
++      fops:   &wedge_fops,
++};
++
++static int __init wedge_init(void)
++{
++        int ret;
++      ret = misc_register(&wedge_miscdev);
++      DPRINTK("major,minor is 10,%d\n", wedge_miscdev.minor);
++      return ret;
++}
++
++static void __exit wedge_exit(void)
++{
++      misc_deregister(&wedge_miscdev);
++}
++
++module_init(wedge_init);
++module_exit(wedge_exit);
++
++MODULE_DESCRIPTION("virtual keyboard wedge");
++MODULE_LICENSE("GPL");
+--- linux-2.4.21/drivers/misc/Makefile~wedge
++++ linux-2.4.21/drivers/misc/Makefile
+@@ -12,7 +12,7 @@
+ O_TARGET := misc.o
+ export-objs                   := mcp-core.o mcp-sa1100.o mcp-pxa.o \
+-                                 ucb1x00-core.o 
++                                 ucb1x00-core.o ucb1x00-ts.o
+ obj-$(CONFIG_MCP_SA1100)      += mcp-core.o mcp-sa1100.o
+ obj-$(CONFIG_MCP_UCB1200)     += ucb1x00-core.o
+--- linux-2.4.21/drivers/misc/mcp-pxa.c~ucb1x00
++++ linux-2.4.21/drivers/misc/mcp-pxa.c
+@@ -31,6 +31,11 @@
+       return (struct mcp *)codec;
+ }
++void mcp_put(void)
++{
++      pxa_ac97_put();
++}
++
+ void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val)
+ {
+       struct ac97_codec *codec = (struct ac97_codec *)mcp;
+@@ -55,3 +60,7 @@
+ void mcp_disable(struct mcp *mcp)
+ {
+ }
++
++MODULE_AUTHOR("Jeff Sutherland <jeffs@accelent.com>");
++MODULE_DESCRIPTION("PXA mcp low level support");
++MODULE_LICENSE("GPL");
+--- linux-2.4.21/drivers/misc/mcp.h~ucb1x00
++++ linux-2.4.21/drivers/misc/mcp.h
+@@ -43,6 +43,7 @@
+ /* noddy implementation alert! */
+ struct mcp *mcp_get(void);
++void mcp_put(void);
+ int mcp_register(struct mcp *);
+ #define mcp_get_sclk_rate(mcp)        ((mcp)->sclk_rate)
+--- linux-2.4.21/drivers/misc/ucb1x00-core.c~pm
++++ linux-2.4.21/drivers/misc/ucb1x00-core.c
+@@ -25,6 +25,7 @@
+ #include <linux/pm.h>
+ #include <linux/tqueue.h>
+ #include <linux/config.h>
++#include <linux/delay.h>
+ #include <asm/irq.h>
+ #include <asm/mach-types.h>
+@@ -181,8 +182,9 @@
+               if (val & UCB_ADC_DAT_VAL)
+                       break;
+               /* yield to other processes */
+-              set_current_state(TASK_INTERRUPTIBLE);
+-              schedule_timeout(1);
++              //HS set_current_state(TASK_INTERRUPTIBLE);
++              //HS schedule_timeout(1);
++              udelay(200);
+       }
+       return UCB_ADC_DAT(val);
+@@ -209,7 +211,8 @@
+       struct ucb1x00 *ucb = (struct ucb1x00 *)dev->data;
+       unsigned int isr;
+-      if (rqst == PM_RESUME) {
++      switch (rqst) {
++      case PM_RESUME:
+               ucb1x00_enable(ucb);
+               isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
+               ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
+@@ -521,7 +524,9 @@
+  */
+ static int __init ucb1x00_configure(struct ucb1x00 *ucb)
+ {
++#ifndef CONFIG_ARCH_RAMSES
+       unsigned int irq_gpio_pin = 0;
++#endif
+       int irq, default_irq = NO_IRQ;
+ #ifdef CONFIG_ARCH_SA1100
+@@ -611,11 +616,13 @@
+       /*
+        * Eventually, this will disappear.
+        */
++#ifndef CONFIG_ARCH_RAMSES
+       if (irq_gpio_pin)
+ #ifdef CONFIG_ARCH_PXA_IDP
+               set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_FALLING_EDGE);
+ #else
+               set_GPIO_IRQ_edge(irq_gpio_pin, GPIO_RISING_EDGE);
++#endif
+ #endif
+       irq = ucb1x00_detect_irq(ucb);
+       if (irq != NO_IRQ) {
+--- linux-2.4.21/drivers/misc/ucb1x00-ts.c~ramses-ucb1x00-dejitter
++++ linux-2.4.21/drivers/misc/ucb1x00-ts.c
+@@ -29,6 +29,7 @@
+ #include <asm/dma.h>
+ #include <asm/semaphore.h>
++#include <asm/hardware.h>
+ #include "ucb1x00.h"
+@@ -97,7 +98,7 @@
+ };
+ static struct ucb1x00_ts ucbts;
+-static int adcsync = UCB_NOSYNC;
++static int adcsync = UCB_SYNC;
+ static int ucb1x00_ts_startup(struct ucb1x00_ts *ts);
+ static void ucb1x00_ts_shutdown(struct ucb1x00_ts *ts);
+@@ -116,8 +117,14 @@
+       next_head = (ts->evt_head + 1) & (NR_EVENTS - 1);
+       if (next_head != ts->evt_tail) {
+               ts->events[ts->evt_head].pressure = pressure;
++#if 0
+               ts->events[ts->evt_head].x = x;
+               ts->events[ts->evt_head].y = y;
++#else
++              // rotate by -90
++              ts->events[ts->evt_head].x = y;
++              ts->events[ts->evt_head].y = x;
++#endif
+               do_gettimeofday(&ts->events[ts->evt_head].stamp);
+               ts->evt_head = next_head;
+@@ -256,11 +263,11 @@
+ #define ucb1x00_ts_evt_clear(ts)      do { } while (0)
+-static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
++void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
+ {
+-      input_report_abs(&ts->idev, ABS_X, x);
+-      input_report_abs(&ts->idev, ABS_Y, y);
+-      input_report_abs(&ts->idev, ABS_PRESSURE, pressure);
++      input_report_abs(&ucbts.idev, ABS_X, y);
++      input_report_abs(&ucbts.idev, ABS_Y, x);
++      input_report_abs(&ucbts.idev, ABS_PRESSURE, pressure);
+ }
+ static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
+@@ -335,7 +342,7 @@
+                       UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
+                       UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+-      return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
++      return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSMY, ts->adcsync);
+ }
+ /*
+@@ -346,19 +353,15 @@
+  */
+ static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts)
+ {
+-      ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+-                      UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+-                      UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+-      ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+-                      UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+-                      UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
++      unsigned int res;
+       ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+                       UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
+-      udelay(55);
++      udelay(600);
+-      return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
++      res = ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSMY, ts->adcsync);
++      return res;
+ }
+ /*
+@@ -369,19 +372,15 @@
+  */
+ static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts)
+ {
++      unsigned int res;
+       ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+-                      UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+-                      UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+-      ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+-                      UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+-                      UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+-      ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+-                      UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
++                      UCB_TS_CR_TSPY_GND | UCB_TS_CR_TSMY_POW |
+                       UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
+-      udelay(55);
++      udelay(300);
+-      return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync);
++      res = ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync);
++      return res;
+ }
+ /*
+@@ -430,8 +429,9 @@
+        * We could run as a real-time thread.  However, thus far
+        * this doesn't seem to be necessary.
+        */
+-//    tsk->policy = SCHED_FIFO;
+-//    tsk->rt_priority = 1;
++//HS
++      tsk->policy = SCHED_FIFO;
++      tsk->rt_priority = 1;
+       /* only want to receive SIGKILL */
+       spin_lock_irq(&tsk->sigmask_lock);
+@@ -451,8 +451,8 @@
+               ucb1x00_adc_enable(ts->ucb);
+               x = ucb1x00_ts_read_xpos(ts);
+-              y = ucb1x00_ts_read_ypos(ts);
+               p = ucb1x00_ts_read_pressure(ts);
++              y = ucb1x00_ts_read_ypos(ts);
+               /*
+                * Switch back to interrupt mode.
+@@ -461,7 +461,7 @@
+               ucb1x00_adc_disable(ts->ucb);
+               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+-              schedule_timeout(HZ / 100);
++              schedule_timeout(HZ / 200);
+               if (signal_pending(tsk))
+                       break;
+@@ -504,7 +504,7 @@
+                       }
+                       set_task_state(tsk, TASK_INTERRUPTIBLE);
+-                      schedule_timeout(HZ / 100);
++                      schedule_timeout(HZ / 200);
+               }
+               if (signal_pending(tsk))
+@@ -655,8 +655,8 @@
+       char *p;
+       while ((p = strsep(&str, ",")) != NULL) {
+-              if (strcmp(p, "sync") == 0)
+-                      adcsync = UCB_SYNC;
++              if (strcmp(p, "nosync") == 0)
++                      adcsync = UCB_NOSYNC;
+       }
+       return 1;
+@@ -674,6 +674,7 @@
+ module_init(ucb1x00_ts_init);
+ module_exit(ucb1x00_ts_exit);
++EXPORT_SYMBOL(ucb1x00_ts_evt_add);
+ MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+ MODULE_DESCRIPTION("UCB1x00 touchscreen driver");
+ MODULE_LICENSE("GPL");
+--- linux-2.4.21/drivers/mtd/maps/Config.in~ramses-mtd
++++ linux-2.4.21/drivers/mtd/maps/Config.in
+@@ -76,6 +76,7 @@
+ if [ "$CONFIG_ARM" = "y" ]; then
+    dep_tristate '  CFI Flash device mapped on Lubbock board' CONFIG_MTD_LUBBOCK $CONFIG_MTD_CFI $CONFIG_ARCH_LUBBOCK $CONFIG_MTD_PARTITIONS
++   dep_tristate '  CFI Flash device mapped on Ramses board' CONFIG_MTD_RAMSES $CONFIG_MTD_CFI $CONFIG_ARCH_RAMSES $CONFIG_MTD_PARTITIONS
+    dep_tristate '  CFI Flash device mapped on Nora' CONFIG_MTD_NORA $CONFIG_MTD_CFI
+    dep_tristate '  CFI Flash device mapped on ARM Integrator/P720T' CONFIG_MTD_ARM_INTEGRATOR $CONFIG_MTD_CFI
+    dep_tristate '  Cirrus CDB89712 evaluation board mappings' CONFIG_MTD_CDB89712 $CONFIG_MTD_CFI $CONFIG_ARCH_CDB89712
+--- linux-2.4.21/drivers/mtd/maps/Makefile~ramses-mtd
++++ linux-2.4.21/drivers/mtd/maps/Makefile
+@@ -16,6 +16,7 @@
+ obj-$(CONFIG_MTD_EPXA)                += epxa-flash.o
+ obj-$(CONFIG_MTD_IQ80310)     += iq80310.o
+ obj-$(CONFIG_MTD_LUBBOCK)     += lubbock.o
++obj-$(CONFIG_MTD_RAMSES)      += ramses.o
+ obj-$(CONFIG_MTD_PXA_CERF)    += pxa_cerf.o
+ obj-$(CONFIG_MTD_TRIZEPS2)    += trizeps2.o
+ obj-$(CONFIG_MTD_L440GX)      += l440gx.o
+--- /dev/null
++++ linux-2.4.21/drivers/mtd/maps/ramses.c
+@@ -0,0 +1,167 @@
++/*
++ * Map driver for the Ramses developer platform.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <asm/io.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++
++
++#define WINDOW_ADDR   0
++#define WINDOW_SIZE   32*1024*1024
++
++static __u8 ramses_read8(struct map_info *map, unsigned long ofs)
++{
++      return *(__u8 *)(map->map_priv_1 + ofs);
++}
++
++static __u16 ramses_read16(struct map_info *map, unsigned long ofs)
++{
++      return *(__u16 *)(map->map_priv_1 + ofs);
++}
++
++static __u32 ramses_read32(struct map_info *map, unsigned long ofs)
++{
++      return *(__u32 *)(map->map_priv_1 + ofs);
++}
++
++static void ramses_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
++{
++      memcpy(to, (void *)(map->map_priv_1 + from), len);
++}
++
++static void ramses_write8(struct map_info *map, __u8 d, unsigned long adr)
++{
++      *(__u8 *)(map->map_priv_1 + adr) = d;
++}
++
++static void ramses_write16(struct map_info *map, __u16 d, unsigned long adr)
++{
++      *(__u16 *)(map->map_priv_1 + adr) = d;
++}
++
++static void ramses_write32(struct map_info *map, __u32 d, unsigned long adr)
++{
++      *(__u32 *)(map->map_priv_1 + adr) = d;
++}
++
++static void ramses_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
++{
++      memcpy((void *)(map->map_priv_1 + to), from, len);
++}
++
++static struct map_info ramses_map = {
++      name: "Flash",
++      size: WINDOW_SIZE,
++      read8:          ramses_read8,
++      read16:         ramses_read16,
++      read32:         ramses_read32,
++      copy_from:      ramses_copy_from,
++      write8:         ramses_write8,
++      write16:        ramses_write16,
++      write32:        ramses_write32,
++      copy_to:        ramses_copy_to
++};
++
++static struct mtd_partition ramses_partitions[] = {
++      {
++              name:           "Bootloader",
++              size:           0x00040000,
++              offset:         0,
++      },{
++              name:           "Kernel",
++              size:           0x00100000,
++              offset:         0x00040000,
++      },{
++              name:           "Filesystem",
++              size:           MTDPART_SIZ_FULL,
++              offset:         0x00140000
++      }
++};
++
++#define NB_OF(x)  (sizeof(x)/sizeof(x[0]))
++
++static struct mtd_info *mymtd;
++static struct mtd_partition *parsed_parts;
++
++extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
++
++static int __init init_ramses(void)
++{
++      struct mtd_partition *parts;
++      int nb_parts = 0;
++      int parsed_nr_parts = 0;
++      char *part_type = "static";
++
++      ramses_map.buswidth = (BOOT_DEF & 1) ? 2 : 4;
++      printk( "Probing flash at physical address 0x%08x (%d-bit buswidth)\n",
++              WINDOW_ADDR, ramses_map.buswidth * 8 );
++#ifdef CONFIG_ARCH_RAMSES
++      FLASH_WRITE_PROTECT_DISABLE();
++#endif
++      ramses_map.map_priv_1 = (unsigned long)__ioremap(WINDOW_ADDR, WINDOW_SIZE, 0);
++      if (!ramses_map.map_priv_1) {
++              printk("Failed to ioremap\n");
++              return -EIO;
++      }
++      mymtd = do_map_probe("cfi_probe", &ramses_map);
++      if (!mymtd) {
++              iounmap((void *)ramses_map.map_priv_1);
++              return -ENXIO;
++      }
++      mymtd->module = THIS_MODULE;
++
++#ifdef CONFIG_MTD_REDBOOT_PARTS
++      if (parsed_nr_parts == 0) {
++              int ret = parse_redboot_partitions(mymtd, &parsed_parts);
++
++              if (ret > 0) {
++                      part_type = "RedBoot";
++                      parsed_nr_parts = ret;
++              }
++      }
++#endif
++
++      if (parsed_nr_parts > 0) {
++              parts = parsed_parts;
++              nb_parts = parsed_nr_parts;
++      } else {
++              parts = ramses_partitions;
++              nb_parts = NB_OF(ramses_partitions);
++      }
++      if (nb_parts) {
++              printk(KERN_NOTICE "Using %s partition definition\n", part_type);
++              add_mtd_partitions(mymtd, parts, nb_parts);
++      } else {
++              add_mtd_device(mymtd);
++      }
++      return 0;
++}
++
++static void __exit cleanup_ramses(void)
++{
++      if (mymtd) {
++              del_mtd_partitions(mymtd);
++              map_destroy(mymtd);
++              if (parsed_parts)
++                      kfree(parsed_parts);
++      }
++      if (ramses_map.map_priv_1)
++              iounmap((void *)ramses_map.map_priv_1);
++#ifdef CONFIG_ARCH_RAMSES
++      FLASH_WRITE_PROTECT_ENABLE();
++#endif
++      return;
++}
++
++module_init(init_ramses);
++module_exit(cleanup_ramses);
++
+--- linux-2.4.21/drivers/net/irda/pxa_ir.c~pxa-irda
++++ linux-2.4.21/drivers/net/irda/pxa_ir.c
+@@ -38,6 +38,7 @@
+ #include <net/irda/wrapper.h>
+ #include <net/irda/irda_device.h>
++#include <asm/io.h>
+ #include <asm/irq.h>
+ #include <asm/dma.h>
+ #include <asm/hardware.h>
+@@ -786,6 +787,7 @@
+  * Suspend the IrDA interface.
+  */
++/*
+ static int pxa250_irda_shutdown(struct pxa250_irda *si)
+ {
+@@ -793,6 +795,7 @@
+    return 0;
+    
+ }
++*/
+ static int pxa250_irda_suspend(struct net_device *dev, int state)
+@@ -1141,11 +1144,11 @@
+       /* allocate consistent buffers for dma access
+        * buffers have to be aligned and situated in dma capable memory region;
+        */
+-      si->rxbuf_dma_virt = consistent_alloc(GFP_KERNEL | GFP_DMA ,HPSIR_MAX_RXLEN , &si->rxbuf_dma);
++      si->rxbuf_dma_virt = consistent_alloc(GFP_KERNEL | GFP_DMA ,HPSIR_MAX_RXLEN , &si->rxbuf_dma, 0);
+       if (! si->rxbuf_dma_virt )
+               goto err_rxbuf_dma;
+-      si->txbuf_dma_virt = consistent_alloc(GFP_KERNEL | GFP_DMA, HPSIR_MAX_TXLEN,  &si->txbuf_dma); 
++      si->txbuf_dma_virt = consistent_alloc(GFP_KERNEL | GFP_DMA, HPSIR_MAX_TXLEN,  &si->txbuf_dma, 0); 
+       if (! si->txbuf_dma_virt )
+               goto err_txbuf_dma;
+--- linux-2.4.21/drivers/net/smc91x.c~pxa-smc91x
++++ linux-2.4.21/drivers/net/smc91x.c
+@@ -46,10 +46,13 @@
+  .   12/20/01  Jeff Sutherland    initial port to Xscale PXA with DMA support
+  .   04/07/03  Nicolas Pitre      unified SMC91x driver, killed irq races,
+  .                                more bus abstraction, big cleanup, etc.
++ .   20/08/03  Holger Schurig     add ethtool support
+  ----------------------------------------------------------------------------*/
++#define DRV_NAME "smc91x"
++
+ static const char version[] =
+-      "smc91x.c: v1.0, mar 07 2003 by Nicolas Pitre <nico@cam.org>\n";
++      DRV_NAME ": v1.1 Aug 20 2003 by Nicolas Pitre <nico@cam.org>\n";
+ /* Debugging level */
+ #ifndef SMC_DEBUG
+@@ -67,6 +70,7 @@
+ #include <linux/timer.h>
+ #include <linux/errno.h>
+ #include <linux/ioport.h>
++#include <linux/ethtool.h>
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+@@ -78,6 +82,7 @@
+ #include <asm/io.h>
+ #include <asm/hardware.h>
+ #include <asm/irq.h>
++#include <asm/uaccess.h>
+ #include "smc91x.h"
+@@ -105,7 +110,7 @@
+ static int irq = SMC_IRQ;
+ #ifndef SMC_NOWAIT
+-# define SMC_NOWAIT           0
++# define SMC_NOWAIT           1
+ #endif
+ static int nowait = SMC_NOWAIT;
+@@ -116,6 +121,11 @@
+ MODULE_PARM_DESC(irq, "IRQ number");
+ MODULE_PARM_DESC(nowait, "set to 1 for no wait state");
++static int
++smc_read_phy_register(unsigned long ioaddr, int phyaddr, int phyreg);
++static void
++smc_write_phy_register( unsigned long ioaddr, int phyaddr,
++                      int phyreg, int phydata );
+ /*------------------------------------------------------------------------
+  .
+@@ -143,7 +153,12 @@
+  . but to the expense of reduced TX throughput and increased IRQ overhead.
+  . Note this is not a cure for a too slow data bus or too high IRQ latency.
+  */
+-#define THROTTLE_TX_PKTS      0
++#define THROTTLE_TX_PKTS      1
++
++/*
++ . This defines if we want to compile ethtool support into the driver
++*/
++#define WITH_ETHTOOL 1
+ /* store this information for the driver.. */
+@@ -310,14 +325,14 @@
+       if (nowait)
+               SMC_SET_CONFIG( SMC_GET_CONFIG() | CONFIG_NO_WAIT );
+-#ifdef POWER_DOWN
++#if POWER_DOWN
+       /* Release from possible power-down state */
+       /* Configuration register is not affected by Soft Reset */
+       SMC_SELECT_BANK( 1 );
+       SMC_SET_CONFIG( SMC_GET_CONFIG() | CONFIG_EPH_POWER_EN );
+       status = smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG);
+       status &= ~PHY_CNTL_PDN;
+-      smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG);
++      smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, status);
+ #endif
+       /* this should pause enough for the chip to be happy */
+@@ -390,10 +405,10 @@
+       SMC_SET_RCR( RCR_CLEAR );
+       SMC_SET_TCR( TCR_CLEAR );
+-#ifdef POWER_DOWN
++#if POWER_DOWN
+       status = smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG);
+       status |= PHY_CNTL_PDN;
+-      smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG);
++      smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, status);
+       /* finally, shut the chip down */
+       SMC_SELECT_BANK( 1 );
+@@ -1628,14 +1643,18 @@
+       // Setup the default Register Modes
+       lp->tcr_cur_mode = TCR_DEFAULT;
+       lp->rcr_cur_mode = RCR_DEFAULT;
+-      lp->rpc_cur_mode = RPC_DEFAULT;
+       /* Set default parameters */
+ #ifdef CONFIG_ARCH_RAMSES
+-      lp->ctl_autoneg = 0;
+-      lp->ctl_rfduplx = 0;
++      lp->rpc_cur_mode = (RPC_ANEG | (RPC_LED_10 << RPC_LSXA_SHFT) | (RPC_LED_TX_RX << RPC_LSXB_SHFT) | RPC_DPLX);
++
++      // 10 MBit/S, auto-negotiation only for 10 MB/s
++      lp->ctl_autoneg = 1;
++      lp->ctl_rfduplx = 1;
+       lp->ctl_rspeed = 10;
+ #else
++      lp->rpc_cur_mode = RPC_DEFAULT;
++
+       lp->ctl_autoneg = 1;
+       lp->ctl_rfduplx = 1;
+       lp->ctl_rspeed = 100;
+@@ -1680,6 +1699,127 @@
+       return 0;
+ }
++/*----------------------------------------------------
++ . smc_ioctl
++ .
++ . This ioctl is currently only used by ethtool(8) to
++ . access the serial EEPROM
++ -----------------------------------------------------*/
++ 
++#if WITH_ETHTOOL
++
++#define SMC91x_EEPROM_SIZE (0x40*2)
++
++u16 smc_eeprom_read(long ioaddr, u16 location)
++{
++      u16 val;
++      u16 oldBank;
++      u16 oldPtr;
++
++      cli();
++      // Save chip settings
++      oldBank = SMC_CURRENT_BANK();
++      SMC_SELECT_BANK( 2 );
++      oldPtr = SMC_GET_PTR();
++
++      // Set location in EEPROM to be read
++      SMC_SET_PTR(location);
++
++      // Set EEPROM_SELECT and RELOAD bits in control register
++      SMC_SELECT_BANK( 1 );
++      val = SMC_GET_CTL();
++      SMC_SET_CTL(val | CTL_EEPROM_SELECT | CTL_RELOAD);
++
++      // Wait until RELEAD is finished
++      while (SMC_GET_CTL() & CTL_RELOAD) ;
++
++      // Get EEPROM data
++      val = SMC_inw(ioaddr, GP_REG);
++
++      // Restore chip settings
++      SMC_SELECT_BANK( 2 );
++      SMC_SET_PTR(oldPtr);
++      SMC_SELECT_BANK( oldBank );
++      sti();
++
++      return val;
++}
++
++static int smc_get_eeprom(struct net_device *dev, u8 *buf)
++{
++      int i;
++      u16 *ebuf = (u16 *)buf;
++
++      for (i = 0; i < SMC91x_EEPROM_SIZE/2; i++) {
++              ebuf[i] = smc_eeprom_read(dev->base_addr, i);
++      }
++      return 0;
++}
++
++static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
++{
++      u32 etcmd;
++      int ret = -EINVAL;
++
++      if (cmd != SIOCETHTOOL)
++              return -EOPNOTSUPP;
++
++      if (get_user(etcmd, (u32 *)rq->ifr_data))
++              return -EFAULT;
++
++      switch (etcmd) {
++
++      /* Get driver info */
++      case ETHTOOL_GDRVINFO: {
++              struct ethtool_drvinfo edrv;
++
++              memset(&edrv, 0, sizeof(edrv));
++              edrv.cmd = etcmd;
++              strcpy(edrv.driver, DRV_NAME);
++              sprintf(edrv.bus_info, "ISA:%8.8lx:%d", dev->base_addr, dev->irq);
++              edrv.eedump_len = SMC91x_EEPROM_SIZE;
++              ret = copy_to_user(rq->ifr_data, &edrv, sizeof(edrv)) ? -EFAULT : 0;
++              break;
++      }
++
++      /* Get EEPROM data */
++      case ETHTOOL_GEEPROM: {
++              struct ethtool_eeprom eeprom;
++              u8 eebuf[SMC91x_EEPROM_SIZE];
++              int r;
++
++              if (copy_from_user(&eeprom, rq->ifr_data, sizeof(eeprom)))
++                      return -EFAULT;
++
++              if (eeprom.offset > eeprom.offset+eeprom.len)
++                      return -EINVAL;
++
++              if ((eeprom.offset+eeprom.len) > SMC91x_EEPROM_SIZE) {
++                      eeprom.len = SMC91x_EEPROM_SIZE-eeprom.offset;
++              }
++              eeprom.magic = 0;
++              if (copy_to_user(rq->ifr_data, &eeprom, sizeof(eeprom)))
++                      return -EFAULT;
++
++              rq->ifr_data += offsetof(struct ethtool_eeprom, data);
++
++              r = smc_get_eeprom(dev, eebuf);
++
++              if (r)
++                      return r;
++              if (copy_to_user(rq->ifr_data, eebuf+eeprom.offset, eeprom.len))
++                      return -EFAULT;
++              return 0;
++
++      }
++      }
++
++      return ret;
++}
++
++#endif
++
++
+ /*------------------------------------------------------------
+  . Get the current statistics.
+  . This may be called with the card open or closed.
+@@ -1925,6 +2065,9 @@
+       dev->watchdog_timeo             = HZ/10;
+       dev->get_stats                  = smc_query_statistics;
+       dev->set_multicast_list         = smc_set_multicast_list;
++#if WITH_ETHTOOL
++      dev->do_ioctl                   = smc_ioctl;
++#endif
+       return 0;
+@@ -1961,12 +2104,17 @@
+               smc_shutdown(global_dev);
+               break;
+       case PM_RESUME:
++              udelay(5000);
+               smc_reset(global_dev);
+               smc_enable(global_dev);
+               SMC_SELECT_BANK( 1 );
+               SMC_SET_MAC_ADDR(global_dev->dev_addr);
+-              if (lp->version >= 0x70)
+-                      smc_phy_configure(global_dev);
++              if (global_dev->flags & IFF_UP) {
++                      if (lp->version >= 0x70)
++                              smc_phy_configure(global_dev);
++              } else {
++                      smc_shutdown(global_dev);
++              }
+               break;
+       }
+       return 0;
+@@ -2054,6 +2202,15 @@
+               int ioaddr = RAMSES_ETH_BASE + 0x300;
+               global_dev->irq = SMC_IRQ;
+               ret = smc_probe(global_dev, ioaddr);
++#ifdef POWER_DOWN
++              smc_shutdown(global_dev);
++#endif
++      }
++#elif defined(CONFIG_ARCH_RAMSES)
++      {
++              int ioaddr = RAMSES_ETH_BASE + 0x300;
++              global_dev->irq = SMC_IRQ;
++              ret = smc_probe(global_dev, ioaddr);
+       }
+ #else
+       if (global_dev->base_addr == -1) {
+@@ -2083,7 +2240,11 @@
+ #ifdef CONFIG_PM
+       if (ret == 0) {
+               struct smc_local *lp = (struct smc_local *)global_dev->priv;
++#ifdef PM_DEBUG
++              lp->pm = pm_register(PM_SYS_UNKNOWN, 0x73393178, smc_pm_callback, "smc91x");
++#else
+               lp->pm = pm_register(PM_SYS_UNKNOWN, 0x73393178, smc_pm_callback);
++#endif
+       }
+ #endif
+--- linux-2.4.21/drivers/net/smc91x.h~ramses-smc91x
++++ linux-2.4.21/drivers/net/smc91x.h
+@@ -79,6 +79,11 @@
+ #include <asm/arch/ramses.h>
+ #define SMC_IOADDR            (RAMSES_ETH_PHYS + 0x300)
+ #define SMC_IRQ                       ETHERNET_IRQ
++      
++#elif CONFIG_ARCH_RAMSES
++#include <asm/arch/ramses.h>
++#define SMC_IOADDR            (RAMSES_ETH_PHYS + 0x300)
++#define SMC_IRQ                       ETHERNET_IRQ
+ #endif
+       
+ #define SMC_CAN_USE_8BIT      1
+--- linux-2.4.21/drivers/net/wireless/hermes.c~orinoco013e
++++ linux-2.4.21/drivers/net/wireless/hermes.c
+@@ -52,7 +52,6 @@
+ #include "hermes.h"
+-static char version[] __initdata = "hermes.c: 4 Dec 2002 David Gibson <hermes@gibson.dropbear.id.au>";
+ MODULE_DESCRIPTION("Low-level driver helper for Lucent Hermes chipset and Prism II HFA384x wireless MAC controller");
+ MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
+ #ifdef MODULE_LICENSE
+@@ -226,7 +225,8 @@
+  * Returns: < 0 on internal error, 0 on success, > 0 on error returned by the firmware
+  *
+  * Callable from any context, but locking is your problem. */
+-int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, hermes_response_t *resp)
++int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
++                    hermes_response_t *resp)
+ {
+       int err;
+       int k;
+@@ -469,13 +469,17 @@
+       err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS, rid, NULL);
+       if (err)
+-              goto out;
++              return err;
+       err = hermes_bap_seek(hw, bap, rid, 0);
+       if (err)
+-              goto out;
++              return err;
+       rlength = hermes_read_reg(hw, dreg);
++
++      if (! rlength)
++              return -ENOENT;
++
+       rtype = hermes_read_reg(hw, dreg);
+       if (length)
+@@ -495,8 +499,7 @@
+       nwords = min((unsigned)rlength - 1, bufsize / 2);
+       hermes_read_words(hw, dreg, buf, nwords);
+- out:
+-      return err;
++      return 0;
+ }
+ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, 
+@@ -511,7 +514,7 @@
+       err = hermes_bap_seek(hw, bap, rid, 0);
+       if (err)
+-              goto out;
++              return err;
+       hermes_write_reg(hw, dreg, length);
+       hermes_write_reg(hw, dreg, rid);
+@@ -523,7 +526,6 @@
+       err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE, 
+                               rid, NULL);
+- out:
+       return err;
+ }
+@@ -539,9 +541,12 @@
+ static int __init init_hermes(void)
+ {
+-      printk(KERN_DEBUG "%s\n", version);
+-
+       return 0;
+ }
++static void __exit exit_hermes(void)
++{
++}
++
+ module_init(init_hermes);
++module_exit(exit_hermes);
+--- linux-2.4.21/drivers/net/wireless/hermes.h~orinoco013e
++++ linux-2.4.21/drivers/net/wireless/hermes.h
+@@ -250,7 +250,6 @@
+       u16 scanreason;             /* ??? */
+       struct hermes_scan_apinfo aps[35];        /* Scan result */
+ } __attribute__ ((packed));
+-
+ #define HERMES_LINKSTATUS_NOT_CONNECTED   (0x0000)  
+ #define HERMES_LINKSTATUS_CONNECTED       (0x0001)
+ #define HERMES_LINKSTATUS_DISCONNECTED    (0x0002)
+@@ -278,7 +277,7 @@
+ /* Basic control structure */
+ typedef struct hermes {
+-      ulong iobase;
++      unsigned long iobase;
+       int io_space; /* 1 if we IO-mapped IO, 0 for memory-mapped IO? */
+ #define HERMES_IO     1
+ #define HERMES_MEM    0
+@@ -368,7 +367,7 @@
+       if (hw->io_space) {
+               insw(hw->iobase + off, buf, count);
+       } else {
+-              int i;
++              unsigned i;
+               u16 *p;
+               /* This needs to *not* byteswap (like insw()) but
+@@ -388,7 +387,7 @@
+       if (hw->io_space) {
+               outsw(hw->iobase + off, buf, count);
+       } else {
+-              int i;
++              unsigned i;
+               const u16 *p;
+               /* This needs to *not* byteswap (like outsw()) but
+@@ -398,6 +397,21 @@
+               for (i = 0, p = buf; i < count; i++) {
+                       writew(le16_to_cpu(*p++), hw->iobase + off);
+               }
++      }
++}
++
++static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count)
++{
++      unsigned i;
++
++      off = off << hw->reg_spacing;;
++
++      if (hw->io_space) {
++              for (i = 0; i < count; i++)
++                      outw(0, hw->iobase + off);
++      } else {
++              for (i = 0; i < count; i++)
++                      writew(0, hw->iobase + off);
+       }
+ }
+--- linux-2.4.21/drivers/net/wireless/ieee802_11.h~orinoco013e
++++ linux-2.4.21/drivers/net/wireless/ieee802_11.h
+@@ -9,6 +9,8 @@
+    bytes is allowed, which is a bit confusing, I suspect this
+    represents the 2304 bytes of real data, plus a possible 8 bytes of
+    WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
++
++
+ #define IEEE802_11_HLEN                       30
+ #define IEEE802_11_FRAME_LEN          (IEEE802_11_DATA_LEN + IEEE802_11_HLEN)
+--- linux-2.4.21/drivers/net/wireless/orinoco.c~orinoco013e
++++ linux-2.4.21/drivers/net/wireless/orinoco.c
+@@ -1,4 +1,4 @@
+-/* orinoco.c 0.13b    - (formerly known as dldwd_cs.c and orinoco_cs.c)
++/* orinoco.c 0.13e    - (formerly known as dldwd_cs.c and orinoco_cs.c)
+  *
+  * A driver for Hermes or Prism 2 chipset based PCMCIA wireless
+  * adaptors, with Lucent/Agere, Intersil or Symbol firmware.
+@@ -117,7 +117,7 @@
+  *    o Init of priv->tx_rate_ctrl in firmware specific section.
+  *    o Prism2/Symbol rate, upto should be 0xF and not 0x15. Doh !
+  *    o Spectrum card always need cor_reset (for every reset)
+- *    o Fix cor_reset to not loose bit 7 in the register
++ *    o Fix cor_reset to not lose bit 7 in the register
+  *    o flush_stale_links to remove zombie Pcmcia instances
+  *    o Ack previous hermes event before reset
+  *            Me (with my little hands)
+@@ -289,7 +289,7 @@
+  *      which are used as the dev->open, dev->stop, priv->reset
+  *      callbacks if none are specified when alloc_orinocodev() is
+  *      called.
+- *    o Removed orinoco_plx_interupt() and orinoco_pci_interrupt().
++ *    o Removed orinoco_plx_interrupt() and orinoco_pci_interrupt().
+  *      They didn't do anything.
+  *
+  * v0.12 -> v0.12a - 4 Jul 2002 - David Gibson
+@@ -345,13 +345,54 @@
+  *      we are connected (avoids cofusing the firmware), and only
+  *      give LINKSTATUS printk()s if the status has changed.
+  *
++ * v0.13b -> v0.13c - 11 Mar 2003 - David Gibson
++ *    o Cleanup: use dev instead of priv in various places.
++ *    o Bug fix: Don't ReleaseConfiguration on RESET_PHYSICAL event
++ *      if we're in the middle of a (driver initiated) hard reset.
++ *    o Bug fix: ETH_ZLEN is supposed to include the header
++ *      (Dionysus Blazakis & Manish Karir)
++ *    o Convert to using workqueues instead of taskqueues (and
++ *      backwards compatibility macros for pre 2.5.41 kernels).
++ *    o Drop redundant (I think...) MOD_{INC,DEC}_USE_COUNT in
++ *      airport.c
++ *    o New orinoco_tmd.c init module from Joerg Dorchain for
++ *      TMD7160 based PCI to PCMCIA bridges (similar to
++ *      orinoco_plx.c).
++ *
++ * v0.13c -> v0.13d - 22 Apr 2003 - David Gibson
++ *    o Make hw_unavailable a counter, rather than just a flag, this
++ *      is necessary to avoid some races (such as a card being
++ *      removed in the middle of orinoco_reset().
++ *    o Restore Release/RequestConfiguration in the PCMCIA event handler
++ *      when dealing with a driver initiated hard reset.  This is
++ *      necessary to prevent hangs due to a spurious interrupt while
++ *      the reset is in progress.
++ *    o Clear the 802.11 header when transmitting, even though we
++ *      don't use it.  This fixes a long standing bug on some
++ *      firmwares, which seem to get confused if that isn't done.
++ *    o Be less eager to de-encapsulate SNAP frames, only do so if
++ *      the OUI is 00:00:00 or 00:00:f8, leave others alone.  The old
++ *      behaviour broke CDP (Cisco Discovery Protocol).
++ *    o Use dev instead of priv for free_irq() as well as
++ *      request_irq() (oops).
++ *    o Attempt to reset rather than giving up if we get too many
++ *      IRQs.
++ *    o Changed semantics of __orinoco_down() so it can be called
++ *      safely with hw_unavailable set.  It also now clears the
++ *      linkstatus (since we're going to have to reassociate).
++ *
++ * v0.13d -> v0.13e - 12 May 2003 - David Gibson
++ *    o Support for post-2.5.68 return values from irq handler.
++ *    o Fixed bug where underlength packets would be double counted
++ *      in the rx_dropped statistics.
++ *    o Provided a module parameter to suppress linkstatus messages.
++ *
+  * TODO
+-
+  *    o New wireless extensions API (patch from Moustafa
+- *      Youssef, updated by Jim Carter).
+- *    o Fix PCMCIA hard resets with pcmcia-cs.
++ *      Youssef, updated by Jim Carter and Pavel Roskin).
+  *    o Handle de-encapsulation within network layer, provide 802.11
+  *      headers (patch from Thomas 'Dent' Mirlacher)
++ *    o RF monitor mode support
+  *    o Fix possible races in SPY handling.
+  *    o Disconnect wireless extensions from fundamental configuration.
+  *    o (maybe) Software WEP support (patch from Stano Meduna).
+@@ -373,27 +414,27 @@
+  * flag after taking the lock, and if it is set, give up on whatever
+  * they are doing and drop the lock again.  The orinoco_lock()
+  * function handles this (it unlocks and returns -EBUSY if
+- * hw_unavailable is true). */
++ * hw_unavailable is non-zero). */
+ #include <linux/config.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+-#include <linux/sched.h>
+ #include <linux/ptrace.h>
+ #include <linux/slab.h>
+ #include <linux/string.h>
+ #include <linux/timer.h>
+ #include <linux/ioport.h>
+-#include <asm/uaccess.h>
+-#include <asm/io.h>
+-#include <asm/system.h>
+ #include <linux/netdevice.h>
+ #include <linux/if_arp.h>
+ #include <linux/etherdevice.h>
+ #include <linux/wireless.h>
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/system.h>
++
+ #include "hermes.h"
+ #include "hermes_rid.h"
+ #include "orinoco.h"
+@@ -416,6 +457,9 @@
+ EXPORT_SYMBOL(orinoco_debug);
+ #endif
++static int suppress_linkstatus; /* = 0 */
++MODULE_PARM(suppress_linkstatus, "i");
++
+ /********************************************************************/
+ /* Compile time configuration and compatibility stuff               */
+ /********************************************************************/
+@@ -443,8 +487,10 @@
+ #define USER_BAP              0
+ #define IRQ_BAP                       1
+ #define MAX_IRQLOOPS_PER_IRQ  10
+-#define MAX_IRQLOOPS_PER_JIFFY        (20000/HZ)      /* Based on a guestimate of how many events the
+-                                                 device could legitimately generate */
++#define MAX_IRQLOOPS_PER_JIFFY        (20000/HZ) /* Based on a guestimate of
++                                          * how many events the
++                                          * device could
++                                          * legitimately generate */
+ #define SMALL_KEY_SIZE                5
+ #define LARGE_KEY_SIZE                13
+ #define TX_NICBUF_SIZE_BUG    1585            /* Bug in Symbol firmware */
+@@ -480,8 +526,8 @@
+       {10,  1,  1,  1},
+       {20,  0,  2,  2},
+       {20,  1,  6,  3},
+-      {55, 0,  4,  4},
+-      {55, 1,  7,  7},
++      {55,  0,  4,  4},
++      {55,  1,  7,  7},
+       {110, 0,  5,  8},
+ };
+ #define BITRATE_TABLE_SIZE (sizeof(bitrate_table) / sizeof(bitrate_table[0]))
+@@ -522,7 +568,7 @@
+ /* Hardware control routines */
+-static int __orinoco_program_rids(struct orinoco_private *priv);
++static int __orinoco_program_rids(struct net_device *dev);
+ static int __orinoco_hw_set_bitrate(struct orinoco_private *priv);
+ static int __orinoco_hw_setup_wep(struct orinoco_private *priv);
+@@ -535,37 +581,17 @@
+ static void __orinoco_set_multicast_list(struct net_device *dev);
+ /* Interrupt handling routines */
+-static void __orinoco_ev_tick(struct orinoco_private *priv, hermes_t *hw);
+-static void __orinoco_ev_wterr(struct orinoco_private *priv, hermes_t *hw);
+-static void __orinoco_ev_infdrop(struct orinoco_private *priv, hermes_t *hw);
+-static void __orinoco_ev_info(struct orinoco_private *priv, hermes_t *hw);
+-static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw);
+-static void __orinoco_ev_txexc(struct orinoco_private *priv, hermes_t *hw);
+-static void __orinoco_ev_tx(struct orinoco_private *priv, hermes_t *hw);
+-static void __orinoco_ev_alloc(struct orinoco_private *priv, hermes_t *hw);
++static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw);
++static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw);
++static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw);
++static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw);
++static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw);
++static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw);
++static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw);
++static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw);
+ /* ioctl() routines */
+-static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq);
+-static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq);
+-static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq);
+-static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq);
+-static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq);
+-static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq);
+-static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq);
+-static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq);
+-static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq);
+-static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq);
+-static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq);
+-static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq);
+-static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq);
+-static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *frq);
+-static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *frq);
+-static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq);
+-static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq);
+-static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq);
+-static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq);
+-
+-static int orinoco_debug_dump_recs(struct orinoco_private *priv);
++static int orinoco_debug_dump_recs(struct net_device *dev);
+ /********************************************************************/
+ /* Function prototypes                                              */
+@@ -577,7 +603,7 @@
+       struct hermes *hw = &priv->hw;
+       int err;
+-      err = __orinoco_program_rids(priv);
++      err = __orinoco_program_rids(dev);
+       if (err) {
+               printk(KERN_ERR "%s: Error %d configuring card\n",
+                      dev->name, err);
+@@ -606,14 +632,25 @@
+       netif_stop_queue(dev);
+-      err = hermes_disable_port(hw, 0);
+-      if (err) {
+-              printk(KERN_ERR "%s: Error %d disabling MAC port\n",
+-                     dev->name, err);
+-              return err;
++      if (! priv->hw_unavailable) {
++              if (! priv->broken_disableport) {
++                      err = hermes_disable_port(hw, 0);
++                      if (err) {
++                              /* Some firmwares (e.g. Intersil 1.3.x) seem
++                               * to have problems disabling the port, oh
++                               * well, too bad. */
++                              printk(KERN_WARNING "%s: Error %d disabling MAC port\n",
++                                     dev->name, err);
++                              priv->broken_disableport = 1;
++                      }
++              }
++              hermes_set_irqmask(hw, 0);
++              hermes_write_regn(hw, EVACK, 0xffff);
+       }
+-      hermes_set_irqmask(hw, 0);
+-      hermes_write_regn(hw, EVACK, 0xffff);
++      
++      /* firmware will have to reassociate */
++      priv->last_linkstatus = 0xffff;
++      priv->connected = 0;
+       return 0;
+ }
+@@ -656,38 +693,38 @@
+       if (err)
+               return err;
+-        priv->open = 1;
+-
+       err = __orinoco_up(dev);
++      if (! err)
++              priv->open = 1;
++
+       orinoco_unlock(priv, &flags);
+       return err;
+ }
+-static int orinoco_stop(struct net_device *dev)
++int orinoco_stop(struct net_device *dev)
+ {
+       struct orinoco_private *priv = dev->priv;
+       int err = 0;
+       /* We mustn't use orinoco_lock() here, because we need to be
+-         able to close the interface, even if hw_unavailable is set
++         able to close the interface even if hw_unavailable is set
+          (e.g. as we're released after a PC Card removal) */
+       spin_lock_irq(&priv->lock);
+       priv->open = 0;
+-      if (! priv->hw_unavailable)
+-              err = __orinoco_down(dev);
++      err = __orinoco_down(dev);
+       spin_unlock_irq(&priv->lock);
+       return err;
+ }
+-static int __orinoco_program_rids(struct orinoco_private *priv)
++static int __orinoco_program_rids(struct net_device *dev)
+ {
+-      struct net_device *dev = priv->ndev;
++      struct orinoco_private *priv = dev->priv;
+       hermes_t *hw = &priv->hw;
+       int err;
+       struct hermes_idstring idbuf;
+@@ -873,51 +910,84 @@
+ }
+ /* xyzzy */
+-static int orinoco_reconfigure(struct orinoco_private *priv)
++static int orinoco_reconfigure(struct net_device *dev)
+ {
++      struct orinoco_private *priv = dev->priv;
+       struct hermes *hw = &priv->hw;
+       unsigned long flags;
+       int err = 0;
+-      orinoco_lock(priv, &flags);
++      if (priv->broken_disableport) {
++              schedule_work(&priv->reset_work);
++              return 0;
++      }
++
++      err = orinoco_lock(priv, &flags);
++      if (err)
++              return err;
++              
+       err = hermes_disable_port(hw, 0);
+       if (err) {
+-              printk(KERN_ERR "%s: Unable to disable port in orinco_reconfigure()\n",
+-                     priv->ndev->name);
++              printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n",
++                     dev->name);
++              priv->broken_disableport = 1;
+               goto out;
+       }
+-      err = __orinoco_program_rids(priv);
+-      if (err)
++      err = __orinoco_program_rids(dev);
++      if (err) {
++              printk(KERN_WARNING "%s: Unable to reconfigure card\n",
++                     dev->name);
+               goto out;
++      }
+       err = hermes_enable_port(hw, 0);
+       if (err) {
+-              printk(KERN_ERR "%s: Unable to enable port in orinco_reconfigure()\n",
+-                     priv->ndev->name);
++              printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
++                     dev->name);
+               goto out;
+       }
+  out:
++      if (err) {
++              printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
++              schedule_work(&priv->reset_work);
++              err = 0;
++      }
++
+       orinoco_unlock(priv, &flags);
+       return err;
+ }
+ /* This must be called from user context, without locks held - use
+- * schedule_task() */
++ * schedule_work() */
+ static void orinoco_reset(struct net_device *dev)
+ {
+       struct orinoco_private *priv = dev->priv;
++      struct hermes *hw = &priv->hw;
+       int err;
+       unsigned long flags;
+       err = orinoco_lock(priv, &flags);
+       if (err)
++              /* When the hardware becomes available again, whatever
++               * detects that is responsible for re-initializing
++               * it. So no need for anything further*/
+               return;
+-      priv->hw_unavailable = 1;
++      netif_stop_queue(dev);
++
++      /* Shut off interrupts.  Depending on what state the hardware
++       * is in, this might not work, but we'll try anyway */
++      hermes_set_irqmask(hw, 0);
++      hermes_write_regn(hw, EVACK, 0xffff);
++
++      priv->hw_unavailable++;
++      priv->last_linkstatus = 0xffff; /* firmware will have to reassociate */
++      priv->connected = 0;
++
+       orinoco_unlock(priv, &flags);
+       if (priv->hard_reset)
+@@ -936,18 +1006,22 @@
+               return;
+       }
+-      spin_lock_irqsave(&priv->lock, flags);
++      spin_lock_irq(&priv->lock); /* This has to be called from user context */
+-      priv->hw_unavailable = 0;
++      priv->hw_unavailable--;
+-      err = __orinoco_up(dev);
+-      if (err) {
+-              printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n",
+-                     dev->name, err);
+-      } else
+-              dev->trans_start = jiffies;
++      /* priv->open or priv->hw_unavailable might have changed while
++       * we dropped the lock */
++      if (priv->open && (! priv->hw_unavailable)) {
++              err = __orinoco_up(dev);
++              if (err) {
++                      printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n",
++                             dev->name, err);
++              } else
++                      dev->trans_start = jiffies;
++      }
+-      orinoco_unlock(priv, &flags);
++      spin_unlock_irq(&priv->lock);
+       return;
+ }
+@@ -979,10 +1053,18 @@
+       }
+ }
++/* Does the frame have a SNAP header indicating it should be
++ * de-encapsulated to Ethernet-II? */
+ static inline int
+-is_snap(struct header_struct *hdr)
++is_ethersnap(struct header_struct *hdr)
+ {
+-      return (hdr->dsap == 0xAA) && (hdr->ssap == 0xAA) && (hdr->ctrl == 0x3);
++      /* We de-encapsulate all packets which, a) have SNAP headers
++       * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
++       * and where b) the OUI of the SNAP header is 00:00:00 or
++       * 00:00:f8 - we need both because different APs appear to use
++       * different OUIs for some reason */
++      return (memcmp(&hdr->dsap, &encaps_hdr, 5) == 0)
++              && ( (hdr->oui[2] == 0x00) || (hdr->oui[2] == 0xf8) );
+ }
+ static void
+@@ -1140,7 +1222,8 @@
+       return 0;
+ }
+-static int orinoco_hw_get_bssid(struct orinoco_private *priv, char buf[ETH_ALEN])
++static int orinoco_hw_get_bssid(struct orinoco_private *priv,
++                              char buf[ETH_ALEN])
+ {
+       hermes_t *hw = &priv->hw;
+       int err = 0;
+@@ -1159,7 +1242,7 @@
+ }
+ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
+-                            char buf[IW_ESSID_MAX_SIZE+1])
++                              char buf[IW_ESSID_MAX_SIZE+1])
+ {
+       hermes_t *hw = &priv->hw;
+       int err = 0;
+@@ -1236,9 +1319,8 @@
+       }
+       if ( (channel < 1) || (channel > NUM_CHANNELS) ) {
+-              struct net_device *dev = priv->ndev;
+-
+-              printk(KERN_WARNING "%s: Channel out of range (%d)!\n", dev->name, channel);
++              printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
++                     priv->ndev->name, channel);
+               err = -EBUSY;
+               goto out;
+@@ -1253,8 +1335,8 @@
+       return err ? err : freq;
+ }
+-static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, int *numrates,
+-                                  s32 *rates, int max)
++static int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
++                                    int *numrates, s32 *rates, int max)
+ {
+       hermes_t *hw = &priv->hw;
+       struct hermes_idstring list;
+@@ -1287,9 +1369,6 @@
+ }
+ #if 0
+-#ifndef ORINOCO_DEBUG
+-static inline void show_rx_frame(struct orinoco_rxframe_hdr *frame) {}
+-#else
+ static void show_rx_frame(struct orinoco_rxframe_hdr *frame)
+ {
+       printk(KERN_DEBUG "RX descriptor:\n");
+@@ -1346,17 +1425,16 @@
+              frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]);
+       printk(KERN_DEBUG "  ethertype  = 0x%04x\n", frame->ethertype);
+ }
+-#endif
+-#endif
++#endif /* 0 */
+ /*
+  * Interrupt handler
+  */
+-void orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++irqreturn_t orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+ {
+-      struct orinoco_private *priv = (struct orinoco_private *) dev_id;
++      struct net_device *dev = (struct net_device *)dev_id;
++      struct orinoco_private *priv = dev->priv;
+       hermes_t *hw = &priv->hw;
+-      struct net_device *dev = priv->ndev;
+       int count = MAX_IRQLOOPS_PER_IRQ;
+       u16 evstat, events;
+       /* These are used to detect a runaway interrupt situation */
+@@ -1367,12 +1445,17 @@
+       unsigned long flags;
+       if (orinoco_lock(priv, &flags) != 0) {
+-              /* If hw is unavailable */
+-              return;
++              /* If hw is unavailable - we don't know if the irq was
++               * for us or not */
++              return IRQ_HANDLED;
+       }
+       evstat = hermes_read_regn(hw, EVSTAT);
+       events = evstat & hw->inten;
++      if (! events) {
++              orinoco_unlock(priv, &flags);
++              return IRQ_NONE;
++      }
+       
+       if (jiffies != last_irq_jiffy)
+               loops_this_jiffy = 0;
+@@ -1380,11 +1463,11 @@
+       while (events && count--) {
+               if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) {
+-                      printk(KERN_CRIT "%s: IRQ handler is looping too \
+-much! Shutting down.\n",
+-                             dev->name);
+-                      /* Perform an emergency shutdown */
++                      printk(KERN_WARNING "%s: IRQ handler is looping too "
++                             "much! Resetting.\n", dev->name);
++                      /* Disable interrupts for now */
+                       hermes_set_irqmask(hw, 0);
++                      schedule_work(&priv->reset_work);
+                       break;
+               }
+@@ -1395,21 +1478,21 @@
+               }
+               if (events & HERMES_EV_TICK)
+-                      __orinoco_ev_tick(priv, hw);
++                      __orinoco_ev_tick(dev, hw);
+               if (events & HERMES_EV_WTERR)
+-                      __orinoco_ev_wterr(priv, hw);
++                      __orinoco_ev_wterr(dev, hw);
+               if (events & HERMES_EV_INFDROP)
+-                      __orinoco_ev_infdrop(priv, hw);
++                      __orinoco_ev_infdrop(dev, hw);
+               if (events & HERMES_EV_INFO)
+-                      __orinoco_ev_info(priv, hw);
++                      __orinoco_ev_info(dev, hw);
+               if (events & HERMES_EV_RX)
+-                      __orinoco_ev_rx(priv, hw);
++                      __orinoco_ev_rx(dev, hw);
+               if (events & HERMES_EV_TXEXC)
+-                      __orinoco_ev_txexc(priv, hw);
++                      __orinoco_ev_txexc(dev, hw);
+               if (events & HERMES_EV_TX)
+-                      __orinoco_ev_tx(priv, hw);
++                      __orinoco_ev_tx(dev, hw);
+               if (events & HERMES_EV_ALLOC)
+-                      __orinoco_ev_alloc(priv, hw);
++                      __orinoco_ev_alloc(dev, hw);
+               
+               hermes_write_regn(hw, EVACK, events);
+@@ -1418,30 +1501,34 @@
+       };
+       orinoco_unlock(priv, &flags);
++      return IRQ_HANDLED;
+ }
+-static void __orinoco_ev_tick(struct orinoco_private *priv, hermes_t *hw)
++static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw)
+ {
+-      printk(KERN_DEBUG "%s: TICK\n", priv->ndev->name);
++      printk(KERN_DEBUG "%s: TICK\n", dev->name);
+ }
+-static void __orinoco_ev_wterr(struct orinoco_private *priv, hermes_t *hw)
++static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw)
+ {
+       /* This seems to happen a fair bit under load, but ignoring it
+          seems to work fine...*/
+       printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n",
+-             priv->ndev->name);
++             dev->name);
+ }
+-static void __orinoco_ev_infdrop(struct orinoco_private *priv, hermes_t *hw)
++static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
+ {
+-      printk(KERN_WARNING "%s: Information frame lost.\n", priv->ndev->name);
++      printk(KERN_WARNING "%s: Information frame lost.\n", dev->name);
+ }
+ static void print_linkstatus(struct net_device *dev, u16 status)
+ {
+       char * s;
++      if (suppress_linkstatus)
++              return;
++
+       switch (status) {
+       case HERMES_LINKSTATUS_NOT_CONNECTED:
+               s = "Not Connected";
+@@ -1472,9 +1559,9 @@
+              dev->name, s, status);
+ }
+-static void __orinoco_ev_info(struct orinoco_private *priv, hermes_t *hw)
++static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
+ {
+-      struct net_device *dev = priv->ndev;
++      struct orinoco_private *priv = dev->priv;
+       u16 infofid;
+       struct {
+               u16 len;
+@@ -1573,9 +1660,9 @@
+       }
+ }
+-static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw)
++static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
+ {
+-      struct net_device *dev = priv->ndev;
++      struct orinoco_private *priv = dev->priv;
+       struct net_device_stats *stats = &priv->stats;
+       struct iw_statistics *wstats = &priv->wstats;
+       struct sk_buff *skb = NULL;
+@@ -1664,14 +1751,13 @@
+        * So, check ourselves */
+       if(((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
+          ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
+-         is_snap(&hdr)) {
++         is_ethersnap(&hdr)) {
+               /* These indicate a SNAP within 802.2 LLC within
+                  802.11 frame which we'll need to de-encapsulate to
+                  the original EthernetII frame. */
+               if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */
+                       stats->rx_length_errors++;
+-                      stats->rx_dropped++;
+                       goto drop;
+               }
+@@ -1726,9 +1812,9 @@
+       return;
+ }
+-static void __orinoco_ev_txexc(struct orinoco_private *priv, hermes_t *hw)
++static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
+ {
+-      struct net_device *dev = priv->ndev;
++      struct orinoco_private *priv = dev->priv;
+       struct net_device_stats *stats = &priv->stats;
+       u16 fid = hermes_read_regn(hw, TXCOMPLFID);
+       struct hermes_tx_descriptor desc;
+@@ -1752,8 +1838,9 @@
+       hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
+ }
+-static void __orinoco_ev_tx(struct orinoco_private *priv, hermes_t *hw)
++static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
+ {
++      struct orinoco_private *priv = dev->priv;
+       struct net_device_stats *stats = &priv->stats;
+       stats->tx_packets++;
+@@ -1761,9 +1848,10 @@
+       hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
+ }
+-static void __orinoco_ev_alloc(struct orinoco_private *priv, hermes_t *hw)
++static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
+ {
+-      struct net_device *dev = priv->ndev;
++      struct orinoco_private *priv = dev->priv;
++
+       u16 fid = hermes_read_regn(hw, ALLOCFID);
+       if (fid != priv->txfid) {
+@@ -1945,7 +2033,7 @@
+       TRACE_ENTER(dev->name);
+-      /* No need to lock, the resetting flag is already set in
++      /* No need to lock, the hw_unavailable flag is already set in
+        * alloc_orinocodev() */
+       priv->nicbuf_size = IEEE802_11_FRAME_LEN + ETH_HLEN;
+@@ -2081,8 +2169,6 @@
+       priv->wep_on = 0;
+       priv->tx_key = 0;
+-      priv->hw_unavailable = 0;
+-
+       err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
+       if (err == -EIO) {
+               /* Try workaround for old Symbol firmware bug */
+@@ -2102,6 +2188,12 @@
+               goto out;
+       }
++      /* Make the hardware available, as long as it hasn't been
++       * removed elsewhere (e.g. by PCMCIA hot unplug) */
++      spin_lock_irq(&priv->lock);
++      priv->hw_unavailable--;
++      spin_unlock_irq(&priv->lock);
++
+       printk(KERN_DEBUG "%s: ready\n", dev->name);
+  out:
+@@ -2267,7 +2359,7 @@
+       /* Length of the packet body */
+       /* FIXME: what if the skb is smaller than this? */
+-      len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN);
++      len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN);
+       eh = (struct ethhdr *)skb->data;
+@@ -2281,6 +2373,12 @@
+               goto fail;
+       }
++      /* Clear the 802.11 header and data length fields - some
++       * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused
++       * if this isn't done. */
++      hermes_clear_words(hw, HERMES_DATA0,
++                         HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
++
+       /* Encapsulate Ethernet-II frames */
+       if (ntohs(eh->h_proto) > 1500) { /* Ethernet-II frame */
+               struct header_struct hdr;
+@@ -2362,7 +2460,7 @@
+       stats->tx_errors++;
+-      schedule_task(&priv->timeout_task);
++      schedule_work(&priv->reset_work);
+ }
+ static int
+@@ -2532,7 +2630,7 @@
+       }
+       err = orinoco_hw_get_bitratelist(priv, &numrates,
+-                                     range.bitrate, IW_MAX_BITRATES);
++                                       range.bitrate, IW_MAX_BITRATES);
+       if (err)
+               return err;
+       range.num_bitrates = numrates;
+@@ -2799,7 +2897,7 @@
+       erq->flags = 1;
+       erq->length = strlen(essidbuf) + 1;
+       if (erq->pointer)
+-              if ( copy_to_user(erq->pointer, essidbuf, erq->length) )
++              if (copy_to_user(erq->pointer, essidbuf, erq->length))
+                       return -EFAULT;
+       TRACE_EXIT(dev->name);
+@@ -3128,7 +3226,7 @@
+                               rrq->value = 5500000;
+                       else
+                               rrq->value = val * 1000000;
+-                        break;
++                      break;
+               case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */
+               case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
+                       for (i = 0; i < BITRATE_TABLE_SIZE; i++)
+@@ -3754,7 +3852,7 @@
+               
+               printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);
+-              schedule_task(&priv->timeout_task);
++              schedule_work(&priv->reset_work);
+               break;
+       case SIOCIWFIRSTPRIV + 0x2: /* set_port3 */
+@@ -3827,7 +3925,7 @@
+               break;
+       case SIOCIWLASTPRIV:
+-              err = orinoco_debug_dump_recs(priv);
++              err = orinoco_debug_dump_recs(dev);
+               if (err)
+                       printk(KERN_ERR "%s: Unable to dump records (%d)\n",
+                              dev->name, err);
+@@ -3839,7 +3937,7 @@
+       }
+       
+       if (! err && changed && netif_running(dev)) {
+-              err = orinoco_reconfigure(priv);
++              err = orinoco_reconfigure(dev);
+       }               
+       TRACE_EXIT(dev->name);
+@@ -3924,7 +4022,7 @@
+       DEBUG_REC(PRIID,WORDS),
+       DEBUG_REC(PRISUPRANGE,WORDS),
+       DEBUG_REC(CFIACTRANGES,WORDS),
+-      DEBUG_REC(NICSERNUM,WORDS),
++      DEBUG_REC(NICSERNUM,XSTRING),
+       DEBUG_REC(NICID,WORDS),
+       DEBUG_REC(MFISUPRANGE,WORDS),
+       DEBUG_REC(CFISUPRANGE,WORDS),
+@@ -3961,8 +4059,9 @@
+ #define DEBUG_LTV_SIZE                128
+-static int orinoco_debug_dump_recs(struct orinoco_private *priv)
++static int orinoco_debug_dump_recs(struct net_device *dev)
+ {
++      struct orinoco_private *priv = dev->priv;
+       hermes_t *hw = &priv->hw;
+       u8 *val8;
+       u16 *val16;
+@@ -4051,6 +4150,7 @@
+       dev->do_ioctl = orinoco_ioctl;
+       dev->change_mtu = orinoco_change_mtu;
+       dev->set_multicast_list = orinoco_set_multicast_list;
++      /* we use the default eth_mac_addr for setting the MAC addr */
+       /* Set up default callbacks */
+       dev->open = orinoco_open;
+@@ -4062,7 +4162,7 @@
+       priv->hw_unavailable = 1; /* orinoco_init() must clear this
+                                  * before anything else touches the
+                                  * hardware */
+-      INIT_TQUEUE(&priv->timeout_task, (void (*)(void *))orinoco_reset, dev);
++      INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev);
+       priv->last_linkstatus = 0xffff;
+       priv->connected = 0;
+@@ -4079,13 +4179,14 @@
+ EXPORT_SYMBOL(__orinoco_up);
+ EXPORT_SYMBOL(__orinoco_down);
++EXPORT_SYMBOL(orinoco_stop);
+ EXPORT_SYMBOL(orinoco_reinit_firmware);
+ EXPORT_SYMBOL(orinoco_interrupt);
+ /* Can't be declared "const" or the whole __initdata section will
+  * become const */
+-static char version[] __initdata = "orinoco.c 0.13b (David Gibson <hermes@gibson.dropbear.id.au> and others)";
++static char version[] __initdata = "orinoco.c 0.13e (David Gibson <hermes@gibson.dropbear.id.au> and others)";
+ static int __init init_orinoco(void)
+ {
+--- linux-2.4.21/drivers/net/wireless/orinoco.h~orinoco013e
++++ linux-2.4.21/drivers/net/wireless/orinoco.h
+@@ -11,9 +11,29 @@
+ #include <linux/spinlock.h>
+ #include <linux/netdevice.h>
+ #include <linux/wireless.h>
+-#include <linux/tqueue.h>
++#include <linux/version.h>
+ #include "hermes.h"
++/* Workqueue / task queue backwards compatibility stuff */
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)
++#include <linux/workqueue.h>
++#else
++#include <linux/tqueue.h>
++#define work_struct tq_struct
++#define INIT_WORK INIT_TQUEUE
++#define schedule_work schedule_task
++#endif
++
++/* Interrupt handler backwards compatibility stuff */
++#ifndef IRQ_NONE
++
++#define IRQ_NONE
++#define IRQ_HANDLED
++typedef void irqreturn_t;
++
++#endif
++
+ /* To enable debug messages */
+ //#define ORINOCO_DEBUG               3
+@@ -36,13 +56,13 @@
+ struct orinoco_private {
+-      void *card;     /* Pointer to card dependant structure */
++      void *card;     /* Pointer to card dependent structure */
+       int (*hard_reset)(struct orinoco_private *);
+       /* Synchronisation stuff */
+       spinlock_t lock;
+       int hw_unavailable;
+-      struct tq_struct timeout_task;
++      struct work_struct reset_work;
+       /* driver state */
+       int open;
+@@ -72,6 +92,7 @@
+       int has_sensitivity;
+       int nicbuf_size;
+       u16 channel_mask;
++      int broken_disableport;
+       /* Configuration paramaters */
+       u32 iw_mode;
+@@ -111,9 +132,9 @@
+                                          int (*hard_reset)(struct orinoco_private *));
+ extern int __orinoco_up(struct net_device *dev);
+ extern int __orinoco_down(struct net_device *dev);
+-int orinoco_reinit_firmware(struct net_device *dev);
+-
+-extern void orinoco_interrupt(int irq, void * dev_id, struct pt_regs *regs);
++extern int orinoco_stop(struct net_device *dev);
++extern int orinoco_reinit_firmware(struct net_device *dev);
++extern irqreturn_t orinoco_interrupt(int irq, void * dev_id, struct pt_regs *regs);
+ /********************************************************************/
+ /* Locking and synchronization functions                            */
+--- linux-2.4.21/drivers/net/wireless/orinoco_cs.c~orinoco013e
++++ linux-2.4.21/drivers/net/wireless/orinoco_cs.c
+@@ -1,4 +1,4 @@
+-/* orinoco_cs.c 0.13b - (formerly known as dldwd_cs.c)
++/* orinoco_cs.c 0.13e - (formerly known as dldwd_cs.c)
+  *
+  * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
+  * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
+@@ -22,11 +22,7 @@
+ #include <linux/ptrace.h>
+ #include <linux/slab.h>
+ #include <linux/string.h>
+-#include <linux/timer.h>
+ #include <linux/ioport.h>
+-#include <asm/uaccess.h>
+-#include <asm/io.h>
+-#include <asm/system.h>
+ #include <linux/netdevice.h>
+ #include <linux/if_arp.h>
+ #include <linux/etherdevice.h>
+@@ -38,7 +34,10 @@
+ #include <pcmcia/cistpl.h>
+ #include <pcmcia/cisreg.h>
+ #include <pcmcia/ds.h>
+-#include <pcmcia/bus_ops.h>
++
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/system.h>
+ #include "orinoco.h"
+@@ -62,7 +61,7 @@
+ /* Some D-Link cards have buggy CIS. They do work at 5v properly, but
+  * don't have any CIS entry for it. This workaround it... */
+-static int ignore_cis_vcc; /* = 0 */
++static int ignore_cis_vcc = 1;
+ MODULE_PARM(irq_mask, "i");
+ MODULE_PARM(irq_list, "1-4i");
+@@ -145,8 +144,10 @@
+ /* PCMCIA stuff                                                   */
+ /********************************************************************/
++/* In 2.5 (as of 2.5.69 at least) there is a cs_error exported which
++ * does this, but it's not in 2.4 so we do our own for now. */
+ static void
+-cs_error(client_handle_t handle, int func, int ret)
++orinoco_cs_error(client_handle_t handle, int func, int ret)
+ {
+       error_info_t err = { func, ret };
+       CardServices(ReportError, handle, &err);
+@@ -202,6 +203,7 @@
+       link->priv = dev;
+       /* Initialize the dev_link_t structure */
++      init_timer(&link->release);
+       link->release.function = &orinoco_cs_release;
+       link->release.data = (u_long) link;
+@@ -240,7 +242,7 @@
+       ret = CardServices(RegisterClient, &link->handle, &client_reg);
+       if (ret != CS_SUCCESS) {
+-              cs_error(link->handle, RegisterClient, ret);
++              orinoco_cs_error(link->handle, RegisterClient, ret);
+               orinoco_cs_detach(link);
+               return NULL;
+       }
+@@ -269,19 +271,12 @@
+               return;
+       }
+-      /*
+-         If the device is currently configured and active, we won't
+-         actually delete it yet.  Instead, it is marked so that when
+-         the release() function is called, that will trigger a proper
+-         detach().
+-       */
+       if (link->state & DEV_CONFIG) {
+-#ifdef PCMCIA_DEBUG
+-              printk(KERN_DEBUG "orinoco_cs: detach postponed, '%s' "
+-                     "still locked\n", link->dev->dev_name);
+-#endif
+-              link->state |= DEV_STALE_LINK;
+-              return;
++              orinoco_cs_release((u_long)link);
++              if (link->state & DEV_CONFIG) {
++                      link->state |= DEV_STALE_LINK;
++                      return;
++              }
+       }
+       /* Break the link with Card Services */
+@@ -368,7 +363,7 @@
+       CS_CHECK(GetFirstTuple, handle, &tuple);
+       while (1) {
+               cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
+-              cistpl_cftable_entry_t dflt = { index: 0 };
++              cistpl_cftable_entry_t dflt = { .index = 0 };
+               CFG_CHECK(GetTupleData, handle, &tuple);
+               CFG_CHECK(ParseTuple, handle, &tuple, &parse);
+@@ -472,7 +467,7 @@
+                               link->irq.IRQInfo2 |= 1 << irq_list[i];
+               
+               link->irq.Handler = orinoco_interrupt; 
+-              link->irq.Instance = priv; 
++              link->irq.Instance = dev; 
+               
+               CS_CHECK(RequestIRQ, link->handle, &link->irq);
+       }
+@@ -532,7 +527,7 @@
+       return;
+  cs_failed:
+-      cs_error(link->handle, last_fn, last_ret);
++      orinoco_cs_error(link->handle, last_fn, last_ret);
+  failed:
+       orinoco_cs_release((u_long) link);
+@@ -549,18 +544,13 @@
+       dev_link_t *link = (dev_link_t *) arg;
+       struct net_device *dev = link->priv;
+       struct orinoco_private *priv = dev->priv;
++      unsigned long flags;
+-      /*
+-         If the device is currently in use, we won't release until it
+-         is actually closed, because until then, we can't be sure that
+-         no one will try to access the device or its data structures.
+-       */
+-      if (priv->open) {
+-              DEBUG(0, "orinoco_cs: release postponed, '%s' still open\n",
+-                    link->dev->dev_name);
+-              link->state |= DEV_STALE_CONFIG;
+-              return;
+-      }
++      /* We're committed to taking the device away now, so mark the
++       * hardware as unavailable */
++      spin_lock_irqsave(&priv->lock, flags);
++      priv->hw_unavailable++;
++      spin_unlock_irqrestore(&priv->lock, flags);
+       /* Don't bother checking to see if these succeed or not */
+       CardServices(ReleaseConfiguration, link->handle);
+@@ -593,14 +583,9 @@
+                       orinoco_lock(priv, &flags);
+                       netif_device_detach(dev);
+-                      priv->hw_unavailable = 1;
++                      priv->hw_unavailable++;
+                       orinoco_unlock(priv, &flags);
+-
+-/*                    if (link->open) */
+-/*                            orinoco_cs_stop(dev); */
+-
+-                      mod_timer(&link->release, jiffies + HZ / 20);
+               }
+               break;
+@@ -619,13 +604,8 @@
+                            a better way, short of rewriting the PCMCIA
+                            layer to not suck :-( */
+                       if (! test_bit(0, &card->hard_reset_in_progress)) {
+-                              err = orinoco_lock(priv, &flags);
+-                              if (err) {
+-                                      printk(KERN_ERR "%s: hw_unavailable on SUSPEND/RESET_PHYSICAL\n",
+-                                             dev->name);
+-                                      break;
+-                              }
+-                              
++                              spin_lock_irqsave(&priv->lock, flags);
++
+                               err = __orinoco_down(dev);
+                               if (err)
+                                       printk(KERN_WARNING "%s: %s: Error %d downing interface\n",
+@@ -634,9 +614,9 @@
+                                              err);
+                               
+                               netif_device_detach(dev);
+-                              priv->hw_unavailable = 1;
+-                              
+-                              orinoco_unlock(priv, &flags);
++                              priv->hw_unavailable++;
++
++                              spin_unlock_irqrestore(&priv->lock, flags);
+                       }
+                       CardServices(ReleaseConfiguration, link->handle);
+@@ -653,10 +633,6 @@
+                       CardServices(RequestConfiguration, link->handle,
+                                    &link->conf);
+-                      /* If we're only getting these events because
+-                           of the ResetCard in the hard reset, we
+-                           don't need to do anything - orinoco_reset()
+-                           will handle reinitialization. */
+                       if (! test_bit(0, &card->hard_reset_in_progress)) {
+                               err = orinoco_reinit_firmware(dev);
+                               if (err) {
+@@ -668,9 +644,9 @@
+                               spin_lock_irqsave(&priv->lock, flags);
+                               
+                               netif_device_attach(dev);
+-                              priv->hw_unavailable = 0;
++                              priv->hw_unavailable--;
+                               
+-                              if (priv->open) {
++                              if (priv->open && ! priv->hw_unavailable) {
+                                       err = __orinoco_up(dev);
+                                       if (err)
+                                               printk(KERN_ERR "%s: Error %d restarting card\n",
+@@ -678,7 +654,7 @@
+                                       
+                               }
+-                              orinoco_unlock(priv, &flags);
++                              spin_unlock_irqrestore(&priv->lock, flags);
+                       }
+               }
+               break;
+@@ -693,7 +669,7 @@
+ /* Can't be declared "const" or the whole __initdata section will
+  * become const */
+-static char version[] __initdata = "orinoco_cs.c 0.13b (David Gibson <hermes@gibson.dropbear.id.au> and others)";
++static char version[] __initdata = "orinoco_cs.c 0.13e (David Gibson <hermes@gibson.dropbear.id.au> and others)";
+ static int __init
+ init_orinoco_cs(void)
+@@ -722,7 +698,6 @@
+       if (dev_list)
+               DEBUG(0, "orinoco_cs: Removing leftover devices.\n");
+       while (dev_list != NULL) {
+-              del_timer(&dev_list->release);
+               if (dev_list->state & DEV_CONFIG)
+                       orinoco_cs_release((u_long) dev_list);
+               orinoco_cs_detach(dev_list);
+--- linux-2.4.21/drivers/pcmcia/pxa/Makefile~ramses-pcmcia
++++ linux-2.4.21/drivers/pcmcia/pxa/Makefile
+@@ -12,6 +12,7 @@
+ obj-$(CONFIG_ARCH_PXA_IDP)    += pxa_idp.o
+ obj-$(CONFIG_ARCH_TRIZEPS2)   += trizeps2.o
+ obj-$(CONFIG_ARCH_PXA_CERF)   += ../sa1100_cerf.o
++obj-$(CONFIG_ARCH_RAMSES)     += ramses.o
+ obj-m                         := $(O_TARGET)
+--- linux-2.4.21/drivers/pcmcia/pxa/pxa.c~pxa-pcmcia
++++ linux-2.4.21/drivers/pcmcia/pxa/pxa.c
+@@ -187,7 +187,6 @@
+   struct pcmcia_state state[PXA_PCMCIA_MAX_SOCK];
+   struct pcmcia_state_array state_array;
+   unsigned int i, clock;
+-  unsigned long mecr;
+   printk(KERN_INFO "Intel PXA250/210 PCMCIA (CS release %s)\n", CS_RELEASE);
+@@ -240,6 +239,8 @@
+     pcmcia_low_level=&pxa_idp_pcmcia_ops;
+   } else if( machine_is_pxa_cerf()){
+     pcmcia_low_level=&cerf_pcmcia_ops;
++  } else if( machine_is_ramses()){
++    pcmcia_low_level=&ramses_pcmcia_ops;
+   } else if (machine_is_trizeps2()){
+ #ifdef CONFIG_ARCH_TRIZEPS2
+     pcmcia_low_level=&trizeps2_pcmcia_ops;
+@@ -835,7 +836,7 @@
+ static int pxa_pcmcia_set_io_map(unsigned int sock,
+                                   struct pccard_io_map *map){
+   unsigned int clock, speed;
+-  unsigned long mecr, start;
++  unsigned long start;
+   DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
+@@ -941,7 +942,7 @@
+ static int pxa_pcmcia_set_mem_map(unsigned int sock,
+                                    struct pccard_mem_map *map){
+   unsigned int clock, speed;
+-  unsigned long mecr, start;
++  unsigned long start;
+   DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
+@@ -1076,7 +1077,6 @@
+   char *p=buf;
+   unsigned int sock=(unsigned int)data;
+   unsigned int clock = get_lclk_frequency_10khz();
+-  unsigned long mecr = MECR;
+   p+=sprintf(p, "k_flags  : %s%s%s%s%s%s%s\n", 
+            pxa_pcmcia_socket[sock].k_state.detect?"detect ":"",
+--- linux-2.4.21/drivers/pcmcia/pxa/pxa.h~ramses-pcmcia
++++ linux-2.4.21/drivers/pcmcia/pxa/pxa.h
+@@ -228,6 +228,7 @@
+ extern struct pcmcia_low_level lubbock_pcmcia_ops;
+ extern struct pcmcia_low_level pxa_idp_pcmcia_ops;
+ extern struct pcmcia_low_level cerf_pcmcia_ops;
++extern struct pcmcia_low_level ramses_pcmcia_ops;
+ extern struct pcmcia_low_level trizeps2_pcmcia_ops;
+ #endif  /* !defined(_PCMCIA_PXA_H) */
+--- /dev/null
++++ linux-2.4.21/drivers/pcmcia/pxa/ramses.c
+@@ -0,0 +1,223 @@
++/*
++ * linux/drivers/pcmcia/pxa/ramses.c
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * Copyright (c) 2003 M&N Logistik-Lösungen Online GmbH
++ * 
++ * Platform specific routines for the Ramses, based on those
++ * first done for the Lubbock and PXA IDP.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/sched.h>
++
++#include <pcmcia/ss.h>
++
++#include <asm/delay.h>
++#include <asm/hardware.h>
++#include <asm/irq.h>
++#include <asm/arch/pcmcia.h>
++
++static int 
++ramses_pcmcia_init(struct pcmcia_init *init)
++{
++      int return_val = 0;
++
++      /* Set PCMCIA Socket 0 power to standby mode.
++      *  RAMSES has dedicated CPLD pins for all this stuff :-)
++      */
++      
++      /* both slots disabled, reset NOT active */
++      RAMSES_CPLD_PCCARD_EN = PCC0_ENABLE | PCC1_ENABLE;
++
++      RAMSES_CPLD_PCCARD_PWR = 0; //all power to both slots off
++      //GPDR(IRQ_TO_GPIO_2_80(CFCARD_CD_VALID)) &= ~GPIO_bit(IRQ_TO_GPIO_2_80(CFCARD_CD_VALID));
++      set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(CFCARD_CD_VALID), GPIO_BOTH_EDGES);
++      //GPDR(IRQ_TO_GPIO_2_80(CFCARD_RDYINT)) &= ~GPIO_bit(IRQ_TO_GPIO_2_80(CFCARD_RDYINT));
++      set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(CFCARD_RDYINT), GPIO_FALLING_EDGE);
++
++      return_val +=
++          request_irq(CFCARD_CD_VALID, init->handler, SA_INTERRUPT,
++                      "CF-Card CD", NULL);
++      
++      if (return_val < 0) {
++              return -1;
++      }
++
++      return 2;
++}
++
++static int
++ramses_pcmcia_shutdown(void)
++{
++
++      free_irq(CFCARD_CD_VALID, NULL);
++  
++      RAMSES_CPLD_PCCARD_EN = 0x03;   //disable slots
++      udelay(200);
++      RAMSES_CPLD_PCCARD_PWR = 0;     //shut off all power
++
++      return 0;
++}
++
++static int
++ramses_pcmcia_socket_state(struct pcmcia_state_array *state_array)
++{
++      unsigned long status;
++      int return_val = 1;
++      int i;
++      volatile unsigned long *stat_regs[2] = {
++              &RAMSES_CPLD_PCCARD0_STATUS,
++              &RAMSES_CPLD_PCCARD1_STATUS
++      };
++
++      if (state_array->size < 2)
++              return -1;
++
++      memset(state_array->state, 0,
++             (state_array->size) * sizeof (struct pcmcia_state));
++      
++      for (i = 1; i < 2; i++) {
++
++              status = *stat_regs[i];
++
++              /* this one is a gpio */
++              state_array->state[i].detect = (PCC_DETECT(i)) ? 0 : 1;
++              
++              state_array->state[i].ready  = ((status & _PCC_IRQ) == 0) ? 0 : 1;
++              state_array->state[i].bvd1   = (status & PCC_BVD1) ? 0 : 1;
++              state_array->state[i].bvd2   = (status & PCC_BVD2) ? 0 : 1;
++              state_array->state[i].wrprot = (status & _PCC_WRPROT) ? 1 : 0;
++              state_array->state[i].vs_3v  = (status & PCC_VS1) ? 0 : 1;
++              state_array->state[i].vs_Xv  = (status & PCC_VS2) ? 0 : 1;
++      }
++
++      state_array->state[0].detect = 0;
++      state_array->state[0].ready  = 0;
++      state_array->state[0].bvd1   = 0;
++      state_array->state[0].bvd2   = 0;
++      state_array->state[0].wrprot = 0;
++      state_array->state[0].vs_3v  = 0;
++      state_array->state[0].vs_Xv  = 0;
++
++      return return_val;
++}
++
++static int
++ramses_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
++{
++      switch (info->sock) {
++          case 0:
++              //info->irq = PCMCIA_S0_RDYINT;
++              //printk("//hs ramses_pcmcia_get_irq_info called for slot 0\n");
++              break;
++
++          case 1:
++              info->irq = CFCARD_RDYINT;
++              break;
++
++          default:
++              return -1;
++      }
++
++      return 0;
++}
++
++static int
++ramses_pcmcia_configure_socket(unsigned int sock, socket_state_t *state)
++{
++  /* The Ramses uses the Maxim MAX1602, with the following connections:
++   *
++   * Socket 0 (PCMCIA):
++   *  MAX1602 PXA_IDP         Register
++   *  Pin     Signal          RAMSES_CPLD_PCCARD_PWR:
++   *  -----   -------         ----------------------
++   *  A0VPP   PCC0_PWR0       bit0
++   *  A1VPP   PCC0_PWR1       bit1    
++   *  A0VCC   PCC0_PWR2       bit2
++   *  A1VCC   PCC0_PWR3       bit3
++   *  VX      VCC
++   *  VY      +3.3V
++   *  12IN    +12V
++   *  CODE    +3.3V           Cirrus Code, CODE = High (VY)
++   *
++   * Socket 1 (PCMCIA):
++   *  MAX1602 PXA_IDP         Register
++   *  Pin     Signal          RAMSES_CPLD_PCCARD_PWR:
++   *  -----   -------         ----------------------
++   *  A0VPP   PCC1_PWR0       bit4
++   *  A1VPP   PCC1_PWR1       bit5
++   *  A0VCC   PCC1_PWR2       bit6
++   *  A1VCC   PCC1_PWR3       bit7
++   *  VX      VCC
++   *  VY      +3.3V
++   *  12IN    +12V            
++   *  CODE    +3.3V           Cirrus Code, CODE = High (VY)
++   *
++   */
++
++      if (sock == 1) {
++
++              switch (state->Vcc) {
++                  case 0:
++                      RAMSES_CPLD_PCCARD_EN |= PCC1_ENABLE; // disable socket
++                      udelay(200);
++                      RAMSES_CPLD_PCCARD_PWR &= ~(PCC1_PWR2 | PCC1_PWR3);
++                      break;
++
++                  case 33:
++                      RAMSES_CPLD_PCCARD_PWR &= ~(PCC1_PWR2 | PCC1_PWR3);
++                      RAMSES_CPLD_PCCARD_PWR |= PCC1_PWR3;
++                      RAMSES_CPLD_PCCARD_EN &= ~PCC1_ENABLE; //turn it on
++                      break;
++
++                  case 50:
++                      RAMSES_CPLD_PCCARD_PWR &= ~(PCC1_PWR2 | PCC1_PWR3);
++                      RAMSES_CPLD_PCCARD_PWR |= PCC1_PWR2;
++                      RAMSES_CPLD_PCCARD_EN &= ~PCC1_ENABLE;
++                      break;
++
++                  default:
++                      printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
++                             __FUNCTION__, state->Vcc);
++                      return -1;
++              }
++
++              switch (state->Vpp) {
++                  case 0:
++                      RAMSES_CPLD_PCCARD_PWR &= ~(PCC1_PWR0 | PCC1_PWR1);
++                      break;
++
++                  case 120:
++                      RAMSES_CPLD_PCCARD_PWR &= ~(PCC1_PWR0 | PCC1_PWR1);
++                      RAMSES_CPLD_PCCARD_PWR |= PCC1_PWR1;
++                      break;
++
++                  default:
++                      if (state->Vpp == state->Vcc)
++                              RAMSES_CPLD_PCCARD_PWR =
++                                  (RAMSES_CPLD_PCCARD_PWR &
++                                   ~(PCC1_PWR0 | PCC1_PWR1)) | PCC1_PWR0;
++                      else {
++                              printk(KERN_ERR "%s(): unrecognized Vpp %u\n",
++                                     __FUNCTION__, state->Vpp);
++                              return -1;
++                      }
++              }
++              RAMSES_CPLD_PCCARD_EN = (state->flags & SS_RESET) ? (RAMSES_CPLD_PCCARD_EN | PCC1_RESET)
++                  : (RAMSES_CPLD_PCCARD_EN & ~PCC1_RESET);
++      }
++      return 0;
++}
++
++struct pcmcia_low_level ramses_pcmcia_ops = { 
++  ramses_pcmcia_init,
++  ramses_pcmcia_shutdown,
++  ramses_pcmcia_socket_state,
++  ramses_pcmcia_get_irq_info,
++  ramses_pcmcia_configure_socket
++};
+--- linux-2.4.21/drivers/scsi/scsi.h~usb-sonycamera
++++ linux-2.4.21/drivers/scsi/scsi.h
+@@ -610,6 +610,7 @@
+       unsigned remap:1;       /* support remapping  */
+       unsigned starved:1;     /* unable to process commands because
+                                  host busy */
++      unsigned no_start_on_add:1;     /* do not issue start on add */
+       // Flag to allow revalidate to succeed in sd_open
+       int allow_revalidate;
+--- linux-2.4.21/drivers/scsi/scsi_scan.c~usb-sonycamera
++++ linux-2.4.21/drivers/scsi/scsi_scan.c
+@@ -37,6 +37,8 @@
+ #define BLIST_ISDISK          0x100   /* Treat as (removable) disk */
+ #define BLIST_ISROM           0x200   /* Treat as (removable) CD-ROM */
+ #define BLIST_LARGELUN                0x400   /* LUNs larger than 7 despite reporting as SCSI 2 */
++#define BLIST_NOSTARTONADD    0x1000  /* do not do automatic start on add */
++
+ static void print_inquiry(unsigned char *data);
+ static int scan_scsis_single(unsigned int channel, unsigned int dev,
+@@ -110,9 +112,10 @@
+       {"HP", "C1750A", "3226", BLIST_NOLUN},                  /* scanjet iic */
+       {"HP", "C1790A", "", BLIST_NOLUN},                      /* scanjet iip */
+       {"HP", "C2500A", "", BLIST_NOLUN},                      /* scanjet iicx */
+-      {"HP", "A6188A", "*", BLIST_SPARSELUN},                 /* HP Va7100 Array */
+-      {"HP", "A6189A", "*", BLIST_SPARSELUN},                 /* HP Va7400 Array */
+-      {"HP", "A6189B", "*", BLIST_SPARSELUN},                 /* HP Va7410 Array */
++      {"HP", "A6188A", "*", BLIST_SPARSELUN | BLIST_LARGELUN},/* HP Va7100 Array */
++      {"HP", "A6189A", "*", BLIST_SPARSELUN | BLIST_LARGELUN},/* HP Va7400 Array */
++      {"HP", "A6189B", "*", BLIST_SPARSELUN | BLIST_LARGELUN},/* HP Va7110 Array */
++      {"HP", "A6218A", "*", BLIST_SPARSELUN | BLIST_LARGELUN},/* HP Va7410 Array */
+       {"YAMAHA", "CDR100", "1.00", BLIST_NOLUN},              /* Locks up if polled for lun != 0 */
+       {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN},              /* Locks up if polled for lun != 0  
+                                                                * extra reset */
+@@ -145,7 +148,7 @@
+       {"EMULEX", "MD21/S2     ESDI", "*", BLIST_SINGLELUN},
+       {"CANON", "IPUBJD", "*", BLIST_SPARSELUN},
+       {"nCipher", "Fastness Crypto", "*", BLIST_FORCELUN},
+-      {"DEC","HSG80","*", BLIST_FORCELUN},
++      {"DEC","HSG80","*", BLIST_FORCELUN | BLIST_NOSTARTONADD},
+       {"COMPAQ","LOGICAL VOLUME","*", BLIST_FORCELUN},
+       {"COMPAQ","CR3500","*", BLIST_FORCELUN},
+       {"NEC", "PD-1 ODX654P", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
+@@ -173,7 +176,11 @@
+       {"HP", "NetRAID-4M", "*", BLIST_FORCELUN},
+       {"ADAPTEC", "AACRAID", "*", BLIST_FORCELUN},
+       {"ADAPTEC", "Adaptec 5400S", "*", BLIST_FORCELUN},
+-      {"COMPAQ", "MSA1000", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
++      {"APPLE", "Xserve", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
++      {"COMPAQ", "MSA1000", "*", BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_NOSTARTONADD},
++      {"COMPAQ", "MSA1000 VOLUME", "*", BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_NOSTARTONADD},
++      {"COMPAQ", "HSV110", "*", BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_NOSTARTONADD},
++      {"HP", "HSV100", "*", BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_NOSTARTONADD},
+       {"HP", "C1557A", "*", BLIST_FORCELUN},
+       {"IBM", "AuSaV1S2", "*", BLIST_FORCELUN},
+       {"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+@@ -182,7 +189,8 @@
+       {"HITACHI", "DF500", "*", BLIST_SPARSELUN},
+       {"HITACHI", "DF600", "*", BLIST_SPARSELUN},
+       {"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+-      {"HITACHI", "OPEN-", "*", BLIST_SPARSELUN},             /* HITACHI XP Arrays */
++      {"HITACHI", "OPEN-", "*", BLIST_SPARSELUN | BLIST_LARGELUN},  /* HITACHI XP Arrays */
++      {"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_SPARSELUN | BLIST_LARGELUN},  /* HITACHI 9960 */
+       {"WINSYS","FLASHDISK G6", "*", BLIST_SPARSELUN},
+       {"DotHill","SANnet RAID X300", "*", BLIST_SPARSELUN},   
+       {"SUN", "T300", "*", BLIST_SPARSELUN},
+@@ -194,6 +202,12 @@
+       {"SGI", "TP9400", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+       {"SGI", "TP9500", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+       {"MYLEX", "DACARMRB", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
++      {"PLATYPUS", "CX5", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
++      {"Raidtec", "FCR", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
++      {"HP", "C7200", "*", BLIST_SPARSELUN},                  /* Medium Changer */
++      {"SMSC", "USB 2 HS", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, 
++      {"XYRATEX", "RS", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
++      {"NEC", "iStorage", "*", BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN},
+       /*
+        * Must be at end of list...
+@@ -209,10 +223,14 @@
+ static unsigned int max_scsi_luns = 1;
+ #endif
++static unsigned int scsi_allow_ghost_devices = 0;
++
+ #ifdef MODULE
+ MODULE_PARM(max_scsi_luns, "i");
+ MODULE_PARM_DESC(max_scsi_luns, "last scsi LUN (should be between 1 and 2^32-1)");
++MODULE_PARM(scsi_allow_ghost_devices, "i");
++MODULE_PARM_DESC(scsi_allow_ghost_devices, "allow devices marked as being offline to be accessed anyway (0 = off, else allow ghosts on lun 0 through scsi_allow_ghost_devices - 1");
+ #else
+@@ -232,6 +250,21 @@
+ __setup("max_scsi_luns=", scsi_luns_setup);
++static int __init scsi_allow_ghost_devices_setup(char *str)
++{
++      unsigned int tmp;
++
++      if (get_option(&str, &tmp) == 1) {
++              scsi_allow_ghost_devices = tmp;
++              return 1;
++      } else {
++              printk("scsi_allow_ghost_devices_setup: usage scsi_allow_ghost_devices=n (0: off else\nallow ghost devices (ghost devices are devices that report themselves as\nbeing offline but which we allow access to anyway) on lun 0 through n - 1.\n");
++              return 0;
++      }
++}
++
++__setup("scsi_allow_ghost_devices=", scsi_allow_ghost_devices_setup);
++
+ #endif
+ static void print_inquiry(unsigned char *data)
+@@ -608,6 +641,7 @@
+               } else {
+                       /* assume no peripheral if any other sort of error */
+                       scsi_release_request(SRpnt);
++                      scsi_release_commandblocks(SDpnt);
+                       return 0;
+               }
+       }
+@@ -618,6 +652,24 @@
+        */
+       /*
++       * If we are offline and we are on a LUN != 0, then skip this entry.
++       * If we are on a BLIST_FORCELUN device this will stop the scan at
++       * the first offline LUN (typically the correct thing to do).  If
++       * we are on a BLIST_SPARSELUN device then this won't stop the scan,
++       * but it will keep us from having false entries in our device
++       * array. DL
++       *
++       * NOTE: Need to test this to make sure it doesn't cause problems
++       * with tape autoloaders, multidisc CD changers, and external
++       * RAID chassis that might use sparse luns or multiluns... DL
++       */
++      if (lun != 0 && (scsi_result[0] >> 5) == 1) {
++              scsi_release_request(SRpnt);
++              scsi_release_commandblocks(SDpnt);
++              return 0;
++      }
++
++      /*
+        * Get any flags for this device.  
+        */
+       bflags = get_device_flags (scsi_result);
+@@ -655,8 +707,11 @@
+       SDpnt->removable = (0x80 & scsi_result[1]) >> 7;
+       /* Use the peripheral qualifier field to determine online/offline */
+-      if (((scsi_result[0] >> 5) & 7) == 1)   SDpnt->online = FALSE;
+-      else SDpnt->online = TRUE;
++      if ((((scsi_result[0] >> 5) & 7) == 1) &&
++          (lun >= scsi_allow_ghost_devices))
++              SDpnt->online = FALSE;
++      else 
++              SDpnt->online = TRUE;
+       SDpnt->lockable = SDpnt->removable;
+       SDpnt->changed = 0;
+       SDpnt->access_count = 0;
+@@ -742,6 +797,13 @@
+       if ((bflags & BLIST_BORKEN) == 0)
+               SDpnt->borken = 0;
++      /*
++       * Some devices may not want to have a start command automatically
++       * issued when a device is added.
++       */
++      if (bflags & BLIST_NOSTARTONADD)
++              SDpnt->no_start_on_add = 1;
++
+       /*
+        * If we want to only allow I/O to one of the luns attached to this device
+        * at a time, then we set this flag.
+@@ -857,11 +919,26 @@
+                * I think we need REPORT LUNS in future to avoid scanning
+                * of unused LUNs. But, that is another item.
+                */
++              /*
+               if (*max_dev_lun < shpnt->max_lun)
+                       *max_dev_lun = shpnt->max_lun;
+               else    if ((max_scsi_luns >> 1) >= *max_dev_lun)
+                               *max_dev_lun += shpnt->max_lun;
+                       else    *max_dev_lun = max_scsi_luns;
++              */
++              /*
++               * Blech...the above code is broken.  When you have a device
++               * that is present, and it is a FORCELUN device, then we
++               * need to scan *all* the luns on that device.  Besides,
++               * skipping the scanning of LUNs is a false optimization.
++               * Scanning for a LUN on a present device is a very fast
++               * operation, it's scanning for devices that don't exist that
++               * is expensive and slow (although if you are truly scanning
++               * through MAX_SCSI_LUNS devices that would be bad, I hope
++               * all of the controllers out there set a reasonable value
++               * in shpnt->max_lun).  DL
++               */
++              *max_dev_lun = shpnt->max_lun;
+               return 1;
+       }
+       /*
+--- linux-2.4.21/drivers/scsi/sd.c~usb-sonycamera
++++ linux-2.4.21/drivers/scsi/sd.c
+@@ -775,7 +775,8 @@
+       char nbuff[6];
+       unsigned char *buffer;
+       unsigned long spintime_value = 0;
+-      int the_result, retries, spintime;
++      int retries, spintime;
++      unsigned int the_result;
+       int sector_size;
+       Scsi_Request *SRpnt;
+@@ -817,7 +818,7 @@
+       do {
+               retries = 0;
+-              while (retries < 3) {
++              do {
+                       cmd[0] = TEST_UNIT_READY;
+                       cmd[1] = (rscsi_disks[i].device->scsi_level <= SCSI_2) ?
+                                ((rscsi_disks[i].device->lun << 5) & 0xe0) : 0;
+@@ -832,10 +833,10 @@
+                       the_result = SRpnt->sr_result;
+                       retries++;
+-                      if (the_result == 0
+-                          || SRpnt->sr_sense_buffer[2] != UNIT_ATTENTION)
+-                              break;
+-              }
++              } while (retries < 3
++                       && (the_result !=0
++                           || ((driver_byte(the_result) & DRIVER_SENSE)
++                               && SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION)));
+               /*
+                * If the drive has indicated to us that it doesn't have
+@@ -853,24 +854,47 @@
+                       break;
+               }
++              if ((driver_byte(the_result) & DRIVER_SENSE) == 0) {
++                      /* no sense, TUR either succeeded or failed
++                       * with a status error */
++                      if(!spintime && the_result != 0)
++                              printk(KERN_NOTICE "%s: Unit Not Ready, error = 0x%x\n", nbuff, the_result);
++                      break;
++              }
++
++              /*
++               * The device does not want the automatic start to be issued.
++               */
++              if (rscsi_disks[i].device->no_start_on_add) {
++                      break;
++              }
++
++              /*
++               * If manual intervention is required, or this is an
++               * absent USB storage device, a spinup is meaningless.
++               */
++              if (SRpnt->sr_sense_buffer[2] == NOT_READY &&
++                  SRpnt->sr_sense_buffer[12] == 4 /* not ready */ &&
++                  SRpnt->sr_sense_buffer[13] == 3) {
++                      break;    /* manual intervention required */
+               /* Look for non-removable devices that return NOT_READY.
+                * Issue command to spin up drive for these cases. */
+-              if (the_result && !rscsi_disks[i].device->removable &&
+-                  SRpnt->sr_sense_buffer[2] == NOT_READY) {
++              } else if (the_result && !rscsi_disks[i].device->removable &&
++                         SRpnt->sr_sense_buffer[2] == NOT_READY) {
+                       unsigned long time1;
+                       if (!spintime) {
+                               printk("%s: Spinning up disk...", nbuff);
+                               cmd[0] = START_STOP;
+                               cmd[1] = (rscsi_disks[i].device->scsi_level <= SCSI_2) ?
+-                                       ((rscsi_disks[i].device->lun << 5) & 0xe0) : 0;
+-                              cmd[1] |= 1;    /* Return immediately */
++                                       ((rscsi_disks[i].device->lun << 5) & 0xe0) : 0;
++                              cmd[1] |= 1;    /* Return immediately */
+                               memset((void *) &cmd[2], 0, 8);
+-                              cmd[4] = 1;     /* Start spin cycle */
++                              cmd[4] = 1;     /* Start spin cycle */
+                               SRpnt->sr_cmd_len = 0;
+                               SRpnt->sr_sense_buffer[0] = 0;
+                               SRpnt->sr_sense_buffer[2] = 0;
+-                              SRpnt->sr_data_direction = SCSI_DATA_READ;
++                              SRpnt->sr_data_direction = SCSI_DATA_NONE;
+                               scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
+                                           0/*512*/, SD_TIMEOUT, MAX_RETRIES);
+                               spintime_value = jiffies;
+@@ -883,6 +907,14 @@
+                               time1 = schedule_timeout(time1);
+                       } while(time1);
+                       printk(".");
++              } else {
++                      /* we don't understand the sense code, so it's
++                       * probably pointless to loop */
++                      if(!spintime) {
++                              printk(KERN_NOTICE "%s: Unit Not Ready, sense:\n", nbuff);
++                              print_req_sense("", SRpnt);
++                      }
++                      break;
+               }
+       } while (the_result && spintime &&
+                time_after(spintime_value + 100 * HZ, jiffies));
+--- linux-2.4.21/drivers/sound/ac97_codec.c~ucb1x00
++++ linux-2.4.21/drivers/sound/ac97_codec.c
+@@ -547,6 +547,12 @@
+                       val = SOUND_CAP_EXCL_INPUT;
+                       break;
++              case SOUND_MIXER_AC97:
++                      if (get_user(val, (int *)arg))
++                              return -EFAULT;
++                      val = codec->codec_read(codec, val);
++                      return put_user(val, (int *)arg);
++
+               default: /* read a specific mixer */
+                       i = _IOC_NR(cmd);
+@@ -575,6 +581,11 @@
+                       codec->recmask_io(codec, 0, val);
+                       return 0;
++
++              case SOUND_MIXER_AC97:
++                      codec->codec_write(codec, val >> 16 & 0xffff, val & 0xffff);
++                      return 0;
++
+               default: /* write a specific mixer */
+                       i = _IOC_NR(cmd);
+--- linux-2.4.21/drivers/sound/pxa-ac97.c~pxa-ac97
++++ linux-2.4.21/drivers/sound/pxa-ac97.c
+@@ -27,6 +27,7 @@
+ #include <linux/sound.h>
+ #include <linux/soundcard.h>
+ #include <linux/ac97_codec.h>
++#include <linux/pm.h>
+ #include <asm/hardware.h>
+ #include <asm/irq.h>
+@@ -164,6 +165,11 @@
+               //pxa_ac97_write(&pxa_ac97_codec, 0x6a, 0x1ff7);
+               pxa_ac97_write(&pxa_ac97_codec, 0x6a, 0x0050);
+               pxa_ac97_write(&pxa_ac97_codec, 0x6c, 0x0030);
++#if CONFIG_ARCH_RAMSES
++              pxa_ac97_codec.supported_mixers = SOUND_MASK_VOLUME | SOUND_MASK_IGAIN;
++              pxa_ac97_codec.stereo_mixers = SOUND_MASK_VOLUME | SOUND_MASK_IGAIN;
++              pxa_ac97_codec.record_sources = SOUND_MASK_MIC | SOUND_MASK_LINE;
++#endif
+       }
+       pxa_ac97_refcount++;
+@@ -198,7 +204,7 @@
+ static int mixer_ioctl( struct inode *inode, struct file *file,
+                       unsigned int cmd, unsigned long arg)
+ {
+-      int ret, val;
++      int ret;
+       ret = pxa_ac97_codec.mixer_ioctl(&pxa_ac97_codec, cmd, arg);
+       if (ret)
+@@ -282,6 +288,7 @@
+               /* fall through */
+       case SOUND_PCM_READ_RATE:
++              val = 0;
+               if (file->f_mode & FMODE_READ)
+                       val = codec_adc_rate;
+               if (file->f_mode & FMODE_WRITE)
+@@ -342,6 +349,44 @@
+ };
++#ifdef CONFIG_PM
++
++static int pxa_ac97_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
++{
++      down(&pxa_ac97_mutex);
++
++      switch (rqst) {
++      case PM_SUSPEND:
++              // TODO: set to low-power state?
++              GCR = GCR_ACLINK_OFF;
++              CKEN &= ~CKEN2_AC97;
++              break;
++
++      case PM_RESUME:
++              CKEN |= CKEN2_AC97; 
++
++              GCR = 0;
++              udelay(10);
++              GCR = GCR_COLD_RST|GCR_CDONE_IE|GCR_SDONE_IE;
++              while (!(GSR & GSR_PCR)) {
++                      schedule();
++              }
++
++              // need little hack for UCB1400 (should be moved elsewhere)
++              pxa_ac97_write(&pxa_ac97_codec,AC97_EXTENDED_STATUS,1);
++              pxa_ac97_write(&pxa_ac97_codec, 0x6a, 0x0050);
++              pxa_ac97_write(&pxa_ac97_codec, 0x6c, 0x0030);
++              break;
++      }
++
++      up(&pxa_ac97_mutex);
++
++      return 0;
++}
++
++#endif
++
++
+ static int __init pxa_ac97_init(void)
+ {
+       int ret;
+@@ -354,11 +399,18 @@
+       ac97_audio_state.dev_dsp = register_sound_dsp(&ac97_audio_fops, -1);
+       pxa_ac97_codec.dev_mixer = register_sound_mixer(&mixer_fops, -1);
++#ifdef PM_DEBUG
++      ac97_audio_state.pmdev = pm_register(PM_SYS_UNKNOWN, 0x71783937, pxa_ac97_pm_callback, "pxa-ac97");
++#else
++      ac97_audio_state.pmdev = pm_register(PM_SYS_UNKNOWN, 0x71783937, pxa_ac97_pm_callback);
++#endif
++
+       return 0;
+ }
+ static void __exit pxa_ac97_exit(void)
+ {
++      pm_unregister(ac97_audio_state.pmdev);
+       unregister_sound_dsp(ac97_audio_state.dev_dsp);
+       unregister_sound_mixer(pxa_ac97_codec.dev_mixer);
+       pxa_ac97_put();
+--- linux-2.4.21/drivers/sound/pxa-audio.h~pm
++++ linux-2.4.21/drivers/sound/pxa-audio.h
+@@ -47,6 +47,9 @@
+       int wr_ref:1;           /* open reference for playback */
+       int (*client_ioctl)(struct inode *, struct file *, uint, ulong);
+       struct semaphore sem;           /* prevent races in attach/release */
++#ifdef CONFIG_PM
++      struct pm_dev *pmdev;           /* Power management */
++#endif
+ } audio_state_t;
+ extern int pxa_audio_attach(struct inode *inode, struct file *file,
+--- linux-2.4.21/drivers/usb/Config.in~pxa-usb
++++ linux-2.4.21/drivers/usb/Config.in
+@@ -5,7 +5,7 @@
+ comment 'USB support'
+ # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
+-if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SA1111" = "y" -o "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
++if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SA1111" = "y" -o "$CONFIG_ARCH_AT91RM9200" = "y" -o "$CONFIG_ARCH_PXA" = "y" ]; then
+    tristate 'Support for USB' CONFIG_USB
+ else
+    define_bool CONFIG_USB n
+--- linux-2.4.21/drivers/usb/Makefile~usb-sl811
++++ linux-2.4.21/drivers/usb/Makefile
+@@ -80,6 +80,9 @@
+ ifeq ($(CONFIG_USB_OHCI),y)
+       obj-y += host/usb-ohci.o host/usb-ohci-sa1111.o
+ endif
++
++subdir-$(CONFIG_USB_SL811HS_ALT)+= host
++
+ subdir-$(CONFIG_USB_OHCI_AT91)        += host
+ ifeq ($(CONFIG_USB_OHCI_AT91),y)
+       obj-y += host/usb-ohci.o
+--- linux-2.4.21/drivers/usb/hcd.c~ramses-usb
++++ linux-2.4.21/drivers/usb/hcd.c
+@@ -662,7 +662,9 @@
+       pci_set_drvdata(dev, hcd);
+       hcd->driver = driver;
+       hcd->description = driver->description;
++#ifdef TODO
+       hcd->pdev = dev;
++#endif
+       printk (KERN_INFO "%s %s: %s\n",
+                       hcd->description,  dev->slot_name, dev->name);
+@@ -1201,6 +1203,7 @@
+               return status;
+       // NOTE:  2.5 does this if !URB_NO_DMA_MAP transfer flag
++#ifdef TODO
+       if (usb_pipecontrol (urb->pipe))
+               urb->setup_dma = pci_map_single (
+ #ifdef CONFIG_PCI
+@@ -1223,7 +1226,7 @@
+                               usb_pipein (urb->pipe)
+                                   ? PCI_DMA_FROMDEVICE
+                                   : PCI_DMA_TODEVICE);
+-
++#endif
+       if (urb->dev == hcd->bus->root_hub)
+               status = rh_urb_enqueue (hcd, urb);
+       else
+@@ -1488,6 +1491,7 @@
+       // hcd_monitor_hook(MONITOR_URB_UPDATE, urb, dev)
+       // NOTE:  2.5 does this if !URB_NO_DMA_MAP transfer flag
++#ifdef TODO
+       if (usb_pipecontrol (urb->pipe))
+               pci_unmap_single (
+ #ifdef CONFIG_PCI
+@@ -1510,6 +1514,7 @@
+                               usb_pipein (urb->pipe)
+                                   ? PCI_DMA_FROMDEVICE
+                                   : PCI_DMA_TODEVICE);
++#endif
+       /* pass ownership to the completion handler */
+       urb->complete (urb);
+--- linux-2.4.21/drivers/usb/host/Config.in~usb-sl811
++++ linux-2.4.21/drivers/usb/host/Config.in
+@@ -13,6 +13,9 @@
+ fi
+ dep_tristate '  OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
+ dep_tristate '  SA1111 OHCI-compatible host interface support' CONFIG_USB_OHCI_SA1111 $CONFIG_USB
++if [ "$CONFIG_ARM" = "y" -o "$CONFIG_X86" = "y" ]; then
++   dep_tristate '  SL811HS Alternate (x86, StrongARM, isosynchronous mode)' CONFIG_USB_SL811HS_ALT $CONFIG_USB $CONFIG_EXPERIMENTAL
++fi
+ if [ "$CONFIG_ARCH_AT91RM9200" = "y" ]; then
+    dep_tristate '  AT91RM9200 OHCI-compatible host interface support' CONFIG_USB_OHCI_AT91 $CONFIG_USB
+ fi
+--- linux-2.4.21/drivers/usb/host/Makefile~usb-sl811
++++ linux-2.4.21/drivers/usb/host/Makefile
+@@ -10,6 +10,7 @@
+ obj-$(CONFIG_USB_UHCI)                                += usb-uhci.o
+ obj-$(CONFIG_USB_OHCI)                                += usb-ohci.o usb-ohci-pci.o
+ obj-$(CONFIG_USB_OHCI_SA1111)                 += usb-ohci.o usb-ohci-sa1111.o
++obj-$(CONFIG_USB_SL811HS_ALT)                 += sl811.o
+ obj-$(CONFIG_USB_OHCI_AT91)                   += usb-ohci.o
+ # Extract lists of the multi-part drivers.
+--- /dev/null
++++ linux-2.4.21/drivers/usb/host/sl811.c
+@@ -0,0 +1,2782 @@
++/*
++ * SL811 Host Controller Interface driver for USB.
++ *
++ * Copyright (c) 2003/06, Courage Co., Ltd.
++ *
++ * Based on:
++ *    1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap,
++ *      Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber,
++ *      Adam Richter, Gregory P. Smith;
++ *    2.Original SL811 driver (hc_sl811.o) by Pei Liu <pbl@cypress.com>
++ *    3.Rewrited as sl811.o by Yin Aihua <yinah:couragetech.com.cn>
++ *
++ * It's now support isochornous mode and more effective than hc_sl811.o
++ * Support x86 architecture now.
++ *
++ * 19.09.2003 (05.06.2003) HNE
++ * sl811_alloc_hc: Set "bus->bus_name" at init.
++ * sl811_reg_test (hc_reset,regTest):
++ *   Stop output at first failed pattern.
++ * Down-Grade for Kernel 2.4.20 and from 2.4.22
++ * Split hardware dependency into files sl811-x86.h and sl811-arm.h.
++ *
++ * 22.09.2003 HNE
++ * sl811_found_hc: First patterntest, than interrupt enable.
++ * Do nothing, if patterntest failed. Release IO if failed.
++ * Stop Interrupts first, than remove handle. (Old blocked Shared IRQ)
++ * Alternate IO-Base for second Controller (CF/USB1).
++ *
++ * 24.09.2003 HNE
++ * Remove all arm specific source (moved into include/asm/sl811-hw.h).
++ *
++ * 03.10.2003 HNE
++ * Low level only for port IO into hardware-include.
++ *
++ * To do:
++ *    1.Modify the timeout part, it's some messy
++ *    2.Use usb-a and usb-b set in Ping-Pong mode
++ *    o Floppy do not work.
++ *    o driver crash, if io region can't register
++ *    o Only tested as module. Compiled-in version not tested!
++ *
++ * 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/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/smp_lock.h>
++#include <linux/list.h>
++#include <linux/ioport.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/hardware.h>
++#include <linux/usb.h>
++
++#include "../hcd.h"
++#include "../hub.h"
++#include "sl811.h"
++
++#define DRIVER_VERSION "v0.30"
++#define MODNAME "SL811"
++#define DRIVER_AUTHOR "Yin Aihua <yinah@couragetech.com.cn>, Henry Nestler <hne@ist1.de>"
++#define DRIVER_DESC "Sl811 USB Host Controller Alternate Driver"
++
++static LIST_HEAD(sl811_hcd_list);
++
++/*
++ * 0: normal prompt and information
++ * 1: error should not occur in normal
++ * 2: error maybe occur in normal
++ * 3: useful and detail debug information
++ * 4: function level enter and level inforamtion
++ * 5: endless information will output because of timer function or interrupt
++ */
++static int debug = 0;
++MODULE_PARM(debug,"i");
++MODULE_PARM_DESC(debug,"debug level");
++
++#include <asm/sl811-hw.h>     /* Include hardware and board depens */
++
++static void sl811_rh_int_timer_do(unsigned long ptr);
++static void sl811_transfer_done(struct sl811_hc *hc, int sof);
++
++/*
++ * Read       a byte of data from the SL811H/SL11H
++ */
++static __u8 inline sl811_read(struct sl811_hc *hc, __u8 offset)
++{
++      sl811_write_index (hc, offset);
++      return (sl811_read_data (hc));
++}
++
++/*
++ * Write a byte       of data to the SL811H/SL11H
++ */
++static void inline sl811_write(struct sl811_hc *hc, __u8 offset, __u8 data)
++{
++      sl811_write_index_data (hc, offset, data);
++}
++
++/*
++ * Read       consecutive bytes of data from the SL811H/SL11H buffer
++ */
++static void inline sl811_read_buf(struct sl811_hc *hc, __u8 offset, __u8 *buf, __u8 size)
++{
++      sl811_write_index (hc, offset);
++      while (size--) {
++              *buf++ = sl811_read_data(hc);
++      }
++}
++
++/*
++ * Write consecutive bytes of data to the SL811H/SL11H buffer
++ */
++static void inline sl811_write_buf(struct sl811_hc *hc, __u8 offset, __u8 *buf, __u8 size)
++{
++      sl811_write_index (hc, offset);
++      while (size--) {
++              sl811_write_data (hc, *buf);
++              buf++;
++      }
++}
++
++/*
++ * This       routine test the Read/Write functionality of SL811HS registers
++ */
++static int sl811_reg_test(struct sl811_hc *hc)
++{
++      int i, data, result = 0;
++      __u8 buf[256];
++
++      for (i = 0x10; i < 256; i++) {
++              /* save the original buffer */
++              buf[i] = sl811_read(hc, i);
++
++              /* Write the new data to the buffer */
++              sl811_write(hc, i, ~i);
++      }
++
++      /* compare the written data */
++      for (i = 0x10; i < 256; i++) {
++              data = sl811_read(hc, i);
++              if (data != (__u8) ~i) {
++                      PDEBUG(1, "reg %02x expected %02x got %02x", i, (__u8) ~i, data);
++                      result = -1;
++
++                      /* If no Debug, show only first failed Address */
++                      if (!debug)
++                          break;
++              }
++      }
++
++      /* restore the data */
++      for (i = 0x10; i < 256; i++)
++              sl811_write(hc, i, buf[i]);
++
++      return result;
++}
++
++/*
++ * Display all SL811HS register       values
++ */
++#if 0 /* unused (hne) */
++static void sl811_reg_show(struct sl811_hc *hc)
++{
++      int i;
++
++      for (i = 0; i < 256; i++)
++              PDEBUG(4, "offset %d: 0x%x", i, sl811_read(hc, i));
++}
++#endif
++
++/*
++ * This       function enables SL811HS interrupts
++ */
++static void sl811_enable_interrupt(struct sl811_hc *hc)
++{
++      PDEBUG(4, "enter");
++      sl811_write(hc, SL811_INTR, SL811_INTR_DONE_A | SL811_INTR_SOF | SL811_INTR_INSRMV);
++}
++
++/*
++ * This       function disables SL811HS interrupts
++ */
++static void sl811_disable_interrupt(struct sl811_hc *hc)
++{
++      PDEBUG(4, "enter");
++      // Disable all other interrupt except for insert/remove.
++      sl811_write(hc, SL811_INTR, SL811_INTR_INSRMV);
++}
++
++/*
++ * SL811 Virtual Root Hub
++ */
++
++/* Device descriptor */
++static __u8 sl811_rh_dev_des[] =
++{
++      0x12,       /*  __u8  bLength; */
++      0x01,       /*  __u8  bDescriptorType; Device */
++      0x10,       /*  __u16 bcdUSB; v1.1 */
++      0x01,
++      0x09,       /*  __u8  bDeviceClass; HUB_CLASSCODE */
++      0x00,       /*  __u8  bDeviceSubClass; */
++      0x00,       /*  __u8  bDeviceProtocol; */
++      0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
++      0x00,       /*  __u16 idVendor; */
++      0x00,
++      0x00,       /*  __u16 idProduct; */
++      0x00,
++      0x00,       /*  __u16 bcdDevice; */
++      0x00,
++      0x00,       /*  __u8  iManufacturer; */
++      0x02,       /*  __u8  iProduct; */
++      0x01,       /*  __u8  iSerialNumber; */
++      0x01        /*  __u8  bNumConfigurations; */
++};
++
++/* Configuration descriptor */
++static __u8 sl811_rh_config_des[] =
++{
++      0x09,       /*  __u8  bLength; */
++      0x02,       /*  __u8  bDescriptorType; Configuration */
++      0x19,       /*  __u16 wTotalLength; */
++      0x00,
++      0x01,       /*  __u8  bNumInterfaces; */
++      0x01,       /*  __u8  bConfigurationValue; */
++      0x00,       /*  __u8  iConfiguration; */
++      0x40,       /*  __u8  bmAttributes;
++                    Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup,
++                    4..0: resvd */
++      0x00,       /*  __u8  MaxPower; */
++
++      /* interface */
++      0x09,       /*  __u8  if_bLength; */
++      0x04,       /*  __u8  if_bDescriptorType; Interface */
++      0x00,       /*  __u8  if_bInterfaceNumber; */
++      0x00,       /*  __u8  if_bAlternateSetting; */
++      0x01,       /*  __u8  if_bNumEndpoints; */
++      0x09,       /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
++      0x00,       /*  __u8  if_bInterfaceSubClass; */
++      0x00,       /*  __u8  if_bInterfaceProtocol; */
++      0x00,       /*  __u8  if_iInterface; */
++
++      /* endpoint */
++      0x07,       /*  __u8  ep_bLength; */
++      0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
++      0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
++      0x03,       /*  __u8  ep_bmAttributes; Interrupt */
++      0x08,       /*  __u16 ep_wMaxPacketSize; */
++      0x00,
++      0xff        /*  __u8  ep_bInterval; 255 ms */
++};
++
++/* root hub class descriptor*/
++static __u8 sl811_rh_hub_des[] =
++{
++      0x09,                   /*  __u8  bLength; */
++      0x29,                   /*  __u8  bDescriptorType; Hub-descriptor */
++      0x01,                   /*  __u8  bNbrPorts; */
++      0x00,                   /* __u16  wHubCharacteristics; */
++      0x00,
++      0x50,                   /*  __u8  bPwrOn2pwrGood; 2ms */
++      0x00,                   /*  __u8  bHubContrCurrent; 0 mA */
++      0xfc,                   /*  __u8  DeviceRemovable; *** 7 Ports max *** */
++      0xff                    /*  __u8  PortPwrCtrlMask; *** 7 ports max *** */
++};
++
++/*
++ * This function examine the port change in the virtual root hub. HUB INTERRUPT ENDPOINT.
++ */
++static int sl811_rh_send_irq(struct sl811_hc *hc, __u8 *rh_change, int rh_len)
++{
++      __u8 data = 0;
++              
++      PDEBUG(5, "enter");
++
++      /*
++       * Right now, It is assume the power is good and no changes and only one port.
++       */
++      if (hc->rh_status.wPortChange & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) {  
++              data = 1<<1;
++              *(__u8 *)rh_change = data;
++              return 1;
++      } else
++              return 0;
++}
++
++/*
++ * This function creates a timer that act as interrupt pipe in the virtual hub.
++ *
++ * Note:  The virtual root hub's interrupt pipe are polled by the timer
++ *        every "interval" ms
++ */
++static void sl811_rh_init_int_timer(struct urb * urb)
++{
++       struct sl811_hc *hc = urb->dev->bus->hcpriv;
++       hc->rh.interval = urb->interval;
++
++       init_timer(&hc->rh.rh_int_timer);
++       hc->rh.rh_int_timer.function = sl811_rh_int_timer_do;
++       hc->rh.rh_int_timer.data = (unsigned long)urb;
++       hc->rh.rh_int_timer.expires = jiffies +
++              (HZ * (urb->interval < 30? 30: urb->interval)) / 1000;
++       add_timer (&hc->rh.rh_int_timer);
++}
++
++/*
++ * This function is called when the timer expires.  It gets the the port
++ * change data and pass along to the upper protocol.
++ */
++static void sl811_rh_int_timer_do(unsigned long ptr)
++{
++      int len;
++      struct urb *urb = (struct urb *)ptr;
++      struct sl811_hc *hc = urb->dev->bus->hcpriv;
++      PDEBUG (5, "enter");
++
++      if(hc->rh.send) {
++              len = sl811_rh_send_irq(hc, urb->transfer_buffer,
++                      urb->transfer_buffer_length);
++              if (len > 0) {
++                      urb->actual_length = len;
++                      if (urb->complete)
++                              urb->complete(urb);
++              }
++      }
++
++#ifdef SL811_TIMEOUT
++      
++{
++      struct list_head *head, *tmp;
++      struct sl811_urb_priv *urbp;
++      struct urb *u;
++      int i;
++      static int timeout_count = 0;
++
++// check time out every second
++      if (++timeout_count > 4) {
++              int max_scan = hc->active_urbs;
++              timeout_count = 0;
++              for (i = 0; i < 6; ++i) {
++                      head = &hc->urb_list[i];
++                      tmp = head->next;
++                      while (tmp != head && max_scan--) {
++                              u = list_entry(tmp, struct urb, urb_list);
++                              urbp = (struct sl811_urb_priv *)u->hcpriv;
++                              tmp = tmp->next;
++                              // Check if the URB timed out
++                              if (u->timeout && time_after_eq(jiffies, urbp->inserttime + u->timeout)) {
++                                      PDEBUG(3, "urb = %p time out, we kill it", urb);
++                                      u->transfer_flags |= USB_TIMEOUT_KILLED;
++                              }
++                      }
++              }
++      }
++}
++
++#endif
++      // re-activate the timer
++      sl811_rh_init_int_timer(urb);
++}
++
++/* helper macro */
++#define OK(x) len = (x); break
++
++/*
++ * This function handles all USB request to the the virtual root hub
++ */
++static int sl811_rh_submit_urb(struct urb *urb)
++{
++      struct usb_device *usb_dev = urb->dev;
++      struct sl811_hc *hc = usb_dev->bus->hcpriv;
++      struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *)urb->setup_packet;
++      void *data = urb->transfer_buffer;
++      int buf_len = urb->transfer_buffer_length;
++      unsigned int pipe = urb->pipe;
++      __u8 data_buf[16];
++      __u8 *bufp = data_buf;
++      int len = 0;
++      int status = 0;
++      
++      __u16 bmRType_bReq;
++      __u16 wValue;
++      __u16 wIndex;
++      __u16 wLength;
++
++      if (usb_pipeint(pipe)) {
++              hc->rh.urb =  urb;
++              hc->rh.send = 1;
++              hc->rh.interval = urb->interval;
++              sl811_rh_init_int_timer(urb);
++              urb->status = 0;
++
++              return 0;
++      }
++
++      bmRType_bReq  = cmd->bRequestType | (cmd->bRequest << 8);
++      wValue        = le16_to_cpu (cmd->wValue);
++      wIndex        = le16_to_cpu (cmd->wIndex);
++      wLength       = le16_to_cpu (cmd->wLength);
++
++      PDEBUG(5, "submit rh urb, req = %d(%x) len=%d", bmRType_bReq, bmRType_bReq, wLength);
++
++      /* Request Destination:
++                 without flags: Device,
++                 USB_RECIP_INTERFACE: interface,
++                 USB_RECIP_ENDPOINT: endpoint,
++                 USB_TYPE_CLASS means HUB here,
++                 USB_RECIP_OTHER | USB_TYPE_CLASS  almost ever means HUB_PORT here
++      */
++      switch (bmRType_bReq) {
++      case RH_GET_STATUS:
++              *(__u16 *)bufp = cpu_to_le16(1);
++              OK(2);
++
++      case RH_GET_STATUS | USB_RECIP_INTERFACE:
++              *(__u16 *)bufp = cpu_to_le16(0);
++              OK(2);
++
++      case RH_GET_STATUS | USB_RECIP_ENDPOINT:
++              *(__u16 *)bufp = cpu_to_le16(0);
++              OK(2);
++
++      case RH_GET_STATUS | USB_TYPE_CLASS:
++              *(__u32 *)bufp = cpu_to_le32(0);
++              OK(4);
++
++      case RH_GET_STATUS | USB_RECIP_OTHER | USB_TYPE_CLASS:
++              *(__u32 *)bufp = cpu_to_le32(hc->rh_status.wPortChange<<16 | hc->rh_status.wPortStatus);
++              OK(4);
++
++      case RH_CLEAR_FEATURE | USB_RECIP_ENDPOINT:
++              switch (wValue) {
++              case 1: 
++                      OK(0);
++              }
++              break;
++
++      case RH_CLEAR_FEATURE | USB_TYPE_CLASS:
++              switch (wValue) {
++              case C_HUB_LOCAL_POWER:
++                      OK(0);
++
++              case C_HUB_OVER_CURRENT:
++                      OK(0);
++              }
++              break;
++
++      case RH_CLEAR_FEATURE | USB_RECIP_OTHER | USB_TYPE_CLASS:
++              switch (wValue) {
++              case USB_PORT_FEAT_ENABLE:
++                      hc->rh_status.wPortStatus &= ~USB_PORT_STAT_ENABLE;
++                      OK(0);
++
++              case USB_PORT_FEAT_SUSPEND:
++                      hc->rh_status.wPortStatus &= ~USB_PORT_STAT_SUSPEND;
++                      OK(0);
++
++              case USB_PORT_FEAT_POWER:
++                      hc->rh_status.wPortStatus &= ~USB_PORT_STAT_POWER;
++                      OK(0);
++
++              case USB_PORT_FEAT_C_CONNECTION:
++                      hc->rh_status.wPortChange &= ~USB_PORT_STAT_C_CONNECTION;
++                      OK(0);
++
++              case USB_PORT_FEAT_C_ENABLE:
++                      hc->rh_status.wPortChange &= ~USB_PORT_STAT_C_ENABLE;
++                      OK(0);
++
++              case USB_PORT_FEAT_C_SUSPEND:
++                      hc->rh_status.wPortChange &= ~USB_PORT_STAT_C_SUSPEND;
++                      OK(0);
++
++              case USB_PORT_FEAT_C_OVER_CURRENT:
++                      hc->rh_status.wPortChange &= ~USB_PORT_STAT_C_OVERCURRENT;
++                      OK(0);
++
++              case USB_PORT_FEAT_C_RESET:
++                      hc->rh_status.wPortChange &= ~USB_PORT_STAT_C_RESET;
++                      OK(0);
++              }
++              break;
++
++      case RH_SET_FEATURE | USB_RECIP_OTHER | USB_TYPE_CLASS:
++              switch (wValue) {
++              case USB_PORT_FEAT_SUSPEND:
++                      hc->rh_status.wPortStatus |= USB_PORT_STAT_SUSPEND;
++                      OK(0);
++
++              case USB_PORT_FEAT_RESET:
++                      hc->rh_status.wPortStatus |= USB_PORT_STAT_RESET;
++                      hc->rh_status.wPortChange = 0;
++                      hc->rh_status.wPortChange |= USB_PORT_STAT_C_RESET;
++                      hc->rh_status.wPortStatus &= ~USB_PORT_STAT_RESET;
++                      hc->rh_status.wPortStatus |= USB_PORT_STAT_ENABLE;
++                      OK(0);
++
++              case USB_PORT_FEAT_POWER:
++                      hc->rh_status.wPortStatus |= USB_PORT_STAT_POWER;
++                      OK(0);
++
++              case USB_PORT_FEAT_ENABLE:
++                      hc->rh_status.wPortStatus |= USB_PORT_STAT_ENABLE;
++                      OK(0);
++              }
++              break;
++
++      case RH_SET_ADDRESS:
++              hc->rh.devnum = wValue;
++              OK(0);
++
++      case RH_GET_DESCRIPTOR:
++              switch ((wValue & 0xff00) >> 8) {
++              case USB_DT_DEVICE:
++                      len = sizeof(sl811_rh_dev_des);
++                      bufp = sl811_rh_dev_des;
++                      OK(len);
++
++              case USB_DT_CONFIG: 
++                      len = sizeof(sl811_rh_config_des);
++                      bufp = sl811_rh_config_des;
++                      OK(len);
++
++              case USB_DT_STRING:
++                      len = usb_root_hub_string(wValue & 0xff, (int)(long)0,  "SL811HS", data, wLength);
++                      if (len > 0) {
++                              bufp = data;
++                              OK(len);
++                      }
++              
++              default:
++                      status = -EPIPE;
++              }
++              break;
++
++      case RH_GET_DESCRIPTOR | USB_TYPE_CLASS:
++              len = sizeof(sl811_rh_hub_des);
++              bufp = sl811_rh_hub_des;
++              OK(len);
++
++      case RH_GET_CONFIGURATION:
++              bufp[0] = 0x01;
++              OK(1);
++
++      case RH_SET_CONFIGURATION:
++              OK(0);
++
++      default:
++              PDEBUG(1, "unsupported root hub command");
++              status = -EPIPE;
++      }
++
++      len = min(len, buf_len);
++      if (data != bufp)
++              memcpy(data, bufp, len);
++      urb->actual_length = len;
++      urb->status = status;
++
++      PDEBUG(5, "len = %d, status = %d", len, status);
++      
++      urb->hcpriv = NULL;
++      urb->dev = NULL;
++      if (urb->complete)
++              urb->complete(urb);
++
++      return 0;
++}
++
++/*
++ * This function unlinks the URB
++ */
++static int sl811_rh_unlink_urb(struct urb *urb)
++{
++      struct sl811_hc *hc = urb->dev->bus->hcpriv;
++
++      PDEBUG(5, "enter");
++      
++      if (hc->rh.urb == urb) {
++              hc->rh.send = 0;
++              del_timer(&hc->rh.rh_int_timer);
++              hc->rh.urb = NULL;
++              urb->hcpriv = NULL;
++              usb_dec_dev_use(urb->dev);
++              urb->dev = NULL;
++              if (urb->transfer_flags & USB_ASYNC_UNLINK) {
++                      urb->status = -ECONNRESET;
++                      if (urb->complete)
++                              urb->complete(urb);
++              } else
++                      urb->status = -ENOENT;
++      }
++
++      return 0;
++}
++
++/*
++ * This function connect the virtual root hub to the USB stack
++ */
++static int sl811_connect_rh(struct sl811_hc * hc)
++{
++      struct usb_device *usb_dev;
++
++      hc->rh.devnum = 0;
++      usb_dev = usb_alloc_dev(NULL, hc->bus);
++      if (!usb_dev)
++              return -ENOMEM;
++
++      hc->bus->root_hub = usb_dev;
++      usb_connect(usb_dev);
++
++      if (usb_new_device(usb_dev)) {
++              usb_free_dev(usb_dev);
++              return -ENODEV;
++      }
++      
++      PDEBUG(5, "leave success");
++      
++      return 0;
++}
++
++/*
++ * This function allocates private data space for the usb device
++ */
++static int sl811_alloc_dev_priv(struct usb_device *usb_dev)
++{
++      return 0;
++}
++
++/*
++ * This function de-allocates private data space for the usb devic
++ */
++static int sl811_free_dev_priv (struct usb_device *usb_dev)
++{
++      return 0;
++}
++
++/*
++ * This function allocates private data space for the urb
++ */
++static struct sl811_urb_priv* sl811_alloc_urb_priv(struct urb *urb)
++{
++      struct sl811_urb_priv *urbp;
++      
++      urbp = kmalloc(sizeof(*urbp), GFP_KERNEL);
++      if (!urbp)
++              return NULL;
++      
++      memset(urbp, 0, sizeof(*urbp));
++      
++      INIT_LIST_HEAD(&urbp->td_list);
++      
++      urbp->urb = urb;
++      urb->hcpriv = urbp;
++      
++      return urbp;
++}
++
++/*
++ * This function free private data space for the urb
++ */
++static void sl811_free_urb_priv(struct urb *urb)
++{
++      struct sl811_urb_priv *urbp = urb->hcpriv;
++      struct sl811_td *td;
++      struct list_head *head, *tmp;
++      
++      if (!urbp)
++              return ;
++      
++      head = &urbp->td_list;
++      tmp = head->next;
++      
++      while (tmp != head) {
++              td = list_entry(tmp, struct sl811_td, td_list);
++              tmp = tmp->next;
++              kfree(td);
++      }
++      
++      kfree(urbp);
++      urb->hcpriv = NULL;
++      
++      return ;
++}
++
++/*
++ * This       function calculate the bus time need by this td.
++ * Fix me! Can this use usb_calc_bus_time()?
++ */
++static void sl811_calc_td_time(struct sl811_td *td)
++{
++#if 1
++      int time;
++      int len = td->len;
++      struct sl811_hc *hc = td->urb->dev->bus->hcpriv; 
++
++      if (hc->rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED)
++              time = 8*8*len + 1024;
++      else {
++              if (td->ctrl & SL811_USB_CTRL_PREAMBLE)
++                      time = 8*8*len + 2048;
++              else
++                      time = 8*len + 256;
++      }
++
++      time += 2*10 * len;
++
++      td->bustime = time;
++      
++#else
++
++      unsigned long tmp;
++      int time;
++      int low_speed = usb_pipeslow(td->urb->pipe);
++      int input_dir = usb_pipein(td->urb->pipe);
++      int bytecount = td->len;
++      int isoc = usb_pipeisoc(td->urb->pipe); 
++
++      if (low_speed) {        /* no isoc. here */
++              if (input_dir) {
++                      tmp = (67667L * (31L + 10L * BitTime (bytecount))) / 1000L;
++                      time =  (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);
++              } else {
++                      tmp = (66700L * (31L + 10L * BitTime (bytecount))) / 1000L;
++                      time =  (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);
++              }
++      } else if (!isoc){      /* for full-speed: */
++              tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L;
++              time = (9107L + BW_HOST_DELAY + tmp);
++      } else {                /* for isoc: */
++              tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L;
++              time =  (((input_dir) ? 7268L : 6265L) + BW_HOST_DELAY + tmp);
++      }
++      
++      td->bustime = time / 84;
++
++#endif                 
++}
++
++/*
++ * This       function calculate the remainder bus time in current frame.
++ */
++static inline int sl811_calc_bus_remainder(struct sl811_hc *hc)
++{
++      return (sl811_read(hc, SL811_SOFCNTDIV) * 64);
++}
++
++/*
++ * This function allocates td for the urb
++ */
++static struct sl811_td* sl811_alloc_td(struct urb *urb)
++{
++      struct sl811_urb_priv *urbp = urb->hcpriv;
++      struct sl811_td *td;
++      
++      td = kmalloc(sizeof (*td), GFP_KERNEL);
++      if (!td)
++              return NULL;
++      
++      memset(td, 0, sizeof(*td));
++      
++      INIT_LIST_HEAD(&td->td_list);
++      
++      td->urb = urb;
++      list_add_tail(&td->td_list, &urbp->td_list);
++      
++      return td;
++}
++
++/*
++ * Fill the td.
++ */
++static inline void sl811_fill_td(struct sl811_td *td, __u8 ctrl, __u8 addr, __u8 len, __u8 pidep, __u8 dev, __u8 *buf)
++{
++      td->ctrl = ctrl;
++      td->addr = addr;
++      td->len = len;
++      td->pidep = pidep;
++      td->dev = dev;
++      td->buf = buf;
++      td->left = len;
++      td->errcnt = 3;
++}
++
++/*
++ * Fill the td.
++ */
++static inline void sl811_reset_td(struct sl811_td *td)
++{
++      td->status = 0;
++      td->left = td->len;
++      td->done = 0;
++      td->errcnt = 3;
++      td->nakcnt = 0;
++      td->td_status = 0;
++}
++
++static void sl811_print_td(int level, struct sl811_td *td)
++{
++       PDEBUG(level, "td = %p, ctrl = %x, addr = %x, len = %x, pidep = %x\n "
++              "dev = %x, status = %x, left = %x, errcnt = %x, done = %x\n "
++              "buf = %p, bustime = %d, td_status = %d\n", 
++              td, td->ctrl, td->addr, td->len, td->pidep,
++              td->dev, td->status, td->left, td->errcnt, td->done,
++              td->buf, td->bustime, td->td_status);
++}
++
++/*
++ * Isochronous transfers
++ */
++static int sl811_submit_isochronous(struct urb *urb)
++{
++      __u8 dev = usb_pipedevice(urb->pipe);
++      __u8 pidep = PIDEP(usb_packetid(urb->pipe), usb_pipeendpoint(urb->pipe));
++      __u8 ctrl = 0;
++      struct sl811_urb_priv *urbp = urb->hcpriv;
++      struct sl811_td *td = NULL;
++      int i;
++      
++      PDEBUG(4, "enter, urb = %p, urbp = %p", urb, urbp);
++      
++      /* Can't have low speed bulk transfers */
++      if (usb_pipeslow(urb->pipe)) {
++              PDEBUG(1, "error, urb = %p, low speed device", urb);
++              return -EINVAL;
++      }
++      
++      if (usb_pipeout(urb->pipe))
++              ctrl |= SL811_USB_CTRL_DIR_OUT;
++              
++      ctrl |= SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE | SL811_USB_CTRL_ISO;
++      
++      for (i = 0; i < urb->number_of_packets; i++) {
++              urb->iso_frame_desc[i].actual_length = 0;
++              urb->iso_frame_desc[i].status = -EXDEV;
++                      
++              td = sl811_alloc_td(urb);
++              if (!td)
++                      return -ENOMEM;
++
++              sl811_fill_td(td, ctrl, SL811_DATA_START, 
++                      urb->iso_frame_desc[i].length,
++                      pidep, dev,
++                      urb->transfer_buffer + urb->iso_frame_desc[i].offset);
++              sl811_calc_td_time(td);
++              if (urbp->cur_td == NULL)
++                      urbp->cur_td = urbp->first_td = td;     
++      }
++
++      urbp->last_td = td;     
++      
++      PDEBUG(4, "leave success");
++
++/*    
++// for debug
++      {
++              struct list_head *head, *tmp;
++              struct sl811_td *td;
++              int i = 0;
++              head = &urbp->td_list;
++              tmp = head->next;
++      
++              if (list_empty(&urbp->td_list)) {
++                      PDEBUG(1, "bug!!! td list is empty!");
++                      return -ENODEV;
++              }
++              
++              while (tmp != head) {
++                      ++i;
++                      td = list_entry(tmp, struct sl811_td, td_list);
++                      PDEBUG(2, "td = %p, i = %d", td, i);
++                      tmp = tmp->next;
++              }
++      }
++*/    
++      return 0;
++}
++
++/*
++ * Reset isochronous transfers
++ */
++static void sl811_reset_isochronous(struct urb *urb)
++{
++      struct sl811_urb_priv *urbp = urb->hcpriv;
++      struct sl811_td *td = NULL;
++      struct list_head *head, *tmp;
++      int i;
++
++      PDEBUG(4, "enter, urb = %p", urb);
++      
++      for (i = 0; i < urb->number_of_packets; i++) {
++              urb->iso_frame_desc[i].actual_length = 0;
++              urb->iso_frame_desc[i].status = -EXDEV;
++      }
++
++      head = &urbp->td_list;
++      tmp = head->next;
++      while (tmp != head) {
++              td = list_entry(tmp, struct sl811_td, td_list);
++              tmp = tmp->next;
++              sl811_reset_td(td);
++      }
++      
++      urbp->cur_td = urbp->first_td;
++      
++      urb->status = -EINPROGRESS;
++      urb->actual_length = 0;
++      urb->error_count = 0;
++}
++
++/*
++ * Result the iso urb.
++ */
++static void sl811_result_isochronous(struct urb *urb)
++{
++      struct list_head *tmp, *head;
++      struct sl811_urb_priv *urbp = urb->hcpriv;
++      int status = 0;
++      struct sl811_td *td;
++      int i;
++
++      PDEBUG(4, "enter, urb = %p", urb);
++              
++      urb->actual_length = 0;
++
++      i = 0;
++      head = &urbp->td_list;
++      tmp = head->next;
++      while (tmp != head) {
++              td = list_entry(tmp, struct sl811_td, td_list);
++              tmp = tmp->next;
++              
++              if (!td->done) {
++                      if (urbp->unlink)
++                              urb->status = -ENOENT;
++                      else {
++                              PDEBUG(1, "we should not get here!");
++                              urb->status = -EXDEV;
++                      }
++                      return ;        
++              }
++              if (td->td_status) {
++                      status = td->td_status;
++                      urb->error_count++;
++                      PDEBUG(1, "error: td = %p, td status = %d", td, td->td_status);
++              }
++
++              urb->iso_frame_desc[i].actual_length = td->len - td->left;
++              urb->actual_length += td->len - td->left;
++              urb->iso_frame_desc[i].status = td->td_status;
++              ++i;
++              if (td->left)
++                      PDEBUG(3, "short packet, td = %p, len = %d, left = %d", td, td->len, td->left);
++      }
++
++      urb->status = status;
++/*
++// for debug
++      PDEBUG(2, "iso urb complete, len = %d, status =%d ", urb->actual_length, urb->status);          
++*/
++      PDEBUG(4, "leave success");
++}
++
++/*
++ * Interrupt transfers
++ */
++static int sl811_submit_interrupt(struct urb *urb)
++{
++      int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
++      int len = urb->transfer_buffer_length;
++      __u8 *data = urb->transfer_buffer;
++      __u8 dev = usb_pipedevice(urb->pipe);
++      __u8 pidep = PIDEP(usb_packetid(urb->pipe), usb_pipeendpoint(urb->pipe));
++      __u8 ctrl = 0;
++      struct sl811_hc *hc = urb->dev->bus->hcpriv;
++      struct sl811_urb_priv *urbp = urb->hcpriv;
++      struct sl811_td *td = NULL;
++      
++      PDEBUG(4, "enter, urb = %p", urb);
++      
++      if (len > maxsze) {
++              PDEBUG(1, "length is big than max packet size, len = %d, max packet = %d", len, maxsze);
++              return -EINVAL;
++      }
++      if (usb_pipeslow(urb->pipe) && !(hc->rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED))
++              ctrl |= SL811_USB_CTRL_PREAMBLE;
++      
++      ctrl |= SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE;
++      if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)))
++              ctrl |= SL811_USB_CTRL_TOGGLE_1;
++      usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));    
++      td = sl811_alloc_td(urb);
++      if (!td)
++              return -ENOMEM;
++              
++      sl811_fill_td(td, ctrl, SL811_DATA_START, len, pidep, dev, data);
++      sl811_calc_td_time(td);
++      urbp->cur_td = urbp->first_td = urbp->last_td = td;
++      urbp->interval = 0;
++      
++      PDEBUG(4, "leave success");
++      
++      return 0;
++}
++
++/*
++ * Reset interrupt transfers
++ */
++static void sl811_reset_interrupt(struct urb *urb)
++{
++      struct sl811_urb_priv *urbp = urb->hcpriv;
++      struct sl811_td *td = urbp->cur_td;
++      
++      PDEBUG(4, "enter, interval = %d", urb->interval);
++      
++      td->ctrl &= ~SL811_USB_CTRL_TOGGLE_1;
++      if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)))
++              td->ctrl |= SL811_USB_CTRL_TOGGLE_1;
++      usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));    
++      
++      sl811_reset_td(td);
++
++      urbp->interval = urb->interval;
++      
++      urb->status = -EINPROGRESS;
++      urb->actual_length = 0;
++}
++
++/*
++ * Result the interrupt urb.
++ */
++static void sl811_result_interrupt(struct urb *urb)
++{
++      struct list_head *tmp;
++      struct sl811_urb_priv *urbp = urb->hcpriv;
++      struct sl811_td *td;
++      int toggle;
++      
++      PDEBUG(4, "enter, urb = %p", urb);
++      
++      urb->actual_length = 0;
++
++      tmp = &urbp->td_list;
++      tmp = tmp->next;
++      td = list_entry(tmp, struct sl811_td, td_list);
++
++      // success.
++      if (td->done && td->td_status == 0) {
++              urb->actual_length += td->len - td->left;
++              urb->status = 0;
++              return ;
++      }
++      // tranfer is done but fail, reset the toggle.
++      else if (td->done && td->td_status) {
++              urb->status = td->td_status;
++reset_toggle:
++              toggle = (td->ctrl & SL811_USB_CTRL_TOGGLE_1) ? 1 : 0;
++              usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), toggle);
++              PDEBUG(3, "error: td = %p, td status = %d", td, td->td_status);
++              return ;
++      }
++      // unlink, and not do transfer yet
++      else if (td->done == 0 && urbp->unlink && td->td_status == 0) {
++              urb->status = -ENOENT;
++              PDEBUG(3, "unlink and not transfer!");
++              return ;
++      }
++      // unlink, and transfer not complete yet.
++      else if (td->done == 0 && urbp->unlink && td->td_status) {
++              urb->status = -ENOENT;
++              PDEBUG(3, "unlink and not complete!");
++              goto reset_toggle;
++      }
++      // must be bug!!!
++      else {// (td->done == 0 && urbp->unlink == 0)
++              PDEBUG(1, "we should not get here!");
++              urb->status = -EPIPE;
++              return ;
++      }
++}
++
++/*
++ * Control transfers
++ */
++static int sl811_submit_control(struct urb *urb)
++{
++      int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
++      int len = urb->transfer_buffer_length;
++      __u8 *data = urb->transfer_buffer;
++      __u8 dev = usb_pipedevice(urb->pipe);
++      __u8 pidep = 0;
++      __u8 ctrl = 0;
++      struct sl811_hc *hc = urb->dev->bus->hcpriv;
++      struct sl811_urb_priv *urbp = urb->hcpriv;
++      struct sl811_td *td = NULL;
++      
++      PDEBUG(4, "enter, urb = %p", urb);
++      
++      if (usb_pipeslow(urb->pipe) && !(hc->rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED))
++              ctrl |= SL811_USB_CTRL_PREAMBLE;
++      
++      /* Build SETUP TD */
++      pidep = PIDEP(USB_PID_SETUP, usb_pipeendpoint(urb->pipe));
++      ctrl |= SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE | SL811_USB_CTRL_DIR_OUT;
++      td = sl811_alloc_td(urb);
++      if (!td)
++              return -ENOMEM;
++              
++      sl811_fill_td(td, ctrl, SL811_DATA_START, 8, pidep, dev, urb->setup_packet);
++      sl811_calc_td_time(td);
++      
++      urbp->cur_td = urbp->first_td = td;
++      
++      /*
++       * If direction is "send", change the frame from SETUP (0x2D)
++       * to OUT (0xE1). Else change it from SETUP to IN (0x69).
++       */
++      pidep = PIDEP(usb_packetid(urb->pipe), usb_pipeendpoint(urb->pipe));
++      if (usb_pipeout(urb->pipe))
++              ctrl |= SL811_USB_CTRL_DIR_OUT;
++      else
++              ctrl &= ~SL811_USB_CTRL_DIR_OUT;
++
++      /* Build the DATA TD's */
++      while (len > 0) {
++              int pktsze = len;
++
++              if (pktsze > maxsze)
++                      pktsze = maxsze;
++
++              /* Alternate Data0/1 (start with Data1) */
++              ctrl ^= SL811_USB_CTRL_TOGGLE_1;
++      
++              td = sl811_alloc_td(urb);
++              if (!td)
++                      return -ENOMEM;
++
++              sl811_fill_td(td, ctrl, SL811_DATA_START, pktsze, pidep, dev, data);    
++              sl811_calc_td_time(td);
++              
++              data += pktsze;
++              len -= pktsze;
++      }
++
++      /* Build the final TD for control status */
++      td = sl811_alloc_td(urb);
++      if (!td)
++              return -ENOMEM;
++
++      /* It's IN if the pipe is an output pipe or we're not expecting data back */
++      if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length) {
++              pidep = PIDEP(USB_PID_IN, usb_pipeendpoint(urb->pipe));
++              ctrl &= ~SL811_USB_CTRL_DIR_OUT;        
++      } else {
++              pidep = PIDEP(USB_PID_OUT, usb_pipeendpoint(urb->pipe));
++              ctrl |= SL811_USB_CTRL_DIR_OUT;
++      }
++              
++      /* End in Data1 */
++      ctrl |= SL811_USB_CTRL_TOGGLE_1;
++
++      sl811_fill_td(td, ctrl, SL811_DATA_START, 0, pidep, dev, 0);
++      sl811_calc_td_time(td);
++      urbp->last_td = td;
++/*    
++// for debug
++      {
++              struct list_head *head, *tmp;
++              struct sl811_td *td;
++              int i = 0;
++              head = &urbp->td_list;
++              tmp = head->next;
++      
++              if (list_empty(&urbp->td_list)) {
++                      PDEBUG(1, "bug!!! td list is empty!");
++                      return -ENODEV;
++              }
++              
++              while (tmp != head) {
++                      ++i;
++                      td = list_entry(tmp, struct sl811_td, td_list);
++                      PDEBUG(3, "td = %p, i = %d", td, i);
++                      tmp = tmp->next;
++              }
++      }
++*/    
++      PDEBUG(4, "leave success");
++      
++      return 0;
++}
++
++/*
++ * Result the control urb.
++ */
++static void sl811_result_control(struct urb *urb)
++{
++      struct list_head *tmp, *head;
++      struct sl811_urb_priv *urbp = urb->hcpriv;
++      struct sl811_td *td;
++
++      PDEBUG(4, "enter, urb = %p", urb);
++      
++      if (list_empty(&urbp->td_list)) {
++              PDEBUG(1, "td list is empty");
++              return ;
++      }
++
++      head = &urbp->td_list;
++
++      tmp = head->next;
++      td = list_entry(tmp, struct sl811_td, td_list);
++
++      /* The first TD is the SETUP phase, check the status, but skip the count */
++      if (!td->done) {
++              PDEBUG(3, "setup phase error, td = %p, done = %d", td, td->done);
++              goto err_done;
++      }
++      if (td->td_status)  {
++              PDEBUG(3, "setup phase error, td = %p, td status = %d", td, td->td_status);
++              goto err_status;
++      }
++
++      urb->actual_length = 0;
++
++      /* The rest of the TD's (but the last) are data */
++      tmp = tmp->next;
++      while (tmp != head && tmp->next != head) {
++              td = list_entry(tmp, struct sl811_td, td_list);
++              tmp = tmp->next;
++              if (!td->done) {
++                      PDEBUG(3, "data phase error, td = %p, done = %d", td, td->done);
++                      goto err_done;
++              }
++              if (td->td_status)  {
++                      PDEBUG(3, "data phase error, td = %p, td status = %d", td, td->td_status);
++                      goto err_status;
++              }
++
++              urb->actual_length += td->len - td->left;
++              // short packet.
++              if (td->left) {
++                      PDEBUG(3, "data phase short packet, td = %p, count = %d", td, td->len - td->left);
++                      break;
++              }
++      }
++
++      /* The last td is status phase */
++      td = urbp->last_td;
++      if (!td->done) {
++              PDEBUG(3, "status phase error, td = %p, done = %d", td, td->done);
++              goto err_done;
++      }
++      if (td->td_status)  {
++              PDEBUG(3, "status phase error, td = %p, td status = %d", td, td->td_status);
++              goto err_status;
++      }
++      
++      PDEBUG(4, "leave success");
++      
++      urb->status = 0;
++      return ;
++
++err_done:
++      if (urbp->unlink)
++              urb->status = -ENOENT;
++      else {
++              PDEBUG(1, "we should not get here! td = %p", td);
++              urb->status = -EPIPE;
++      }
++      return ;        
++
++err_status:
++      urb->status = td->td_status;            
++      return ;
++}
++
++/*
++ * Bulk transfers
++ */
++static int sl811_submit_bulk(struct urb *urb)
++{
++      int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
++      int len = urb->transfer_buffer_length;
++      __u8 *data = urb->transfer_buffer;
++      __u8 dev = usb_pipedevice(urb->pipe);
++      __u8 pidep = PIDEP(usb_packetid(urb->pipe), usb_pipeendpoint(urb->pipe));
++      __u8 ctrl = 0;
++      struct sl811_urb_priv *urbp = urb->hcpriv;
++      struct sl811_td *td = NULL;
++
++      PDEBUG(4, "enter, urb = %p", urb);
++              
++      if (len < 0) {
++              PDEBUG(1, "error, urb = %p, len = %d", urb, len);
++              return -EINVAL;
++      }
++
++      /* Can't have low speed bulk transfers */
++      if (usb_pipeslow(urb->pipe)) {
++              PDEBUG(1, "error, urb = %p, low speed device", urb);
++              return -EINVAL;
++      }
++
++      if (usb_pipeout(urb->pipe))
++              ctrl |= SL811_USB_CTRL_DIR_OUT;
++              
++      ctrl |= SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE;
++                      
++      /* Build the DATA TD's */
++      do {    /* Allow zero length packets */
++              int pktsze = len;
++
++              if (pktsze > maxsze)
++                      pktsze = maxsze;
++
++              td = sl811_alloc_td(urb);
++              if (!td)
++                      return -ENOMEM;
++
++              /* Alternate Data0/1 (start with Data1) */
++              ctrl &= ~SL811_USB_CTRL_TOGGLE_1;
++              if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)))
++                      ctrl |= SL811_USB_CTRL_TOGGLE_1;
++              usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));            
++              
++              sl811_fill_td(td, ctrl, SL811_DATA_START, pktsze, pidep, dev, data);
++              sl811_calc_td_time(td);
++              
++              if (urbp->cur_td == NULL)
++                      urbp->cur_td = urbp->first_td = td;
++                      
++              data += pktsze;
++              len -= maxsze;
++      } while (len > 0);
++
++      /*
++       * USB_ZERO_PACKET means adding a 0-length packet, if
++       * direction is OUT and the transfer_length was an
++       * exact multiple of maxsze, hence
++       * (len = transfer_length - N * maxsze) == 0
++       * however, if transfer_length == 0, the zero packet
++       * was already prepared above.
++       */
++      if (usb_pipeout(urb->pipe) && (urb->transfer_flags & USB_ZERO_PACKET) &&
++         !len && urb->transfer_buffer_length) {
++              
++              td = sl811_alloc_td(urb);
++              if (!td)
++                      return -ENOMEM;
++
++              /* Alternate Data0/1 (start with Data1) */
++              ctrl &= ~SL811_USB_CTRL_TOGGLE_1;
++              if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)))
++                      ctrl |= SL811_USB_CTRL_TOGGLE_1;
++              usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
++                      
++              sl811_fill_td(td, ctrl, SL811_DATA_START, 0, pidep, dev, 0);
++              sl811_calc_td_time(td);
++      }
++      
++      urbp->last_td = td;
++      
++      PDEBUG(4, "leave success");
++      
++      return 0;
++}
++
++/*
++ * Reset bulk transfers
++ */
++static int sl811_reset_bulk(struct urb *urb)
++{
++      struct sl811_urb_priv *urbp = urb->hcpriv;
++      struct sl811_td *td;
++      struct list_head *head, *tmp;
++
++      PDEBUG(4, "enter, urb = %p", urb);
++      
++      
++      head = &urbp->td_list;  
++      tmp = head->next;
++      
++      while (tmp != head) {
++              td = list_entry(tmp, struct sl811_td, td_list);
++
++              /* Alternate Data0/1 (start with Data1) */
++              td->ctrl &= ~SL811_USB_CTRL_TOGGLE_1;
++              if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)))
++                      td->ctrl |= SL811_USB_CTRL_TOGGLE_1;
++              usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
++              
++              sl811_reset_td(td);
++      } 
++
++      urb->status = -EINPROGRESS;
++      urb->actual_length = 0;
++      urbp->cur_td = urbp->first_td;
++
++      PDEBUG(4, "leave success");
++      
++      return 0;
++}
++
++/*
++ * Result the bulk urb.
++ */
++static void sl811_result_bulk(struct urb *urb)
++{
++      struct list_head *tmp, *head;
++      struct sl811_urb_priv *urbp = urb->hcpriv;
++      struct sl811_td *td = NULL;
++      int toggle;
++
++      PDEBUG(4, "enter, urb = %p", urb);
++      
++      urb->actual_length = 0;
++
++      head = &urbp->td_list;
++      tmp = head->next;
++      while (tmp != head) {
++              td = list_entry(tmp, struct sl811_td, td_list);
++              tmp = tmp->next;
++
++              // success.
++              if (td->done && td->td_status == 0) {
++                      urb->actual_length += td->len - td->left;
++                      
++                      // short packet
++                      if (td->left) {
++                              urb->status = 0;
++                              PDEBUG(3, "short packet, td = %p, count = %d", td, td->len - td->left);
++                              goto reset_toggle;
++                      }
++              }
++              // tranfer is done but fail, reset the toggle.
++              else if (td->done && td->td_status) {
++                      urb->status = td->td_status;
++                      PDEBUG(3, "error: td = %p, td status = %d", td, td->td_status);
++                      goto reset_toggle;
++              }
++              // unlink, and not do transfer yet
++              else if (td->done == 0 && urbp->unlink && td->td_status == 0) {
++                      urb->status = -ENOENT;
++                      PDEBUG(3, "unlink and not transfer!");
++                      return ;
++              }
++              // unlink, and transfer not complete yet.
++              else if (td->done == 0 && urbp->unlink && td->td_status) {
++                      PDEBUG(3, "unlink and not complete!");
++                      urb->status = -ENOENT;
++                      goto reset_toggle;
++              }
++              // must be bug!!!
++              else {// (td->done == 0 && urbp->unlink == 0)
++                      urb->status = -EPIPE;
++                      PDEBUG(1, "we should not get here!");
++                      return ;
++              }
++      }
++      
++      PDEBUG(4, "leave success");             
++      urb->status = 0;
++      return ;
++
++reset_toggle:
++      toggle = (td->ctrl & SL811_USB_CTRL_TOGGLE_1) ? 1 : 0;
++      usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), toggle);
++}
++
++/*
++ * Find the first urb have the same dev and endpoint.
++ */
++static inline int sl811_find_same_urb(struct list_head *head, struct urb *urb)
++{
++      struct list_head *tmp;
++      struct urb *u;
++      
++      if (!head || !urb)
++              return 0;
++              
++      tmp = head->next;
++      
++      while (tmp != head) {
++              u = list_entry(tmp, struct urb, urb_list);
++              if (u == urb)
++                      return 1;
++              tmp = tmp->next;        
++      }
++      
++      return 0;
++}
++
++/*
++ * Find the first urb have the same dev and endpoint.
++ */
++static inline struct urb* sl811_find_same_devep(struct list_head *head, struct urb *urb)
++{
++      struct list_head *tmp;
++      struct urb *u;
++      
++      if (!head || !urb)
++              return NULL;
++              
++      tmp = head->next;
++      
++      while (tmp != head) {
++              u = list_entry(tmp, struct urb, urb_list);
++              if ((usb_pipe_endpdev(u->pipe)) == (usb_pipe_endpdev(urb->pipe)))
++                      return u;
++              tmp = tmp->next;        
++      }
++      
++      return NULL;
++}
++
++/*
++ * This function is called by the USB core API when an URB is available to
++ * process. 
++ */
++static int sl811_submit_urb(struct urb *urb)
++{
++      struct sl811_hc *hc = urb->dev->bus->hcpriv;
++      unsigned int pipe = urb->pipe;
++      struct list_head *head = NULL;
++      unsigned long flags;
++      int bustime;
++      int ret = 0;
++      
++      if (!urb) {
++              PDEBUG(1, "urb is null");
++              return -EINVAL;
++      }
++      
++      if (urb->hcpriv) {
++              PDEBUG(1, "urbp is not null, urb = %p, urbp = %p", urb, urb->hcpriv);
++              return -EINVAL;
++      }
++      
++      if (!urb->dev || !urb->dev->bus || !hc)  {
++              PDEBUG(1, "dev or bus or hc is null");
++              return -ENODEV;
++      }
++      
++      if (usb_endpoint_halted(urb->dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) {
++              PDEBUG(2, "sl811_submit_urb: endpoint_halted");
++              return -EPIPE;
++      }
++      
++      if (usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)) > SL811_DATA_LIMIT) {
++              printk(KERN_ERR "Packet size is big for SL811, should < %d!\n", SL811_DATA_LIMIT);
++              return -EINVAL;
++      }
++      
++      /* a request to the virtual root hub */ 
++      if (usb_pipedevice(pipe) == hc->rh.devnum)
++              return sl811_rh_submit_urb(urb);
++      
++      spin_lock_irqsave(&hc->hc_lock, flags);
++      spin_lock(&urb->lock);
++      
++      switch (usb_pipetype(urb->pipe)) {
++      case PIPE_ISOCHRONOUS:
++              head = &hc->iso_list;
++              break;
++      case PIPE_INTERRUPT:
++              head = &hc->intr_list;
++              break;
++      case PIPE_CONTROL:
++              head = &hc->ctrl_list;
++              break;
++      case PIPE_BULK:
++              head = &hc->bulk_list;
++              break;
++      }
++              
++      if (sl811_find_same_devep(head, urb)) {
++              list_add(&urb->urb_list, &hc->wait_list);
++              PDEBUG(4, "add to wait list");
++              goto out_unlock;
++      }
++      
++      if (!sl811_alloc_urb_priv(urb)) {
++              ret = -ENOMEM;
++              goto out_unlock;
++      }
++      
++      switch (usb_pipetype(urb->pipe)) {
++      case PIPE_ISOCHRONOUS:
++              if (urb->number_of_packets <= 0) {
++                      ret = -EINVAL;
++                      break;
++              }
++              bustime = usb_check_bandwidth(urb->dev, urb);
++              if (bustime < 0) {
++                      ret = bustime;
++                      break;
++              }
++              if (!(ret = sl811_submit_isochronous(urb)))
++                      usb_claim_bandwidth(urb->dev, urb, bustime, 1);
++              break;
++      case PIPE_INTERRUPT:
++              bustime = usb_check_bandwidth(urb->dev, urb);
++              if (bustime < 0)
++                      ret = bustime;
++              else if (!(ret = sl811_submit_interrupt(urb)))
++                      usb_claim_bandwidth(urb->dev, urb, bustime, 0);
++              break;
++      case PIPE_CONTROL:
++              ret = sl811_submit_control(urb);
++              break;
++      case PIPE_BULK:
++              ret = sl811_submit_bulk(urb);
++              break;
++      }
++      
++      if (!ret) {
++              ((struct sl811_urb_priv *)urb->hcpriv)->inserttime = jiffies;
++              list_add(&urb->urb_list, head);
++              PDEBUG(4, "add to type list");
++              urb->status = -EINPROGRESS;
++              if (++hc->active_urbs == 1)
++                      sl811_enable_interrupt(hc);
++              goto out_unlock;        
++      } else {
++              PDEBUG(2, "submit urb fail! error = %d", ret);
++              sl811_free_urb_priv(urb);
++      }
++      
++out_unlock:   
++      spin_unlock(&urb->lock);
++      spin_unlock_irqrestore(&hc->hc_lock, flags);
++
++      return ret;
++}
++
++/*
++ * Submit the urb the wait list.
++ */
++static int sl811_submit_urb_with_lock(struct urb *urb)
++{
++      struct sl811_hc *hc = urb->dev->bus->hcpriv;
++      struct list_head *head = NULL;
++      int bustime;
++      int ret = 0;
++      
++      spin_lock(&urb->lock);
++      
++      switch (usb_pipetype(urb->pipe)) {
++      case PIPE_ISOCHRONOUS:
++              head = &hc->iso_list;
++              break;
++      case PIPE_INTERRUPT:
++              head = &hc->intr_list;
++              break;
++      case PIPE_CONTROL:
++              head = &hc->ctrl_list;
++              break;
++      case PIPE_BULK:
++              head = &hc->bulk_list;
++              break;
++      }
++              
++      if (!sl811_alloc_urb_priv(urb)) {
++              ret = -ENOMEM;
++              goto out_unlock;
++      }
++      
++      switch (usb_pipetype(urb->pipe)) {
++      case PIPE_ISOCHRONOUS:
++              if (urb->number_of_packets <= 0) {
++                      ret = -EINVAL;
++                      break;
++              }
++              bustime = usb_check_bandwidth(urb->dev, urb);
++              if (bustime < 0) {
++                      ret = bustime;
++                      break;
++              }
++              if (!(ret = sl811_submit_isochronous(urb)))
++                      usb_claim_bandwidth(urb->dev, urb, bustime, 1);
++              break;
++      case PIPE_INTERRUPT:
++              bustime = usb_check_bandwidth(urb->dev, urb);
++              if (bustime < 0)
++                      ret = bustime;
++              else if (!(ret = sl811_submit_interrupt(urb)))
++                      usb_claim_bandwidth(urb->dev, urb, bustime, 0);
++              break;
++      case PIPE_CONTROL:
++              ret = sl811_submit_control(urb);
++              break;
++      case PIPE_BULK:
++              ret = sl811_submit_bulk(urb);
++              break;
++      }
++      
++      if (ret == 0) {
++              ((struct sl811_urb_priv *)urb->hcpriv)->inserttime = jiffies;
++              list_add(&urb->urb_list, head);
++              PDEBUG(4, "add to type list");
++              urb->status = -EINPROGRESS;
++              if (++hc->active_urbs == 1)
++                      sl811_enable_interrupt(hc);
++              goto out_unlock;        
++      } else {
++              PDEBUG(2, "submit urb fail! error = %d", ret);
++              sl811_free_urb_priv(urb);
++      }
++      
++out_unlock:   
++      spin_unlock(&urb->lock);
++
++      return ret;
++}
++
++/*
++ * Reset the urb
++ */
++static void sl811_reset_urb(struct urb *urb)
++{
++      struct sl811_urb_priv *urbp = urb->hcpriv;
++
++      switch (usb_pipetype(urb->pipe)) {
++      case PIPE_ISOCHRONOUS:
++              sl811_reset_isochronous(urb);
++              break;
++      case PIPE_INTERRUPT:
++              sl811_reset_interrupt(urb);
++              break;
++      case PIPE_CONTROL:
++              return;
++      case PIPE_BULK:
++              sl811_reset_bulk(urb);
++              break;
++      }
++      urbp->inserttime = jiffies;
++}
++
++/*
++ * Return the result of a transfer
++ */
++static void sl811_result_urb(struct urb *urb)
++{
++      struct sl811_urb_priv *urbp = urb->hcpriv;
++      struct sl811_hc *hc = urb->dev->bus->hcpriv;
++      struct list_head *head = NULL;
++      struct urb *u = NULL;
++      int reset = 0;
++      int ring = 0;
++
++      if (urb->status != -EINPROGRESS) {
++              PDEBUG(1, "urb status is not EINPROGRESS!");
++              return ;
++      }
++      
++      spin_lock(&urb->lock);
++      
++      switch (usb_pipetype(urb->pipe)) {
++      case PIPE_ISOCHRONOUS:
++              head = &hc->iso_list;
++              sl811_result_isochronous(urb);
++              
++              // if the urb is not unlink and is in a urb "ring", we reset it
++              if (!urbp->unlink && urb->next) 
++                      ring = 1;
++              break;
++      case PIPE_INTERRUPT:
++              head = &hc->intr_list;
++              sl811_result_interrupt(urb);
++              
++              // if the urb is not unlink and not "once" query, we reset.
++              if (!urbp->unlink && urb->interval)
++                      reset = 1;
++              break;
++      case PIPE_CONTROL:
++              head = &hc->ctrl_list;
++              sl811_result_control(urb);
++              break;
++      case PIPE_BULK:
++              head = &hc->bulk_list;
++              sl811_result_bulk(urb);
++              
++              // if the urb is not unlink and is in a urb "ring", we reset it
++              if (!urbp->unlink && urb->next)
++                      ring = 1;
++              break;
++      }
++      
++      PDEBUG(4, "result urb status = %d", urb->status);
++      
++      if (ring && urb->next == urb)
++              reset = 1;
++      
++      if (!reset) {
++              switch (usb_pipetype(urb->pipe)) {
++              case PIPE_ISOCHRONOUS:
++                      usb_release_bandwidth(urb->dev, urb, 1);
++                      break;
++              case PIPE_INTERRUPT:
++                      usb_release_bandwidth(urb->dev, urb, 0);
++                      break;
++              }
++              sl811_free_urb_priv(urb);
++      }
++      
++      spin_unlock(&urb->lock);
++      
++      if (urb->complete)
++              urb->complete(urb);
++      
++      if (reset) {
++              spin_lock(&urb->lock);
++              sl811_reset_urb(urb);
++              if (usb_pipeint(urb->pipe))
++                      list_add(&urb->urb_list, &hc->idle_intr_list);
++              else
++                      list_add(&urb->urb_list, head);
++              spin_unlock(&urb->lock);
++      } else {
++              if (--hc->active_urbs <= 0) {
++                      hc->active_urbs = 0;
++                      sl811_disable_interrupt(hc);
++              }
++              
++              if (ring) 
++                      u = urb->next;
++              else
++                      u = sl811_find_same_devep(&hc->wait_list, urb);
++                      
++              if (u) {
++                      if (!list_empty(&u->urb_list))
++                              list_del(&u->urb_list);
++                      if (sl811_submit_urb_with_lock(u))
++                              list_add(&u->urb_list, &hc->wait_list);
++              }
++      }
++}
++
++
++#ifdef SL811_TIMEOUT
++
++/*
++ * Unlink the urb from the urb list
++ */
++static int sl811_unlink_urb(struct urb *urb)
++{
++      unsigned long flags;
++      struct sl811_hc *hc;
++      struct sl811_urb_priv *urbp;
++      int call = 0;
++      int schedule = 0;
++      int count = 0;
++      
++      if (!urb) {
++              PDEBUG(1, "urb is null");
++              return -EINVAL;
++      }
++      
++      if (!urb->dev || !urb->dev->bus) {
++              PDEBUG(1, "dev or bus is null");
++              return -ENODEV;
++      }
++      
++      hc = urb->dev->bus->hcpriv; 
++      urbp = urb->hcpriv;
++      
++      /* a request to the virtual root hub */
++      if (usb_pipedevice(urb->pipe) == hc->rh.devnum)
++              return sl811_rh_unlink_urb(urb); 
++      
++      spin_lock_irqsave(&hc->hc_lock, flags);
++      spin_lock(&urb->lock);
++
++      // in wait list
++      if (sl811_find_same_urb(&hc->wait_list, urb)) { 
++              PDEBUG(4, "unlink urb in wait list");
++              list_del_init(&urb->urb_list);
++              urb->status = -ENOENT;
++              call = 1;
++              goto out;
++      }
++      
++      // in intr idle list.
++      if (sl811_find_same_urb(&hc->idle_intr_list, urb)) {    
++              PDEBUG(4, "unlink urb in idle intr list");
++              list_del_init(&urb->urb_list);
++              urb->status = -ENOENT;
++              sl811_free_urb_priv(urb);
++              usb_release_bandwidth(urb->dev, urb, 0);
++              if (--hc->active_urbs <= 0) {
++                      hc->active_urbs = 0;
++                      sl811_disable_interrupt(hc);
++              }
++              call = 1;
++              goto out;
++      }
++
++      if (urb->status == -EINPROGRESS) {  
++              PDEBUG(3, "urb is still in progress");
++              urbp->unlink = 1;
++
++re_unlink:
++              // Is it in progress?
++              urbp = urb->hcpriv;
++              if (urbp && hc->cur_td == urbp->cur_td) {
++                      ++count;
++                      if (sl811_read(hc, 0) & SL811_USB_CTRL_ARM) {
++                              PDEBUG(3, "unlink: cur td is still in progress! count = %d", count);
++re_schedule:                          
++                              schedule = 1;
++                              spin_unlock(&urb->lock);
++                              spin_unlock_irqrestore(&hc->hc_lock, flags);
++                              schedule_timeout(HZ/50);
++                              spin_lock_irqsave(&hc->hc_lock, flags);
++                              spin_lock(&urb->lock);
++                      } else {
++                              PDEBUG(3, "unlink: lost of interrupt? do parse! count = %d", count);
++                              spin_unlock(&urb->lock);
++                              sl811_transfer_done(hc, 0);
++                              spin_lock(&urb->lock);
++                      }
++                      goto re_unlink;
++              }
++              
++              if (list_empty(&urb->urb_list)) {
++                      PDEBUG(3, "unlink: list empty!");
++                      goto out;
++              }
++                      
++              if (urb->transfer_flags & USB_TIMEOUT_KILLED) { 
++                      PDEBUG(3, "unlink: time out killed");
++                      // it is timeout killed by us 
++                      goto result;
++              } else if (urb->transfer_flags & USB_ASYNC_UNLINK) { 
++                      // we do nothing, just let it be processing later
++                      PDEBUG(3, "unlink async, do nothing");
++                      goto out;
++              } else {
++                      // synchron without callback
++                      PDEBUG(3, "unlink synchron, we wait the urb complete or timeout");
++                      if (schedule == 0) {
++                              PDEBUG(3, "goto re_schedule");
++                              goto re_schedule;
++                      } else {
++                              PDEBUG(3, "already scheduled");
++                              goto result;
++                      }
++              }
++      } else if (!list_empty(&urb->urb_list)) {
++              PDEBUG(1, "urb = %p, status = %d is in a list, why?", urb, urb->status);
++              //list_del_init(&urb->urb_list);
++              //call = 1;
++      }
++
++out:
++      spin_unlock(&urb->lock);
++      spin_unlock_irqrestore(&hc->hc_lock, flags);
++      
++      if (call && urb->complete)
++              urb->complete(urb);
++      
++      return 0;
++      
++result:
++      spin_unlock(&urb->lock);
++      
++      list_del_init(&urb->urb_list);
++      sl811_result_urb(urb);  
++      
++      spin_unlock_irqrestore(&hc->hc_lock, flags);
++      
++      return 0;
++}
++
++#else
++
++/*
++ * Unlink the urb from the urb list
++ */
++static int sl811_unlink_urb(struct urb *urb)
++{
++      unsigned long flags;
++      struct sl811_hc *hc;
++      struct sl811_urb_priv *urbp;
++      int call = 0;
++      
++      if (!urb) {
++              PDEBUG(1, "urb is null");
++              return -EINVAL;
++      }
++      
++      if (!urb->dev || !urb->dev->bus) {
++              PDEBUG(1, "dev or bus is null");
++              return -ENODEV;
++      }
++      
++      hc = urb->dev->bus->hcpriv; 
++      urbp = urb->hcpriv;
++      
++      /* a request to the virtual root hub */
++      if (usb_pipedevice(urb->pipe) == hc->rh.devnum)
++              return sl811_rh_unlink_urb(urb); 
++      
++      spin_lock_irqsave(&hc->hc_lock, flags);
++      spin_lock(&urb->lock);
++
++      // in wait list
++      if (sl811_find_same_urb(&hc->wait_list, urb)) { 
++              PDEBUG(2, "unlink urb in wait list");
++              list_del_init(&urb->urb_list);
++              urb->status = -ENOENT;
++              call = 1;
++              goto out;
++      }
++      
++      if (urb->status == -EINPROGRESS) {  
++              PDEBUG(2, "urb is still in progress");
++              urbp->unlink = 1;
++
++              // Is it in progress?
++              urbp = urb->hcpriv;
++              if (urbp && hc->cur_td == urbp->cur_td) {
++                      // simple, let it out
++                      PDEBUG(2, "unlink: cur td is still in progress!");
++                      hc->cur_td = NULL;
++              }
++              
++              goto result;
++      } else if (!list_empty(&urb->urb_list)) {
++              PDEBUG(1, "urb = %p, status = %d is in a list, why?", urb, urb->status);
++              list_del_init(&urb->urb_list);
++              if (urbp)
++                      goto result;
++              else
++                      call = 1;
++      }
++
++out:
++      spin_unlock(&urb->lock);
++      spin_unlock_irqrestore(&hc->hc_lock, flags);
++      
++      if (call && urb->complete)
++              urb->complete(urb);
++                      
++      return 0;
++      
++result:
++      spin_unlock(&urb->lock);
++      
++      list_del_init(&urb->urb_list);
++      sl811_result_urb(urb);  
++      
++      spin_unlock_irqrestore(&hc->hc_lock, flags);
++      
++      return 0;
++}
++
++#endif
++
++static int sl811_get_current_frame_number(struct usb_device *usb_dev)
++{
++      return ((struct sl811_hc *)(usb_dev->bus->hcpriv))->frame_number;
++}
++
++static struct usb_operations sl811_device_operations = 
++{
++      sl811_alloc_dev_priv,
++      sl811_free_dev_priv,
++      sl811_get_current_frame_number,
++      sl811_submit_urb,
++      sl811_unlink_urb
++};
++
++/*
++ * This       functions transmit a td.
++ */
++static inline void sl811_trans_cur_td(struct sl811_hc *hc, struct sl811_td *td)
++{
++      sl811_print_td(4, td);
++      sl811_write_buf(hc, SL811_ADDR_A,  &td->addr, 4);
++      if (td->len && (td->ctrl & SL811_USB_CTRL_DIR_OUT))
++              sl811_write_buf(hc, td->addr,  td->buf, td->len);
++
++      sl811_write(hc, SL811_CTRL_A, td->ctrl);
++}
++
++              
++/*
++ * This       function checks the status of the transmitted or received packet
++ * and copy the       data from the SL811HS register into a buffer.
++ */
++static void sl811_parse_cur_td(struct sl811_hc *hc, struct sl811_td *td)
++{
++      struct urb *urb = td->urb;
++#ifdef SL811_DEBUG
++      int dev = usb_pipedevice(td->urb->pipe);
++      int ep = usb_pipeendpoint(td->urb->pipe);
++#endif
++
++      sl811_read_buf(hc, SL811_STS_A, &td->status, 2);
++      
++      if (td->status & SL811_USB_STS_ACK) {
++              td->done = 1;
++              
++/*            if ((td->ctrl & SL811_USB_CTRL_TOGGLE_1) != (td->status & SL811_USB_STS_TOGGLE_1)) {
++                      PDEBUG(2, "dev %d endpoint %d unexpect data toggle!", dev, ep);
++                      td->td_status = -EILSEQ;
++              }
++*/            
++              if (!(td->ctrl & SL811_USB_CTRL_DIR_OUT) && td->len > 0)
++                      sl811_read_buf(hc, td->addr, td->buf, td->len - td->left);
++                      
++              if (td->left && (urb->transfer_flags & USB_DISABLE_SPD)) {
++                      PDEBUG(2, "dev %d endpoint %d unexpect short packet! td = %p", dev, ep, td);
++                      td->td_status = -EREMOTEIO;
++              } else
++                      td->td_status = 0;
++      } else if (td->status & SL811_USB_STS_STALL) {
++              PDEBUG(2, "dev %d endpoint %d halt, td = %p", dev, ep, td);
++              td->td_status = -EPIPE;
++              if (urb->dev)
++                      usb_endpoint_halt(td->urb->dev, usb_pipeendpoint(td->urb->pipe), usb_pipeout(td->urb->pipe));
++              td->done = 1;
++      } else if (td->status & SL811_USB_STS_OVERFLOW) {
++              PDEBUG(1, "dev %d endpoint %d overflow, sl811 only support packet less than %d", dev, ep, SL811_DATA_LIMIT);    
++              td->td_status = -EOVERFLOW;
++              td->done = 1;
++      } else if (td->status & SL811_USB_STS_TIMEOUT ) {
++              PDEBUG(2, "dev %d endpoint %d timeout, td = %p", dev, ep, td);  
++              td->td_status = -ETIMEDOUT;
++              if (--td->errcnt == 0)
++                      td->done = 1;
++      } else if (td->status & SL811_USB_STS_ERROR) {
++              PDEBUG(2, "dev %d endpoint %d error, td = %p", dev, ep, td);
++              td->td_status = -EILSEQ;
++              if (--td->errcnt == 0)
++                      td->done = 1;
++      } else if (td->status & SL811_USB_STS_NAK) {
++              ++td->nakcnt;
++              PDEBUG(3, "dev %d endpoint %d nak, td = %p, count = %d", dev, ep, td, td->nakcnt);
++              td->td_status = -EINPROGRESS;
++              if (!usb_pipeslow(td->urb->pipe) && td->nakcnt > 1024) {
++                      PDEBUG(2, "too many naks, td = %p, count = %d", td, td->nakcnt);
++                      td->td_status = -ETIMEDOUT;
++                      td->done = 1;
++              } 
++      } 
++      
++      sl811_print_td(4, td);
++}
++
++/*
++ * This       function checks the status of current urb.
++ */
++static int sl811_parse_cur_urb(struct urb *urb)
++{
++      struct sl811_urb_priv *urbp = urb->hcpriv;
++      struct sl811_td *td = urbp->cur_td;
++      struct list_head *tmp;
++      
++      sl811_print_td(5, td);
++      
++      // this td not done yet.
++      if (!td->done)
++              return 0;
++      
++      // the last ld, so the urb is done.
++      if (td == urbp->last_td) {
++              PDEBUG(4, "urb = %p is done success", td->urb);
++              if (usb_pipeisoc(td->urb->pipe))
++                      PDEBUG(4, "ISO URB DONE, td = %p", td);
++              return 1;
++      }
++      
++      // iso transfer, we always advance to next td 
++      if (usb_pipeisoc(td->urb->pipe)) {
++              tmp = &td->td_list;
++              tmp = tmp->next;
++              urbp->cur_td = list_entry(tmp, struct sl811_td, td_list);
++              PDEBUG(4, "ISO NEXT, td = %p", urbp->cur_td);   
++              return 0;
++      }
++              
++      // some error occur, so the urb is done.
++      if (td->td_status) {
++              PDEBUG(3, "urb = %p is done error, td status is = %d", td->urb, td->td_status);
++              return 1;
++      }
++              
++      // short packet.
++      if (td->left) {
++              if (usb_pipecontrol(td->urb->pipe)) {
++                      // control packet, we advance to the last td
++                      PDEBUG(3, "ctrl short packet, advance to last td");
++                      urbp->cur_td = urbp->last_td;
++                      return 0;
++              } else {
++                      // interrut and bulk packet, urb is over.
++                      PDEBUG(3, "bulk or intr short packet, urb is over");
++                      return 1;
++              }
++      }
++
++      // we advance to next td.       
++      tmp = &td->td_list;
++      tmp = tmp->next;
++      urbp->cur_td = list_entry(tmp, struct sl811_td, td_list);
++#ifdef SL811_DEBUG
++      PDEBUG(4, "advance to the next td, urb = %p, td = %p", urb, urbp->cur_td);
++      sl811_print_td(5, urbp->cur_td);
++      if (td == urbp->cur_td)
++              PDEBUG(1, "bug!!!");
++#endif                
++      return 0;
++}
++
++/*
++ * Find the next td to transfer.
++ */
++static inline struct sl811_td* sl811_schedule_next_td(struct urb *urb, struct sl811_td *cur_td)
++{
++      struct sl811_urb_priv *urbp = urb->hcpriv;
++      
++      PDEBUG(4, "urb at %p, cur td at %p", urb, cur_td);
++      
++      // iso don't schedule the td in the same frame.
++      if (usb_pipeisoc(cur_td->urb->pipe))
++              return NULL;
++      
++      // cur td is not complete
++      if (!cur_td->done)
++              return NULL;    
++      
++      // here, urbp->cur_td is already the next td;
++      return urbp->cur_td;
++}
++
++/*
++ * Scan the list to find a active urb
++ */
++static inline struct urb* sl811_get_list_next_urb(struct sl811_hc *hc, struct list_head *next)
++{
++      struct urb *urb;
++      int i;
++      
++      if (list_empty(next))
++              return NULL;
++      
++      if (next == hc->cur_list)
++              return NULL;
++                      
++      for (i = 0; i < 4; ++i) 
++              if (next == &hc->urb_list[i])
++                      return NULL;
++                      
++      urb = list_entry(next, struct urb, urb_list);
++      PDEBUG(4, "next urb in list is at %p", urb);
++              
++      return urb;
++}
++
++/*
++ * Find the next td to transfer.
++ */
++static struct sl811_td* sl811_schedule_next_urb(struct sl811_hc *hc, struct list_head *next)
++{
++      struct urb *urb = NULL;
++      int back_loop = 1;
++      struct list_head *old_list = hc->cur_list;
++              
++      // try to get next urb in the same list.
++      if (next) {
++              urb = sl811_get_list_next_urb(hc, next);
++              if (!urb)
++                      ++hc->cur_list;
++      }
++
++      // try other list.
++      if (!urb) {                     
++re_loop:
++              // try all the list.
++              while (hc->cur_list < &hc->urb_list[4]) { 
++                      if ((urb = sl811_get_list_next_urb(hc, hc->cur_list->next)))
++                              return ((struct sl811_urb_priv *)urb->hcpriv)->cur_td;
++                      ++hc->cur_list;
++              }
++              // the last list is try 
++              if (back_loop && (old_list >= &hc->ctrl_list)) {
++                      hc->cur_list = &hc->ctrl_list;
++                      back_loop = 0;
++                      goto re_loop;
++              }
++      }
++      
++      if (hc->cur_list > &hc->urb_list[3])
++              hc->cur_list = &hc->ctrl_list;
++                      
++      return NULL;
++}
++
++/*
++ * This function process the transfer rusult.
++ */
++static void sl811_transfer_done(struct sl811_hc *hc, int sof) 
++{
++      struct sl811_td *cur_td = hc->cur_td, *next_td = NULL;
++      struct urb *cur_urb = NULL;
++              struct list_head *next = NULL;
++              int done;
++      
++      PDEBUG(5, "enter");
++      
++      if (cur_td == NULL) {
++              PDEBUG(1, "in done interrupt, but td is null, be already parsed?");
++              return ;
++      }
++
++      cur_urb = cur_td->urb;
++      hc->cur_td = NULL;
++      next = &cur_urb->urb_list;
++      next = next->next;
++      
++      spin_lock(&cur_urb->lock);      
++      sl811_parse_cur_td(hc, cur_td);
++      done = sl811_parse_cur_urb(cur_urb);
++      spin_unlock(&cur_urb->lock);
++      
++      if (done) {
++              list_del_init(&cur_urb->urb_list);
++              cur_td = NULL;
++              sl811_result_urb(cur_urb);      
++      }
++
++      if (sof)
++              return ;
++      
++      if (!done) {
++              next_td = sl811_schedule_next_td(cur_urb, cur_td);
++              if (next_td && next_td != cur_td && (sl811_calc_bus_remainder(hc) > next_td->bustime)) {
++                      hc->cur_td = next_td;
++                      PDEBUG(5, "ADD TD");
++                      sl811_trans_cur_td(hc, next_td);
++                      return ;
++              }
++      }
++      
++      while (1) {
++              next_td = sl811_schedule_next_urb(hc, next);
++              if (!next_td)
++                      return;
++              if (next_td == cur_td)
++                      return;
++              next = &next_td->urb->urb_list;
++              next = next->next;
++              if (sl811_calc_bus_remainder(hc) > next_td->bustime) {
++                      hc->cur_td = next_td;
++                      PDEBUG(5, "ADD TD");
++                      sl811_trans_cur_td(hc, next_td);
++                      return ;
++              }
++      }
++}
++
++/*
++ *
++ */
++static void inline sl811_dec_intr_interval(struct sl811_hc *hc)
++{
++      struct list_head *head, *tmp;
++      struct urb *urb;
++      struct sl811_urb_priv *urbp;
++      
++      if (list_empty(&hc->idle_intr_list))
++              return ;
++      
++      head = &hc->idle_intr_list;
++      tmp = head->next;
++      
++      while (tmp != head) {
++              urb = list_entry(tmp, struct urb, urb_list);
++              tmp = tmp->next;
++              spin_lock(&urb->lock);
++              urbp = urb->hcpriv;
++              if (--urbp->interval == 0) {
++                      list_del(&urb->urb_list);
++                      list_add(&urb->urb_list, &hc->intr_list);
++                      PDEBUG(4, "intr urb active");
++              }
++              spin_unlock(&urb->lock);
++      }
++}
++
++/*
++ * The sof interrupt is happen.       
++ */
++static void sl811_start_sof(struct sl811_hc *hc)
++{
++      struct sl811_td *next_td;
++#ifdef SL811_DEBUG
++      static struct sl811_td *repeat_td = NULL;
++      static int repeat_cnt = 1;
++#endif        
++      if (++hc->frame_number > 1024)
++              hc->frame_number = 0;
++      
++      if (hc->active_urbs == 0)
++              return ;
++      
++      sl811_dec_intr_interval(hc);
++      
++      if (hc->cur_td) {
++              if (sl811_read(hc, 0) & SL811_USB_CTRL_ARM) {
++#ifdef SL811_DEBUG
++                      if (repeat_td == hc->cur_td) 
++                              ++repeat_cnt;
++                      else {
++                              if (repeat_cnt >= 2)
++                                      PDEBUG(2, "cur td = %p repeat %d", hc->cur_td, repeat_cnt);
++                              repeat_cnt = 1;
++                              repeat_td = hc->cur_td;
++                      }
++#endif
++                      return ;
++              } else {
++                      PDEBUG(2, "lost of interrupt in sof? do parse!");
++                      sl811_transfer_done(hc, 1);
++                      
++                      // let this frame idle  
++                      return;
++              }
++      }
++      
++      hc->cur_list = &hc->iso_list;
++      
++      if (hc->active_urbs == 0)
++              return ;
++      
++      next_td = sl811_schedule_next_urb(hc, NULL);
++      if (!next_td) {
++#ifdef SL811_DEBUG
++              if (list_empty(&hc->idle_intr_list))
++                      PDEBUG(2, "not schedule a td, why? urbs = %d", hc->active_urbs);
++#endif
++              return; 
++      }
++      if (sl811_calc_bus_remainder(hc) > next_td->bustime) {
++              hc->cur_td = next_td;
++              sl811_trans_cur_td(hc, next_td);
++      } else
++              PDEBUG(2, "bus time if not enough, why?");
++}
++
++/*
++ * This       function resets SL811HS controller and detects the speed of
++ * the connecting device
++ *
++ * Return: 0 = no device attached; 1 = USB device attached
++ */
++static int sl811_hc_reset(struct sl811_hc *hc)
++{
++      int status ;
++
++      sl811_write(hc, SL811_CTRL2, SL811_CTL2_HOST | SL811_12M_HI);
++      sl811_write(hc, SL811_CTRL1, SL811_CTRL1_RESET);
++
++      mdelay(20);
++      
++      // Disable hardware SOF generation, clear all irq status.
++      sl811_write(hc, SL811_CTRL1, 0);
++      mdelay(2);
++      sl811_write(hc, SL811_INTRSTS, 0xff); 
++      status = sl811_read(hc, SL811_INTRSTS);
++
++      if (status & SL811_INTR_NOTPRESENT) {
++              // Device is not present
++              PDEBUG(0, "Device not present");
++              hc->rh_status.wPortStatus &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE);
++              hc->rh_status.wPortChange |= USB_PORT_STAT_C_CONNECTION;
++              sl811_write(hc, SL811_INTR, SL811_INTR_INSRMV);
++              return 0;
++      }
++
++      // Send SOF to address 0, endpoint 0.
++      sl811_write(hc, SL811_LEN_B, 0);
++      sl811_write(hc, SL811_PIDEP_B, PIDEP(USB_PID_SOF, 0));
++      sl811_write(hc, SL811_DEV_B, 0x00);
++      sl811_write (hc, SL811_SOFLOW, SL811_12M_HI);
++
++      if (status & SL811_INTR_SPEED_FULL) {
++              /* full speed device connect directly to root hub */
++              PDEBUG (0, "Full speed Device attached");
++              
++              sl811_write(hc, SL811_CTRL1, SL811_CTRL1_RESET);
++              mdelay(20);
++              sl811_write(hc, SL811_CTRL2, SL811_CTL2_HOST | SL811_12M_HI);
++              sl811_write(hc, SL811_CTRL1, SL811_CTRL1_SOF);
++
++              /* start the SOF or EOP */
++              sl811_write(hc, SL811_CTRL_B, SL811_USB_CTRL_ARM);
++              hc->rh_status.wPortStatus |= USB_PORT_STAT_CONNECTION;
++              hc->rh_status.wPortStatus &= ~USB_PORT_STAT_LOW_SPEED;
++              mdelay(2);
++              sl811_write (hc, SL811_INTRSTS, 0xff);
++      } else {
++              /* slow speed device connect directly to root-hub */
++              PDEBUG(0, "Low speed Device attached");
++              
++              sl811_write(hc, SL811_CTRL1, SL811_CTRL1_RESET);
++              mdelay(20);
++              sl811_write(hc, SL811_CTRL2, SL811_CTL2_HOST | SL811_CTL2_DSWAP | SL811_12M_HI);
++              sl811_write(hc, SL811_CTRL1, SL811_CTRL1_SPEED_LOW | SL811_CTRL1_SOF);
++
++              /* start the SOF or EOP */
++              sl811_write(hc, SL811_CTRL_B, SL811_USB_CTRL_ARM);
++              hc->rh_status.wPortStatus |= USB_PORT_STAT_CONNECTION | USB_PORT_STAT_LOW_SPEED;
++              mdelay(2);
++              sl811_write(hc, SL811_INTRSTS, 0xff);
++      }
++
++      hc->rh_status.wPortChange |= USB_PORT_STAT_C_CONNECTION;
++      sl811_write(hc, SL811_INTR, SL811_INTR_INSRMV);
++      
++      return 1;
++}
++
++/*
++ * Interrupt service routine.
++ */
++static void sl811_interrupt(int irq, void *__hc, struct pt_regs * r)
++{
++      __u8 status;
++      struct sl811_hc *hc = __hc;
++
++      status = sl811_read(hc, SL811_INTRSTS);
++      if (status == 0)
++              return ; /* Not me */
++
++      sl811_write(hc, SL811_INTRSTS, 0xff);
++
++      if (status & SL811_INTR_INSRMV) {
++              sl811_write(hc, SL811_INTR, 0);
++              sl811_write(hc, SL811_CTRL1, 0);
++              // wait for device stable
++              mdelay(100);                    
++              sl811_hc_reset(hc);
++              return ;
++      }
++
++      spin_lock(&hc->hc_lock);
++      
++      if (status & SL811_INTR_DONE_A) {
++              if (status & SL811_INTR_SOF) {
++                      sl811_transfer_done(hc, 1);
++                      PDEBUG(4, "sof in done!");
++                      sl811_start_sof(hc);
++              } else
++                      sl811_transfer_done(hc, 0);
++      } else if (status & SL811_INTR_SOF)
++              sl811_start_sof(hc);    
++
++      spin_unlock(&hc->hc_lock);      
++
++      return ;
++}
++
++/*
++ * This       function allocates all data structure and store in the
++ * private data       structure.
++ *
++ * Return value        : data structure for the host controller
++ */
++static struct sl811_hc* __devinit sl811_alloc_hc(void)
++{
++      struct sl811_hc *hc;
++      struct usb_bus *bus;
++      int i;
++
++      PDEBUG(4, "enter");
++
++      hc = (struct sl811_hc *)kmalloc(sizeof(struct sl811_hc), GFP_KERNEL);
++      if (!hc)
++              return NULL;
++
++      memset(hc, 0, sizeof(struct sl811_hc));
++
++      hc->rh_status.wPortStatus = USB_PORT_STAT_POWER;
++      hc->rh_status.wPortChange = 0;
++
++      hc->active_urbs = 0;
++      INIT_LIST_HEAD(&hc->hc_hcd_list);
++      list_add(&hc->hc_hcd_list, &sl811_hcd_list);
++      
++      init_waitqueue_head(&hc->waitq);
++      
++      for (i = 0; i < 6; ++i)
++              INIT_LIST_HEAD(&hc->urb_list[i]);
++      
++      hc->cur_list = &hc->iso_list;
++
++      bus = usb_alloc_bus(&sl811_device_operations);
++      if (!bus) {
++              kfree (hc);
++              return NULL;
++      }
++
++      hc->bus = bus;
++      bus->bus_name = MODNAME;
++      bus->hcpriv = hc;
++
++      return hc;
++}
++
++/*
++ * This       function De-allocate all resources
++ */
++static void sl811_release_hc(struct sl811_hc *hc)
++{
++      PDEBUG(4, "enter");
++
++      /* disconnect all devices */
++      if (hc->bus->root_hub)
++              usb_disconnect(&hc->bus->root_hub);
++
++      // Stop interrupt handle
++      if (hc->irq)
++              free_irq(hc->irq, hc);
++      hc->irq = 0;
++
++      /* Stop interrupt for sharing */
++      if (hc->addr_io) {
++              /* Disable Interrupts */
++              sl811_write(hc, SL811_INTR, 0);
++
++              /* Remove all Interrupt events */
++              mdelay(2);
++              sl811_write(hc, SL811_INTRSTS, 0xff);
++      }
++
++      /* free io regions */
++      sl811_release_regions(hc);
++
++      usb_deregister_bus(hc->bus);
++      usb_free_bus(hc->bus);
++
++      list_del(&hc->hc_hcd_list);
++      INIT_LIST_HEAD(&hc->hc_hcd_list);
++
++      kfree (hc);
++}
++
++/*
++ * This       function request IO memory regions, request IRQ, and
++ * allocate all       other resources.
++ *
++ * Input: addr_io = first IO address
++ *      data_io = second IO address
++ *      irq = interrupt number
++ *
++ * Return: 0 = success or error       condition
++ */
++static int __devinit sl811_found_hc(int addr_io, int data_io, int irq)
++{
++      struct sl811_hc *hc;
++
++      PDEBUG(4, "enter");
++
++      hc = sl811_alloc_hc();
++      if (!hc)
++              return -ENOMEM;
++
++      if (sl811_request_regions (hc, addr_io, data_io, MODNAME)) {
++              PDEBUG(1, "ioport %X,%X is in use!", addr_io, data_io);
++              sl811_release_hc(hc);
++              return -EBUSY;
++      }
++
++      if (sl811_reg_test(hc)) {
++              PDEBUG(1, "SL811 register test failed!");
++              sl811_release_hc(hc);
++              return -ENODEV;
++      }
++      
++//#ifdef SL811_DEBUG_VERBOSE
++      {
++          __u8 u = sl811_read(hc, SL811_HWREV);
++          
++          // Show the hardware revision of chip
++          PDEBUG(1, "SL811 HW: %02Xh", u);
++          switch (u & 0xF0) {
++          case 0x00: PDEBUG(1, "SL11H");              break;
++          case 0x10: PDEBUG(1, "SL811HS rev1.2");     break;
++          case 0x20: PDEBUG(1, "SL811HS rev1.5");     break;
++          default:   PDEBUG(1, "Revision unknown!");
++          }
++      }
++//#endif // SL811_DEBUG_VERBOSE
++
++      sl811_init_irq();
++
++      usb_register_bus(hc->bus);
++
++      if (request_irq(irq, sl811_interrupt, SA_SHIRQ, MODNAME, hc)) {
++              PDEBUG(1, "request interrupt %d failed", irq);
++              sl811_release_hc(hc);
++              return -EBUSY;
++      }
++      hc->irq = irq;
++
++      printk(KERN_INFO __FILE__ ": USB SL811 at %08x,%08x, IRQ %d\n",
++              hc->addr_io, hc->data_io, irq);
++
++      sl811_hc_reset(hc);
++      sl811_connect_rh(hc);
++      
++      return 0;
++}
++
++/*
++ * This       is an init function, and it is the first function being called
++ *
++ * Return: 0 = success or error       condition
++ */
++static int __init sl811_hcd_init(void)
++{
++      int ret = -ENODEV;
++      
++      PDEBUG(4, "enter");
++
++      info(DRIVER_VERSION " : " DRIVER_DESC);
++
++#ifdef CONFIG_X86
++      {
++              int count;
++              // registering some instance
++              for (count = 0; count < MAX_CONTROLERS; count++) {
++                      if (io[count]) {
++                              ret = sl811_found_hc(io[count], io[count]+OFFSET_DATA_REG, irq[count]);
++                              if (ret)
++                                      return (ret);
++                      }
++              }
++      }
++#endif
++#ifdef CONFIG_ARCH_RAMSES
++      ret = sl811_found_hc(0,0,SL811HS_IRQ);
++#endif
++
++      return ret;
++}
++
++/*
++ * This       is a cleanup function, and it is called when module is unloaded.
++ */
++static void __exit sl811_hcd_cleanup(void)
++{
++      struct list_head *list = sl811_hcd_list.next;
++      struct sl811_hc *hc;
++
++      PDEBUG(4, "enter");
++
++      for (; list != &sl811_hcd_list; ) {
++              hc = list_entry(list, struct sl811_hc, hc_hcd_list);
++              list = list->next;
++              sl811_release_hc(hc);
++      }
++}
++
++module_init(sl811_hcd_init);
++module_exit(sl811_hcd_cleanup);
++
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_DESCRIPTION(DRIVER_DESC);
+--- /dev/null
++++ linux-2.4.21/drivers/usb/host/sl811.h
+@@ -0,0 +1,177 @@
++#ifndef __LINUX_SL811_H
++#define __LINUX_SL811_H
++
++#define SL811_DEBUG
++
++#ifdef SL811_DEBUG
++      #define PDEBUG(level, fmt, args...) \
++              if (debug >= (level)) info("[%s:%d] " fmt, \
++              __PRETTY_FUNCTION__, __LINE__ , ## args)
++#else
++      #define PDEBUG(level, fmt, args...) do {} while(0)
++#endif
++
++//#define SL811_TIMEOUT
++              
++/* Sl811 host control register */
++#define       SL811_CTRL_A            0x00
++#define       SL811_ADDR_A            0x01
++#define       SL811_LEN_A             0x02
++#define       SL811_STS_A             0x03    /* read */
++#define       SL811_PIDEP_A           0x03    /* write */
++#define       SL811_CNT_A             0x04    /* read */
++#define       SL811_DEV_A             0x04    /* write */
++#define       SL811_CTRL1             0x05
++#define       SL811_INTR              0x06
++#define       SL811_CTRL_B            0x08
++#define       SL811_ADDR_B            0x09
++#define       SL811_LEN_B             0x0A
++#define       SL811_STS_B             0x0B    /* read */
++#define       SL811_PIDEP_B           0x0B    /* write */
++#define       SL811_CNT_B             0x0C    /* read */
++#define       SL811_DEV_B             0x0C    /* write */
++#define       SL811_INTRSTS           0x0D    /* write clears bitwise */
++#define       SL811_HWREV             0x0E    /* read */
++#define       SL811_SOFLOW            0x0E    /* write */
++#define       SL811_SOFCNTDIV         0x0F    /* read */
++#define       SL811_CTRL2             0x0F    /* write */
++
++/* USB control register bits (addr 0x00 and addr 0x08) */
++#define       SL811_USB_CTRL_ARM      0x01
++#define       SL811_USB_CTRL_ENABLE   0x02
++#define       SL811_USB_CTRL_DIR_OUT  0x04
++#define       SL811_USB_CTRL_ISO      0x10
++#define       SL811_USB_CTRL_SOF      0x20
++#define       SL811_USB_CTRL_TOGGLE_1 0x40
++#define       SL811_USB_CTRL_PREAMBLE 0x80
++
++/* USB status register bits (addr 0x03 and addr 0x0B) */
++#define       SL811_USB_STS_ACK       0x01
++#define       SL811_USB_STS_ERROR     0x02
++#define       SL811_USB_STS_TIMEOUT   0x04
++#define       SL811_USB_STS_TOGGLE_1  0x08
++#define       SL811_USB_STS_SETUP     0x10
++#define       SL811_USB_STS_OVERFLOW  0x20
++#define       SL811_USB_STS_NAK       0x40
++#define       SL811_USB_STS_STALL     0x80
++
++/* Control register 1 bits (addr 0x05) */
++#define       SL811_CTRL1_SOF         0x01
++#define       SL811_CTRL1_RESET       0x08
++#define       SL811_CTRL1_JKSTATE     0x10
++#define       SL811_CTRL1_SPEED_LOW   0x20
++#define       SL811_CTRL1_SUSPEND     0x40
++
++/* Interrut enable (addr 0x06) and interrupt status register bits (addr 0x0D) */
++#define       SL811_INTR_DONE_A       0x01
++#define       SL811_INTR_DONE_B       0x02
++#define       SL811_INTR_SOF          0x10
++#define       SL811_INTR_INSRMV       0x20
++#define       SL811_INTR_DETECT       0x40
++#define       SL811_INTR_NOTPRESENT   0x40
++#define       SL811_INTR_SPEED_FULL   0x80    /* only in status reg */
++
++/* HW rev and SOF lo register bits (addr 0x0E) */
++#define       SL811_HWR_HWREV         0xF0
++
++/* SOF counter and control reg 2 (addr 0x0F) */
++#define       SL811_CTL2_SOFHI        0x3F
++#define       SL811_CTL2_DSWAP        0x40
++#define       SL811_CTL2_HOST         0x80
++
++/* Set up for 1-ms SOF time. */
++#define SL811_12M_LOW         0xE0
++#define SL811_12M_HI          0x2E
++
++#define SL811_DATA_START      0x10
++#define SL811_DATA_LIMIT      240
++
++
++/* Requests: bRequest << 8 | bmRequestType */
++#define RH_GET_STATUS           0x0080
++#define RH_CLEAR_FEATURE        0x0100
++#define RH_SET_FEATURE          0x0300
++#define RH_SET_ADDRESS                0x0500
++#define RH_GET_DESCRIPTOR     0x0680
++#define RH_SET_DESCRIPTOR       0x0700
++#define RH_GET_CONFIGURATION  0x0880
++#define RH_SET_CONFIGURATION  0x0900
++#define RH_GET_STATE            0x0280
++#define RH_GET_INTERFACE        0x0A80
++#define RH_SET_INTERFACE        0x0B00
++#define RH_SYNC_FRAME           0x0C80
++
++
++#define PIDEP(pid, ep) (((pid) & 0x0f) << 4 | (ep))
++
++/* Virtual Root HUB */
++struct virt_root_hub {
++      int devnum;                     /* Address of Root Hub endpoint */ 
++      void *urb;                      /* interrupt URB of root hub */
++      int send;                       /* active flag */
++      int interval;                   /* intervall of roothub interrupt transfers */
++      struct timer_list rh_int_timer; /* intervall timer for rh interrupt EP */
++};
++
++struct sl811_td {
++      /* hardware */
++      __u8 ctrl;                      /* control register */
++      
++      /* write */                     
++      __u8 addr;                      /* base adrress register */
++      __u8 len;                       /* base length register */
++      __u8 pidep;                     /* PId and endpoint register */
++      __u8 dev;                       /* device address register */
++      
++      /* read */
++      __u8 status;                    /* status register */
++      __u8 left;                      /* transfer count register */
++      
++      /* software */
++      __u8 errcnt;                    /* error count, begin with 3 */
++      __u8 done;                      /* is this td tranfer done */
++      __u8 *buf;                      /* point to data buffer for tranfer */
++      int bustime;                    /* the bus time need by this td */
++      int td_status;                  /* the status of this td */
++      int nakcnt;                     /* number of naks */
++      struct urb *urb;                        /* the urb this td belongs to */
++      struct list_head td_list;       /* link to a list of the urb */
++};
++
++struct sl811_urb_priv {
++      struct urb *urb;                        /* the urb this priv beloings to */
++      struct list_head td_list;       /* list of all the td of this urb */
++      struct sl811_td *cur_td;                /* current td is in processing or it will be */
++      struct sl811_td *first_td;              /* the first td of this urb */
++      struct sl811_td *last_td;               /* the last td of this urb */
++      int interval;                   /* the query time value for intr urb */
++      int unlink;                     /* is the this urb unlinked */
++      unsigned long inserttime;       /* the time when insert to list */
++};
++
++struct sl811_hc {
++      spinlock_t hc_lock;             /* Lock for this structure */
++      
++      int irq;                        /* IRQ number this hc use */
++      int addr_io;                    /* I/O address line address */
++      int data_io;                    /* I/O data line address */
++      struct virt_root_hub rh;                /* root hub */
++      struct usb_port_status rh_status;/* root hub port status */
++      struct list_head urb_list[6];   /* set of urbs, the order is iso,intr,ctrl,bulk,inactive intr, wait */
++      struct list_head *cur_list;     /* the current list is in process */
++      wait_queue_head_t waitq;        /* deletion of URBs and devices needs a waitqueue */
++      struct sl811_td *cur_td;                /* point to the td is in process */
++      struct list_head hc_hcd_list;   /* list of all hci_hcd */
++      struct usb_bus *bus;            /* our bus */
++      int active_urbs;                /* total number of active usbs */
++      int frame_number;               /* the current frame number, we do't use it, any one need it? */
++};
++
++#define iso_list      urb_list[0]     /* set of isoc urbs */
++#define intr_list     urb_list[1]     /* ordered (tree) set of int urbs */
++#define ctrl_list     urb_list[2]     /* set of ctrl urbs */
++#define bulk_list     urb_list[3]     /* set of bulk urbs */
++#define idle_intr_list        urb_list[4]     /* set of intr urbs in its idle time*/
++#define wait_list     urb_list[5]     /* set of wait urbs */
++
++#endif
+--- linux-2.4.21/drivers/usb/storage/transport.h~usb-sonycamera
++++ linux-2.4.21/drivers/usb/storage/transport.h
+@@ -75,6 +75,8 @@
+ #define US_PR_JUMPSHOT  0xf3            /* Lexar Jumpshot */
+ #endif
++#define US_PR_DEVICE    0xff          /* Use device's value */
++
+ /*
+  * Bulk only data structures
+  */
+--- linux-2.4.21/drivers/usb/storage/unusual_devs.h~usb-sonycamera
++++ linux-2.4.21/drivers/usb/storage/unusual_devs.h
+@@ -223,10 +223,10 @@
+               US_FL_FIX_INQUIRY | US_FL_START_STOP ),
+ /* This entry is needed because the device reports Sub=ff */
+-UNUSUAL_DEV(  0x054c, 0x0010, 0x0106, 0x0440, 
++UNUSUAL_DEV(  0x054c, 0x0010, 0x0106, 0x0450, 
+               "Sony",
+-              "DSC-S30/S70/S75/505V/F505/F707/F717", 
+-              US_SC_SCSI, US_PR_CB, NULL,
++              "DSC-S30/S70/S75/505V/F505/F707/F717/P8",
++              US_SC_SCSI, US_PR_DEVICE, NULL,
+               US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE ),
+ /* Reported by wim@geeks.nl */
+--- linux-2.4.21/drivers/usb/storage/usb.c~usb-sonycamera
++++ linux-2.4.21/drivers/usb/storage/usb.c
+@@ -622,7 +622,9 @@
+       /* Determine subclass and protocol, or copy from the interface */
+       subclass = unusual_dev->useProtocol;
+-      protocol = unusual_dev->useTransport;
++      protocol = (unusual_dev->useTransport == US_PR_DEVICE) ?
++                      altsetting->bInterfaceProtocol :
++                      unusual_dev->useTransport;
+       flags = unusual_dev->flags;
+       /*
+--- linux-2.4.21/drivers/video/fbcon-cfb16.c~fb-turn180
++++ linux-2.4.21/drivers/video/fbcon-cfb16.c
+@@ -34,6 +34,41 @@
+ #endif
+ };
++static u8 mirrortab_cfb16[] = {
++   0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,
++   0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
++   0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,
++   0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
++   0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,
++   0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
++   0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,
++   0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
++   0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,
++   0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
++   0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,
++   0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
++   0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,
++   0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
++   0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,
++   0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
++   0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,
++   0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
++   0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,
++   0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
++   0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,
++   0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
++   0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,
++   0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
++   0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,
++   0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
++   0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,
++   0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
++   0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,
++   0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
++   0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,
++   0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
++};
++
+ void fbcon_cfb16_setup(struct display *p)
+ {
+     p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<1;
+@@ -46,6 +81,53 @@
+     int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
+     u8 *src, *dst;
++    if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++    char    *scrn_end =   p->screen_base + p->var.xres*p->var.yres * 2;
++/*
++    printk("---@paul@-------------------------\n"\
++       "fbcon_cfb16_bmove() %d %d %d %d %d %d\n",
++       sx,sy,dx,dy,height,width
++      );
++*/
++    if (sx == 0 && dx == 0 && width * fontwidth(p) * 2 == bytes)
++    {
++        fb_memmove(
++            scrn_end - dy * linesize,
++            scrn_end - sy * linesize,
++            height * linesize
++        );
++      return;
++    }
++    if (fontwidthlog(p)) {
++      sx <<= fontwidthlog(p)+1;
++          dx <<= fontwidthlog(p)+1;
++      width <<= fontwidthlog(p)+1;
++    } else {
++      sx *= fontwidth(p)*2;
++      dx *= fontwidth(p)*2;
++      width *= fontwidth(p)*2;
++    }
++    if (dy < sy || (dy == sy && dx < sx)) {
++      src = scrn_end + sy * linesize + sx;
++      dst = scrn_end + dy * linesize + dx;
++      for (rows = height * fontheight(p); rows--;)
++      {
++              fb_memmove(dst, src, width);
++              src += bytes;
++          dst += bytes;
++      }
++    } else {
++      src = scrn_end + (sy+height) * linesize + sx - bytes;
++          dst = scrn_end + (dy+height) * linesize + dx - bytes;
++      for (rows = height * fontheight(p); rows--;)
++      {
++              fb_memmove(dst, src, width);
++          src -= bytes;
++          dst -= bytes;
++      }
++    }
++/* if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */
++    } else {
+     if (sx == 0 && dx == 0 && width * fontwidth(p) * 2 == bytes) {
+       fb_memmove(p->screen_base + dy * linesize,
+                 p->screen_base + sy * linesize,
+@@ -78,6 +160,8 @@
+           dst -= bytes;
+       }
+     }
++    }
++/* elseif ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */
+ }
+ static inline void rectfill(u8 *dest, int width, int height, u32 data,
+@@ -108,10 +192,16 @@
+     int bytes = p->next_line, lines = height * fontheight(p);
+     u32 bgx;
+-    dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p) * 2;
+-
+-    bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+-
++    if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++        dest = p->screen_base
++               + p->var.xres*p->var.yres * 2
++               - (sy+height) * fontheight(p) * bytes
++               + sx * fontwidth(p) * 2;
++        bgx = 1;
++    } else {
++        dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p) * 2;
++        bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
++    }
+     width *= fontwidth(p)/4;
+     if (width * 8 == bytes)
+       rectfill(dest, lines * width * 4, 1, bgx, bytes);
+@@ -126,14 +216,69 @@
+     int bytes = p->next_line, rows;
+     u32 eorx, fgx, bgx;
+-    dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2;
+-
+     fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)];
+     bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)];
+     fgx |= (fgx << 16);
+     bgx |= (bgx << 16);
+     eorx = fgx ^ bgx;
++    if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++    dest = p->screen_base
++           + p->var.xres*p->var.yres * 2
++           - yy * fontheight(p) * bytes
++           - xx * fontwidth(p) * 2;
++
++    switch (fontwidth(p)) {
++    case 4:
++      cdat = p->fontdata + (c & p->charmask) * fontheight(p);
++      for (rows = fontheight(p); rows--; dest += bytes)
++      {
++          bits = mirrortab_cfb16[*cdat++];
++          fb_writel((tab_cfb16[bits >> 6]     & eorx) ^ bgx, dest-8);
++          fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-4);
++      }
++    case 8:
++      cdat = p->fontdata + (c & p->charmask) * fontheight(p);
++      for (rows = fontheight(p); rows--; dest += bytes)
++      {
++          bits = mirrortab_cfb16[*cdat++];
++          fb_writel((tab_cfb16[bits >> 6]     & eorx) ^ bgx, dest-16);
++          fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-12);
++                      fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest-8);
++              fb_writel((tab_cfb16[bits & 3]      & eorx) ^ bgx, dest-4);
++      }
++      break;
++    case 12:
++      cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1);
++      for (rows = fontheight(p); rows--; dest += bytes) {
++          bits = mirrortab_cfb16[*cdat++];
++          fb_writel((tab_cfb16[bits >> 6]     & eorx) ^ bgx, dest-24);
++          fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-20);
++          fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest-16);
++          fb_writel((tab_cfb16[bits & 3]      & eorx) ^ bgx, dest-12);
++          bits = mirrortab_cfb16[*cdat++];
++          fb_writel((tab_cfb16[bits >> 6]     & eorx) ^ bgx, dest-8);
++          fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-4);
++      }
++    case 16:
++      cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1);
++      for (rows = fontheight(p); rows--; dest += bytes) {
++          bits = mirrortab_cfb16[*cdat++];
++          fb_writel((tab_cfb16[bits >> 6]     & eorx) ^ bgx, dest-32);
++          fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-28);
++          fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest-24);
++          fb_writel((tab_cfb16[bits & 3]      & eorx) ^ bgx, dest-20);
++          bits = mirrortab_cfb16[*cdat++];
++          fb_writel((tab_cfb16[bits >> 6]     & eorx) ^ bgx, dest-16);
++          fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-12);
++              fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest-8);
++              fb_writel((tab_cfb16[bits & 3]      & eorx) ^ bgx, dest-4);
++      }
++      break;
++    }
++/* if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */
++    } else {
++    dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2;
+     switch (fontwidth(p)) {
+     case 4:
+     case 8:
+@@ -167,6 +312,8 @@
+       }
+       break;
+     }
++    }
++/* elseif ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */
+ }
+ void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p,
+@@ -177,7 +324,6 @@
+     int rows, bytes = p->next_line;
+     u32 eorx, fgx, bgx;
+-    dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2;
+     c = scr_readw(s);
+     fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)];
+     bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)];
+@@ -185,6 +331,81 @@
+     bgx |= (bgx << 16);
+     eorx = fgx ^ bgx;
++    if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++    dest0 = p->screen_base 
++            + p->var.xres * p->var.yres * 2
++            - yy * fontheight(p) * bytes
++            - xx * fontwidth(p) * 2;
++
++    switch (fontwidth(p)) {
++    case 4:
++      while (count--) {
++          c = scr_readw(s++) & p->charmask;
++          cdat = p->fontdata + c * fontheight(p);
++          for (rows = fontheight(p), dest = dest0; rows--; dest -= bytes)
++          {
++                      u8 bits = mirrortab_cfb16[*cdat++];
++              fb_writel((tab_cfb16[bits >> 6]     & eorx) ^ bgx, dest-8);
++              fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-4);
++          }
++          dest0 -= fontwidth(p)*2;
++      }
++    case 8:
++      while (count--) {
++          c = scr_readw(s++) & p->charmask;
++          cdat = p->fontdata + c * fontheight(p);
++          for (rows = fontheight(p), dest = dest0; rows--; dest -= bytes)
++          {
++                      u8 bits = mirrortab_cfb16[*cdat++];
++              fb_writel((tab_cfb16[bits >> 6]     & eorx) ^ bgx, dest-16);
++              fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-12);
++                  fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest-8);
++                  fb_writel((tab_cfb16[bits & 3]      & eorx) ^ bgx, dest-4);
++          }
++          dest0 -= fontwidth(p)*2;
++      }
++      break;
++    case 12:
++      while (count--) {
++          c = scr_readw(s++) & p->charmask;
++          cdat = p->fontdata + (c * fontheight(p) << 1);
++          for (rows = fontheight(p), dest = dest0; rows--; dest -= bytes)
++          {
++                      u8 bits = mirrortab_cfb16[*cdat++];
++              fb_writel((tab_cfb16[bits >> 6]     & eorx) ^ bgx, dest-24);
++              fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-20);
++              fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest-16);
++              fb_writel((tab_cfb16[bits & 3]      & eorx) ^ bgx, dest-12);
++                      bits = mirrortab_cfb16[*cdat++];
++              fb_writel((tab_cfb16[bits >> 6]     & eorx) ^ bgx, dest-8);
++              fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-4);
++          }
++          dest0 -= fontwidth(p)*2;
++      }
++    case 16:
++      while (count--) {
++          c = scr_readw(s++) & p->charmask;
++          cdat = p->fontdata + (c * fontheight(p) << 1);
++          for (rows = fontheight(p), dest = dest0; rows--; dest -= bytes)
++          {
++                      u8 bits = mirrortab_cfb16[*cdat++];
++              fb_writel((tab_cfb16[bits >> 6]     & eorx) ^ bgx, dest-32);
++              fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-28);
++              fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest-24);
++              fb_writel((tab_cfb16[bits & 3]      & eorx) ^ bgx, dest-20);
++                      bits = mirrortab_cfb16[*cdat++];
++              fb_writel((tab_cfb16[bits >> 6]     & eorx) ^ bgx, dest-16);
++              fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest-12);
++                  fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest-8);
++                  fb_writel((tab_cfb16[bits & 3]      & eorx) ^ bgx, dest-4);
++          }
++          dest0 -= fontwidth(p)*2;
++      }
++      break;
++    }
++/* if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */
++    } else {
++    dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2;
+     switch (fontwidth(p)) {
+     case 4:
+     case 8:
+@@ -226,6 +447,8 @@
+       }
+       break;
+     }
++    }
++/* elseif ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */
+ }
+ void fbcon_cfb16_revc(struct display *p, int xx, int yy)
+@@ -233,6 +456,32 @@
+     u8 *dest;
+     int bytes = p->next_line, rows;
++    if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++    dest = p->screen_base
++           + p->var.xres*p->var.yres * 2
++           - yy * fontheight(p) * bytes
++           - xx * fontwidth(p) * 2;
++    for (rows = fontheight(p); rows--; dest -= bytes) {
++      switch (fontwidth(p)) {
++      case 16:
++          fb_writel(fb_readl(dest-32) ^ 0xffffffff, dest-32);
++          fb_writel(fb_readl(dest-28) ^ 0xffffffff, dest-28);
++          /* FALL THROUGH */
++      case 12:
++          fb_writel(fb_readl(dest-24) ^ 0xffffffff, dest-24);
++          fb_writel(fb_readl(dest-20) ^ 0xffffffff, dest-20);
++          /* FALL THROUGH */
++      case 8:
++          fb_writel(fb_readl(dest-16) ^ 0xffffffff, dest-16);
++          fb_writel(fb_readl(dest-12) ^ 0xffffffff, dest-12);
++          /* FALL THROUGH */
++      case 4:
++          fb_writel(fb_readl(dest-8) ^ 0xffffffff, dest-8);
++          fb_writel(fb_readl(dest-4) ^ 0xffffffff, dest-4);
++      }
++    }
++/* if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */
++    } else {
+     dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p)*2;
+     for (rows = fontheight(p); rows--; dest += bytes) {
+       switch (fontwidth(p)) {
+@@ -253,6 +502,8 @@
+           fb_writel(fb_readl(dest+4) ^ 0xffffffff, dest+4);
+       }
+     }
++    }
++/* elseif ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */
+ }
+ void fbcon_cfb16_clear_margins(struct vc_data *conp, struct display *p,
+@@ -268,6 +519,9 @@
+     bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+     if (!bottom_only && (right_width = p->var.xres-right_start))
++    if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++        printk("---@paul@------------------------- fbcon-cfb16 clear margins\n");
++    }
+       rectfill(p->screen_base+right_start*2, right_width,
+                p->var.yres_virtual, bgx, bytes);
+     if ((bottom_width = p->var.yres-bottom_start))
+--- linux-2.4.21/drivers/video/fbcon-cfb8.c~fb-turn180
++++ linux-2.4.21/drivers/video/fbcon-cfb8.c
+@@ -39,6 +39,41 @@
+ #endif
+ };
++static u8 mirrortab_cfb8[] = {
++   0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,
++   0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
++   0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,
++   0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
++   0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,
++   0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
++   0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,
++   0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
++   0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,
++   0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
++   0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,
++   0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
++   0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,
++   0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
++   0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,
++   0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
++   0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,
++   0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
++   0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,
++   0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
++   0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,
++   0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
++   0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,
++   0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
++   0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,
++   0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
++   0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,
++   0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
++   0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,
++   0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
++   0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,
++   0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
++};
++
+ void fbcon_cfb8_setup(struct display *p)
+ {
+     p->next_line = p->line_length ? p->line_length : p->var.xres_virtual;
+@@ -51,10 +86,57 @@
+     int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
+     u8 *src,*dst;
++    if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++/*
++    printk("---@paul@-------------------------\n"\
++       "fbcon_cfb8_bmove() %d %d %d %d %d %d\n",
++       sx,sy,dx,dy,height,width
++      );
++*/
++    if (sx == 0 && dx == 0 && width * fontwidth(p) == bytes)
++    {
++        fb_memmove(
++            p->screen_base + p->var.xres*p->var.yres - dy * linesize,
++            p->screen_base + p->var.xres*p->var.yres - sy * linesize,
++            height * linesize);
++      return;
++    }
++    if (fontwidthlog(p)) {
++      sx <<= fontwidthlog(p); dx <<= fontwidthlog(p); width <<= fontwidthlog(p);
++    } else {
++      sx *= fontwidth(p); dx *= fontwidth(p); width *= fontwidth(p);
++    }
++    if (dy < sy || (dy == sy && dx < sx))
++    {
++          src = p->screen_base + p->var.xres*p->var.yres
++                - sy * linesize - sx;
++      dst = p->screen_base + p->var.xres*p->var.yres
++            - dy * linesize - dx;
++      for (rows = height * fontheight(p) ; rows-- ;)
++      {
++          fb_memmove(dst, src, width);
++          src += bytes;
++          dst += bytes;
++      }
++    } else
++    {
++          src = p->screen_base + p->var.xres*p->var.yres
++              - (sy+height) * linesize - sx + bytes;
++      dst = p->screen_base + p->var.xres*p->var.yres
++              - (dy+height) * linesize - dx + bytes;
++          for (rows = height * fontheight(p) ; rows-- ;)
++          {
++              fb_memmove(dst, src, width);
++          src -= bytes;
++          dst -= bytes;
++      }
++    }
++/* if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */
++    } else {
+     if (sx == 0 && dx == 0 && width * fontwidth(p) == bytes) {
+-      fb_memmove(p->screen_base + dy * linesize,
+-                p->screen_base + sy * linesize,
+-                height * linesize);
++        fb_memmove(p->screen_base + dy * linesize,
++                  p->screen_base + sy * linesize,
++                  height * linesize);
+       return;
+     }
+     if (fontwidthlog(p)) {
+@@ -79,6 +161,7 @@
+           dst -= bytes;
+       }
+     }
++/* elseif ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */
+ }
+ static inline void rectfill(u8 *dest, int width, int height, u8 data,
+@@ -97,11 +180,17 @@
+     int bytes=p->next_line,lines=height * fontheight(p);
+     u8 bgx;
+-    dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p);
+-
+-    bgx=attr_bgcol_ec(p,conp);
+-
+-    width *= fontwidth(p);
++    if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++        bgx=attr_bgcol_ec(p,conp);
++        width *= fontwidth(p);
++        dest = p->screen_base + p->var.xres*p->var.yres
++               - (sy+height) * fontheight(p) * bytes
++               + sx * fontwidth(p);
++    } else {
++        dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p);
++        bgx=attr_bgcol_ec(p,conp);
++        width *= fontwidth(p);
++    }
+     if (width == bytes)
+       rectfill(dest, lines * width, 1, bgx, bytes);
+     else
+@@ -114,8 +203,8 @@
+     u8 *dest,*cdat;
+     int bytes=p->next_line,rows;
+     u32 eorx,fgx,bgx;
++    u8      chrrow;
+-    dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p);
+     if (fontwidth(p) <= 8)
+       cdat = p->fontdata + (c & p->charmask) * fontheight(p);
+     else
+@@ -129,6 +218,53 @@
+     bgx |= (bgx << 16);
+     eorx = fgx ^ bgx;
++    if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++    dest = p->screen_base
++           + p->var.xres*p->var.yres
++           - yy * fontheight(p) * bytes
++           - xx * fontwidth(p);
++
++    switch (fontwidth(p)) {
++    case 4:
++      for (rows = fontheight(p) ; rows-- ; dest += bytes)
++      {
++            chrrow = mirrortab_cfb8[*cdat++];
++          fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx) ^ bgx, dest-4);
++          }
++        break;
++    case 8:
++      for (rows = fontheight(p) ; rows-- ; dest += bytes)
++      {
++            chrrow = mirrortab_cfb8[*cdat++];
++              fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx)  ^ bgx, dest-8);
++              fb_writel((nibbletab_cfb8[chrrow & 0xf] & eorx) ^ bgx, dest-4);
++        }
++        break;
++    case 12:
++      for (rows = fontheight(p) ; rows-- ; dest += bytes)
++      {
++            chrrow = mirrortab_cfb8[*cdat++];
++              fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx)  ^ bgx, dest-12);
++          fb_writel((nibbletab_cfb8[chrrow & 0xf] & eorx) ^ bgx, dest-8);
++            chrrow = mirrortab_cfb8[*cdat++];
++              fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx)  ^ bgx, dest-4);
++        }
++        break;
++    case 16:
++      for (rows = fontheight(p) ; rows-- ; dest += bytes)
++      {
++            chrrow = mirrortab_cfb8[*cdat++];
++              fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx)  ^ bgx, dest-16);
++          fb_writel((nibbletab_cfb8[chrrow & 0xf] & eorx) ^ bgx, dest-12);
++            chrrow = mirrortab_cfb8[*cdat++];
++              fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx)  ^ bgx, dest-8);
++              fb_writel((nibbletab_cfb8[chrrow & 0xf] & eorx) ^ bgx, dest-4);
++        }
++        break;
++    }
++/* if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */
++    } else {
++    dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p);
+     switch (fontwidth(p)) {
+     case 4:
+       for (rows = fontheight(p) ; rows-- ; dest += bytes)
+@@ -152,6 +288,8 @@
+         }
+         break;
+     }
++    }
++/* elseif ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */
+ }
+ void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p, 
+@@ -161,8 +299,8 @@
+     u16 c;
+     int rows,bytes=p->next_line;
+     u32 eorx, fgx, bgx;
++    u8      chrrow;
+-    dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p);
+     c = scr_readw(s);
+     fgx = attr_fgcol(p, c);
+     bgx = attr_bgcol(p, c);
+@@ -171,6 +309,76 @@
+     bgx |= (bgx << 8);
+     bgx |= (bgx << 16);
+     eorx = fgx ^ bgx;
++
++    if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++    dest0 = p->screen_base
++            + p->var.xres*p->var.yres
++            - yy * fontheight(p) * bytes
++            - xx * fontwidth(p);
++    switch (fontwidth(p)) {
++    case 4:
++      while (count--) {
++              c = scr_readw(s++) & p->charmask;
++              cdat = p->fontdata + c * fontheight(p);
++
++          for (rows = fontheight(p), dest = dest0; rows-- ; dest -= bytes)
++          {
++                chrrow = mirrortab_cfb8[*cdat++];
++                      fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx) ^ bgx, dest-4);
++            }
++          dest0 -= 4;
++        }
++        break;
++    case 8:
++        while (count--) {
++            c = scr_readw(s++) & p->charmask;
++            cdat = p->fontdata + c * fontheight(p);
++            for (rows = fontheight(p), dest = dest0; rows-- ; dest -= bytes)
++            {
++                chrrow = mirrortab_cfb8[*cdat++];
++                fb_writel((nibbletab_cfb8[chrrow >> 4]  & eorx) ^ bgx, dest-8);
++                fb_writel((nibbletab_cfb8[chrrow & 0xf] & eorx) ^ bgx, dest-4);
++            }
++            dest0 -= 8;
++        }
++        break;
++    case 12:
++      while (count--) {
++              c = scr_readw(s++) & p->charmask;
++              cdat = p->fontdata + (c * fontheight(p) << 1);
++
++          for (rows = fontheight(p), dest = dest0; rows-- ; dest -= bytes)
++          {
++                chrrow = mirrortab_cfb8[*cdat++];
++                      fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx)  ^ bgx, dest-12);
++                      fb_writel((nibbletab_cfb8[chrrow & 0xf] & eorx) ^ bgx, dest-8);
++                chrrow = mirrortab_cfb8[*cdat++];
++                      fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx) ^ bgx, dest-4);
++              }
++              dest0 -= fontwidth(p);
++        }
++        break;
++    case 16:
++      while (count--) {
++              c = scr_readw(s++) & p->charmask;
++              cdat = p->fontdata + (c * fontheight(p) << 1);
++
++          for (rows = fontheight(p), dest = dest0; rows-- ; dest -= bytes)
++          {
++                chrrow = mirrortab_cfb8[*cdat++];
++                      fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx)  ^ bgx, dest-16);
++                      fb_writel((nibbletab_cfb8[chrrow & 0xf] & eorx) ^ bgx, dest-12);
++                chrrow = mirrortab_cfb8[*cdat++];
++                      fb_writel((nibbletab_cfb8[chrrow >> 4] & eorx)  ^ bgx, dest-8);
++                fb_writel((nibbletab_cfb8[chrrow & 0xf] & eorx) ^ bgx, dest-4);
++              }
++              dest0 -= fontwidth(p);
++        }
++        break;
++    } /* switch (fontwidth(p)) */
++/* if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */
++    } else {
++    dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p);
+     switch (fontwidth(p)) {
+     case 4:
+       while (count--) {
+@@ -212,6 +420,8 @@
+         }
+         break;
+     }
++    }
++/* elseif ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */
+ }
+ void fbcon_cfb8_revc(struct display *p, int xx, int yy)
+@@ -219,6 +429,21 @@
+     u8 *dest;
+     int bytes=p->next_line, rows;
++    if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++    dest = p->screen_base + p->var.xres*p->var.yres
++           - yy * fontheight(p) * bytes
++           - xx * fontwidth(p);
++    for (rows = fontheight(p) ; rows-- ; dest -= bytes) {
++      switch (fontwidth(p)) {
++      case 16: fb_writel(fb_readl(dest-16) ^ 0x0f0f0f0f, dest-16); /* fall thru */
++      case 12: fb_writel(fb_readl(dest-12) ^ 0x0f0f0f0f, dest-12); /* fall thru */
++      case 8: fb_writel(fb_readl(dest-8)   ^ 0x0f0f0f0f, dest-8);  /* fall thru */
++      case 4: fb_writel(fb_readl(dest-4)   ^ 0x0f0f0f0f, dest-4);  /* fall thru */
++      default: break;
++      }
++    }
++/* if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */
++    } else {
+     dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p);
+     for (rows = fontheight(p) ; rows-- ; dest += bytes) {
+       switch (fontwidth(p)) {
+@@ -229,6 +454,8 @@
+       default: break;
+       }
+     }
++    }
++/* elseif ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) */
+ }
+ void fbcon_cfb8_clear_margins(struct vc_data *conp, struct display *p,
+@@ -244,6 +471,9 @@
+     bgx=attr_bgcol_ec(p,conp);
+     if (!bottom_only && (right_width = p->var.xres-right_start))
++    if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++        printk("---@paul@------------------------- fbcon-cfb8 clear margins\n");
++    }
+       rectfill(p->screen_base+right_start, right_width, p->var.yres_virtual,
+                bgx, bytes);
+     if ((bottom_width = p->var.yres-bottom_start))
+--- linux-2.4.21/drivers/video/fbcon.c~fb-turn180
++++ linux-2.4.21/drivers/video/fbcon.c
+@@ -1558,6 +1558,7 @@
+       update_region(fg_console,
+                     conp->vc_origin + conp->vc_size_row * conp->vc_top,
+                     conp->vc_size_row * (conp->vc_bottom - conp->vc_top) / 2);
++      conp->vc_top = 0;
+       return 0;
+     }
+     return 1;
+@@ -2209,7 +2210,16 @@
+               src = logo;
+               bdepth = depth/8;
+               for( y1 = 0; y1 < LOGO_H; y1++ ) {
+-                  dst = fb + y1*line + x*bdepth;
++
++            if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++/*
++    Das ist NICHT die richtige Stelle für den Ramses 16 BPP Modus
++    aber dafür die weiter unten.
++*/
++                      dst = fb + p->var.xres*p->var.yres*bdepth -1 - y1*line - x*bdepth;
++            } else {
++                  dst = fb + y1*line + x*bdepth;
++            }
+                   for( x1 = 0; x1 < LOGO_W; x1++, src++ ) {
+                       val = (*src << redshift) |
+                             (*src << greenshift) |
+@@ -2217,18 +2227,32 @@
+                       if (bdepth == 4 && !((long)dst & 3)) {
+                           /* Some cards require 32bit access */
+                           fb_writel (val, dst);
+-                          dst += 4;
++                if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++                          dst -= 4;
++                } else {
++                          dst += 4;
++                }
+                       } else if (bdepth == 2 && !((long)dst & 1)) {
+                           /* others require 16bit access */
+                           fb_writew (val,dst);
+-                          dst +=2;
++                if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++                          dst -= 2;
++                } else {
++                          dst +=2;
++                }
+                       } else {
++                if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++                              for( i = bdepth-1; i >= 0; --i )
++                                  fb_writeb (val >> (i*8), dst--);
++
++                } else {
+ #ifdef __LITTLE_ENDIAN
+-                          for( i = 0; i < bdepth; ++i )
++                          for( i = 0; i < bdepth; ++i )
+ #else
+-                          for( i = bdepth-1; i >= 0; --i )
++                          for( i = bdepth-1; i >= 0; --i )
+ #endif
+-                              fb_writeb (val >> (i*8), dst++);
++                              fb_writeb (val >> (i*8), dst++);
++                }
+                       }
+                   }
+               }
+@@ -2239,28 +2263,42 @@
+               src = linux_logo16;
+               bdepth = (depth+7)/8;
+               for( y1 = 0; y1 < LOGO_H; y1++ ) {
+-                  dst = fb + y1*line + x*bdepth;
++            if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++                      dst = fb + p->var.xres*p->var.yres*bdepth -1 - y1*line - x*bdepth;
++            } else {
++                  dst = fb + y1*line + x*bdepth;
++            }
+                   for( x1 = 0; x1 < LOGO_W/2; x1++, src++ ) {
+                       pix = *src >> 4; /* upper nibble */
+                       val = (pix << redshift) |
+                             (pix << greenshift) |
+                             (pix << blueshift);
++            if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++                              for( i = bdepth-1; i >= 0; --i )
++                          fb_writeb (val >> (i*8), dst--);
++            } else {
+ #ifdef __LITTLE_ENDIAN
+-                      for( i = 0; i < bdepth; ++i )
++                      for( i = 0; i < bdepth; ++i )
+ #else
+-                      for( i = bdepth-1; i >= 0; --i )
++                      for( i = bdepth-1; i >= 0; --i )
+ #endif
+-                          fb_writeb (val >> (i*8), dst++);
++                          fb_writeb (val >> (i*8), dst++);
++            }
+                       pix = *src & 0x0f; /* lower nibble */
+                       val = (pix << redshift) |
+                             (pix << greenshift) |
+                             (pix << blueshift);
++            if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++                              for( i = bdepth-1; i >= 0; --i )
++                          fb_writeb (val >> (i*8), dst--);
++            } else {
+ #ifdef __LITTLE_ENDIAN
+-                      for( i = 0; i < bdepth; ++i )
++                      for( i = 0; i < bdepth; ++i )
+ #else
+-                      for( i = bdepth-1; i >= 0; --i )
++                      for( i = bdepth-1; i >= 0; --i )
+ #endif
+-                          fb_writeb (val >> (i*8), dst++);
++                          fb_writeb (val >> (i*8), dst++);
++            }
+                   }
+               }
+           }
+@@ -2287,7 +2325,11 @@
+           src = logo;
+           for( y1 = 0; y1 < LOGO_H; y1++ ) {
+-              dst = fb + y1*line + x*bdepth;
++        if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++              dst = fb + p->var.xres*p->var.yres*bdepth -1 - y1*line - x*bdepth;
++        } else {
++              dst = fb + y1*line + x*bdepth;
++        }
+               for( x1 = 0; x1 < LOGO_W; x1++, src++ ) {
+                   val = safe_shift((linux_logo_red[*src-32]   & redmask), redshift) |
+                         safe_shift((linux_logo_green[*src-32] & greenmask), greenshift) |
+@@ -2295,18 +2337,31 @@
+                   if (bdepth == 4 && !((long)dst & 3)) {
+                       /* Some cards require 32bit access */
+                       fb_writel (val, dst);
+-                      dst += 4;
++            if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++                      dst -= 4;
++            } else {
++                      dst += 4;
++            }
+                   } else if (bdepth == 2 && !((long)dst & 1)) {
+                       /* others require 16bit access */
+                       fb_writew (val,dst);
+-                      dst +=2;
++            if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++                      dst -= 2;
++            } else {
++                      dst +=2;
++            }
+                   } else {
++            if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++                      for( i = bdepth-1; i >= 0; --i )
++                          fb_writeb (val >> (i*8), dst--);
++            } else {
+ #ifdef __LITTLE_ENDIAN
+-                      for( i = 0; i < bdepth; ++i )
++                      for( i = 0; i < bdepth; ++i )
+ #else
+-                      for( i = bdepth-1; i >= 0; --i )
++                      for( i = bdepth-1; i >= 0; --i )
+ #endif
+-                          fb_writeb (val >> (i*8), dst++);
++                          fb_writeb (val >> (i*8), dst++);
++            }
+                   }
+               }
+           }
+@@ -2331,13 +2386,24 @@
+       if (depth == 8 && p->type == FB_TYPE_PACKED_PIXELS) {
+           /* depth 8 or more, packed, with color registers */
+               
+-          src = logo;
+-          for( y1 = 0; y1 < LOGO_H; y1++ ) {
+-              dst = fb + y1*line + x;
+-              for( x1 = 0; x1 < LOGO_W; x1++ )
+-                  fb_writeb (*src++, dst++);
+-          }
+-          done = 1;
++        if ( ramses_flags & RAMSES_FLAGS_LCD_FBTURN) {
++            src = logo;
++            for( y1 = 0; y1 < LOGO_H; y1++ )
++            {
++                dst = fb + p->var.xres*p->var.yres -1 - y1*line - x;
++                      for( x1 = 0; x1 < LOGO_W; x1++ )
++                    fb_writeb (*src++, dst--);
++            }
++            done = 1;
++        } else {
++            src = logo;
++            for( y1 = 0; y1 < LOGO_H; y1++ ) {
++                dst = fb + y1*line + x;
++                for( x1 = 0; x1 < LOGO_W; x1++ )
++                fb_writeb (*src++, dst++);
++            }
++            done = 1;
++        }
+       }
+ #endif
+ #if defined(CONFIG_FBCON_AFB) || defined(CONFIG_FBCON_ILBM) || \
+--- linux-2.4.21/drivers/video/fbmem.c~fb-buffered
++++ linux-2.4.21/drivers/video/fbmem.c
+@@ -302,7 +302,7 @@
+       { "sa1100", sa1100fb_init, NULL },
+ #endif
+ #ifdef CONFIG_FB_PXA
+-      { "pxa", pxafb_init, NULL },
++      { "pxa", pxafb_init, NULL },
+ #endif
+ #ifdef CONFIG_FB_SUN3
+       { "sun3", sun3fb_init, sun3fb_setup },
+@@ -672,7 +672,11 @@
+ #elif defined(__hppa__)
+       pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; 
+ #elif defined(__ia64__) || defined(__arm__)
++#ifdef CONFIG_PXA
++      vma->vm_page_prot = pgprot_noncached_buffered(vma->vm_page_prot);
++#else
+       vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
++#endif
+ #elif defined(__hppa__)
+       pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; 
+ #else
+--- linux-2.4.21/drivers/video/pxafb.c~ramses-lcd
++++ linux-2.4.21/drivers/video/pxafb.c
+@@ -45,8 +45,6 @@
+ #include <video/fbcon.h>
+ #include <video/fbcon-mfb.h>
+-#include <video/fbcon-cfb4.h>
+-#include <video/fbcon-cfb8.h>
+ #include <video/fbcon-cfb16.h>
+ #include <video/lcdctrl.h> /* brightness, contrast, etc. control */
+@@ -57,7 +55,7 @@
+ /*
+  * Complain if VAR is out of range.
+  */
+-#define DEBUG_VAR 1
++#define DEBUG_VAR 0
+ #undef ASSABET_PAL_VIDEO
+@@ -66,16 +64,6 @@
+ void (*pxafb_blank_helper)(int blank);
+ EXPORT_SYMBOL(pxafb_blank_helper);
+-/*
+- * IMHO this looks wrong.  In 8BPP, length should be 8.
+- */
+-static struct pxafb_rgb rgb_8 = {
+-      red:    { offset: 0,  length: 4, },
+-      green:  { offset: 0,  length: 4, },
+-      blue:   { offset: 0,  length: 4, },
+-      transp: { offset: 0,  length: 0, },
+-};
+-
+ static struct pxafb_rgb def_rgb_16 = {
+       red:    { offset: 11, length: 5, },
+       green:  { offset: 5,  length: 6, },
+@@ -99,9 +87,30 @@
+       lccr3:          LCD_LCCR3
+ };
++static struct pxafb_mach_info torisan_fb_info __initdata = {
++      pixclock:       70000,
++      bpp:            LCD_BPP,
++      xres:           320,
++      yres:           240,
++      hsync_len:      2,
++      vsync_len:      2,
++      left_margin:    1,
++      upper_margin:   4,
++      right_margin:   139,
++      lower_margin:   4,
++      sync:           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++      lccr0:          LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | LCCR0_QDM | LCCR0_BM  | LCCR0_OUM | LCCR0_PAS,
++      lccr3:          0x04700007
++};
++
+ static struct pxafb_mach_info * __init
+ pxafb_get_machine_info(struct pxafb_info *fbi)
+ {
++#ifdef CONFIG_ARCH_RAMSES
++      if (ramses_lcd_type == 2)
++              return &torisan_fb_info;
++      else
++#endif
+       return &pxa_fb_info;
+ }
+@@ -276,7 +285,7 @@
+                * 16 bits works apparemtly fine in passive mode for those,
+                * so don't complain
+                */
+-              if (machine_is_lubbock() ||
++              if (machine_is_lubbock() || machine_is_ramses() ||
+                   machine_is_pxa_cerf()) {
+                       ret = 0;
+               } else
+@@ -671,7 +680,7 @@
+ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *fbi)
+ {
+       struct pxafb_lcd_reg new_regs;
+-//    u_int pcd = get_pcd(var->pixclock);
++      u_int pcd = get_pcd(var->pixclock);
+       u_long flags;
+       DPRINTK("Configuring PXA LCD\n");
+@@ -710,7 +719,7 @@
+                       fbi->fb.fix.id, var->lower_margin);
+ #endif
+-#if defined (CONFIG_PXA_CERF_PDA)
++#if defined (CONFIG_PXA_CERF_PDA) || defined(CONFIG_ARCH_RAMSES)
+       new_regs.lccr0 = fbi->lccr0;
+       new_regs.lccr1 =
+               LCCR1_DisWdth(var->xres) +
+@@ -767,8 +776,8 @@
+ //            LCCR3_ACBsCntOff;
+ #endif
+-//    if (pcd)
+-//            new_regs.lccr3 |= LCCR3_PixClkDiv(pcd);
++      if (pcd)
++              new_regs.lccr3 = (new_regs.lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
+       DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0);
+       DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1);
+@@ -820,6 +829,7 @@
+               fbi->fdadr0 = fbi->dmadesc_fbhigh_dma; /* no pal just fbhigh */
+       }
++#if 0
+       DPRINTK("fbi->dmadesc_fblow_cpu = 0x%x\n", fbi->dmadesc_fblow_cpu);
+       DPRINTK("fbi->dmadesc_fbhigh_cpu = 0x%x\n", fbi->dmadesc_fbhigh_cpu);
+       DPRINTK("fbi->dmadesc_palette_cpu = 0x%x\n", fbi->dmadesc_palette_cpu);
+@@ -838,6 +848,7 @@
+       DPRINTK("fbi->dmadesc_fblow_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fblow_cpu->ldcmd);
+       DPRINTK("fbi->dmadesc_fbhigh_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fbhigh_cpu->ldcmd);
+       DPRINTK("fbi->dmadesc_palette_cpu->ldcmd = 0x%x\n", fbi->dmadesc_palette_cpu->ldcmd);
++#endif
+       
+       fbi->reg_lccr0 = new_regs.lccr0;
+       fbi->reg_lccr1 = new_regs.lccr1;
+@@ -874,14 +885,20 @@
+       DPRINTK("backlight on\n");
+ #ifdef CONFIG_ARCH_PXA_IDP
+-      if(machine_is_pxa_idp()) {      
++      if (machine_is_pxa_idp()) {     
+               FB_BACKLIGHT_ON();
+       }
+ #endif
++#ifdef CONFIG_ARCH_RAMSES
++      if (machine_is_ramses()) {
++//printk("--> pxafb_backlight_on\n");
++              ramses_lcd_backlight_on();
++      }
++#endif
+ }
+ /*
+- * FIXME: move LCD power stuf into pxafb_power_down_lcd()
++ * FIXME: move LCD power stuff into pxafb_power_down_lcd()
+  * Also, I'm expecting that the backlight stuff should
+  * be handled differently.
+  */
+@@ -894,7 +911,13 @@
+               FB_BACKLIGHT_OFF();
+       }
+ #endif
+-      
++
++#ifdef CONFIG_ARCH_RAMSES
++      if (machine_is_ramses()) {
++//printk("--> pxafb_backlight_off calling ramses_lcd_backlight_off\n");
++              ramses_lcd_backlight_off();
++      }
++#endif
+ }
+ static void pxafb_power_up_lcd(struct pxafb_info *fbi)
+@@ -902,11 +925,10 @@
+       DPRINTK("LCD power on\n");
+       CKEN |= CKEN16_LCD;
+-      if(machine_is_pxa_cerf()) {
++      if (machine_is_pxa_cerf()) {
+               lcdctrl_enable();
+       }
+-
+-#if CONFIG_ARCH_PXA_IDP
++#ifdef CONFIG_ARCH_PXA_IDP
+       /* set GPIOs, etc */
+       if(machine_is_pxa_idp()) {
+               // FIXME need to add proper delays
+@@ -914,26 +936,36 @@
+               FB_VLCD_ON();   // FIXME this should be after scanning starts
+       }
+ #endif
++
++#ifdef CONFIG_ARCH_RAMSES
++      if (machine_is_ramses()) {
++//printk("--> pxafb_power_up_lcd\n");
++              ramses_lcd_power_on();
++      }
++#endif
+ }
+ static void pxafb_power_down_lcd(struct pxafb_info *fbi)
+ {
+       DPRINTK("LCD power off\n");
++#ifdef CONFIG_ARCH_RAMSES
++      if (machine_is_ramses()) {
++//printk("--> pxafb_power_down_lcd calling ramses_lcd_power_off\n");
++              ramses_lcd_power_off();
++      }
++#endif
+       CKEN &= ~CKEN16_LCD;
+-      if(machine_is_pxa_cerf()) {
++      if (machine_is_pxa_cerf()) {
+               lcdctrl_disable();
+       }
+-
+-      /* set GPIOs, etc */
+-#if CONFIG_ARCH_PXA_IDP
++#ifdef CONFIG_ARCH_PXA_IDP
+       if(machine_is_pxa_idp()) {
+               // FIXME need to add proper delays
+               FB_PWR_OFF();
+               FB_VLCD_OFF();  // FIXME this should be before scanning stops
+       }
+ #endif
+-
+ }
+ static void pxafb_setup_gpio(struct pxafb_info *fbi)
+@@ -1082,6 +1114,10 @@
+               if (old_state != C_DISABLE) {
+                       fbi->state = state;
++#ifdef CONFIG_ARCH_PXA
++                      //printk("--> set_ctrlr_state(%d) calling ramses_lcd_power_off\n", state);
++                      ramses_lcd_power_off();
++#endif
+                       pxafb_backlight_off(fbi);
+                       if (old_state != C_DISABLE_CLKCHANGE)
+                               pxafb_disable_controller(fbi);
+@@ -1191,6 +1227,7 @@
+               if (state == 0) {
+                       /* Enter D0. */
++//printk("--> pxafb_pm_callback(%d)\n", req);
+                       set_ctrlr_state(fbi, C_ENABLE);
+               } else {
+                       /* Enter D1-D3.  Disable the LCD controller.  */
+@@ -1300,7 +1337,6 @@
+       fbi->fb.disp            = (struct display *)(fbi + 1);
+       fbi->fb.pseudo_palette  = (void *)(fbi->fb.disp + 1);
+-      fbi->rgb[RGB_8]         = &rgb_8;
+       fbi->rgb[RGB_16]        = &def_rgb_16;
+       inf = pxafb_get_machine_info(fbi);
+@@ -1348,11 +1384,18 @@
+       if (!fbi)
+               goto failed;
+-      if(machine_is_pxa_cerf()) {
+-              // brightness&contrast is handled via lcdctrl.
++      if (machine_is_pxa_cerf()) {
++              // brightness & contrast is handled via lcdctrl
+               lcdctrl_init();
+       }
+-
++#if 0
++      ifdef CONFIG_ARCH_RAMSES
++      if (machine_is_ramses()) {
++              ramses_lcd_set_intensity(100);
++              ramses_lcd_set_brightness(20);
++              ramses_lcd_set_contrast(84,1);
++      }
++#endif
+       /* Initialize video memory */
+       ret = pxafb_map_video_memory(fbi);
+       if (ret)
+--- linux-2.4.21/drivers/video/pxafb.h~ramses-lcd
++++ linux-2.4.21/drivers/video/pxafb.h
+@@ -235,4 +235,22 @@
+ #define LCD_LCCR0                     (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | LCCR0_QDM | LCCR0_BM  | LCCR0_OUM)
+ #define LCD_LCCR3                     (LCCR3_PCP | LCCR3_PixClkDiv(0x12) | LCCR3_Bpp(PXAFB_BPP_BITS) | LCCR3_Acb(0x18))
++#elif defined CONFIG_ARCH_RAMSES
++#define LCD_PIXCLOCK                  100000
++#define LCD_BPP                               PXAFB_BPP
++#define LCD_XRES                      240
++#define LCD_YRES                      320
++#define LCD_HORIZONTAL_SYNC_PULSE_WIDTH       6
++#define LCD_VERTICAL_SYNC_PULSE_WIDTH 1
++#define LCD_BEGIN_OF_LINE_WAIT_COUNT  21
++#define LCD_BEGIN_FRAME_WAIT_COUNT    7
++#define LCD_END_OF_LINE_WAIT_COUNT    21
++#define LCD_END_OF_FRAME_WAIT_COUNT   1
++#define LCD_SYNC                      (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT)
++#define LCD_LCCR0                     (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM | LCCR0_QDM | LCCR0_BM  | LCCR0_OUM)
++#define LCD_LCCR3                     (LCCR3_PCP | LCCR3_Bpp(PXAFB_BPP_BITS) | LCCR3_Acb(0xe))
++
++// PCD 21 ist noch ok
++// PIXCLOCK 150000 ergibt LCCR3_PCD von 15
++
+ #endif
+--- linux-2.4.21/include/asm-arm/arch-pxa/hardware.h~ramses
++++ linux-2.4.21/include/asm-arm/arch-pxa/hardware.h
+@@ -127,16 +127,20 @@
+  * Implementation specifics
+  */
+-//#ifdef CONFIG_ARCH_LUBBOCK
++#ifdef CONFIG_ARCH_LUBBOCK
+ #include "lubbock.h"
+-//#endif
++#endif
+-//#ifdef CONFIG_ARCH_PXA_IDP
++#ifdef CONFIG_ARCH_PXA_IDP
+ #include "idp.h"
+-//#endif
++#endif
+-//#ifdef CONFIG_ARCH_PXA_CERF
++#ifdef CONFIG_ARCH_PXA_CERF
+ #include "cerf.h"
+-//#endif
++#endif
++
++#ifdef CONFIG_ARCH_RAMSES
++#include "ramses.h"
++#endif
+ #endif  /* _ASM_ARCH_HARDWARE_H */
+--- linux-2.4.21/include/asm-arm/arch-pxa/irqs.h~ramses
++++ linux-2.4.21/include/asm-arm/arch-pxa/irqs.h
+@@ -105,14 +105,13 @@
+ #define S0_BVD1_STSCHG        SA1111_IRQ(53)
+ #define S1_BVD1_STSCHG        SA1111_IRQ(54)
+-#define SA1111_IRQ_MAX        SA1111_IRQ(54)
+ #undef NR_IRQS
+ #define NR_IRQS               (SA1111_IRQ_MAX + 1)
+ #endif        // defined(CONFIG_SA1111)
+-#if defined(CONFIG_ARCH_LUBBOCK) || defined(CONFIG_ARCH_PXA_IDP) 
++#if defined(CONFIG_ARCH_LUBBOCK) || defined(CONFIG_ARCH_PXA_IDP)
+ #if CONFIG_SA1111
+ #define LUBBOCK_IRQ(x)        (SA1111_IRQ_MAX + 1 + (x))
+ #else
+@@ -132,6 +131,3 @@
+ #define NR_IRQS               (LUBBOCK_LAST_IRQ + 1)
+ #endif        // CONFIG_ARCH_LUBBOCK
+-
+-
+-
+--- linux-2.4.21/include/asm-arm/arch-pxa/pxa-regs.h~ramses
++++ linux-2.4.21/include/asm-arm/arch-pxa/pxa-regs.h
+@@ -1051,6 +1051,7 @@
+ #define PGSR1         __REG(0x40F00024)  /* Power Manager GPIO Sleep State Register for GP[63-32] */
+ #define PGSR2         __REG(0x40F00028)  /* Power Manager GPIO Sleep State Register for GP[84-64] */
+ #define RCSR          __REG(0x40F00030)  /* Reset Controller Status Register */
++#define PMFW          __REG(0x40F00034)  /* Power Manager Fast-Sleep Wakeup Configuration Register */
+ #define PSSR_RDH      (1 << 5)        /* Read Disable Hold */
+ #define PSSR_PH               (1 << 4)        /* Peripheral Control Hold */
+--- /dev/null
++++ linux-2.4.21/include/asm-arm/arch-pxa/ramses.h
+@@ -0,0 +1,364 @@
++/*
++ *  linux/include/asm-arm/arch-pxa/ramses.h
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * Copyright (c) 2002,2003 M&N Logistik-Lösungen Online GmbH
++ *
++ * 2001-09-13: Cliff Brake <cbrake@accelent.com>
++ *             Initial code
++ *
++ * 2002-10-08: adaption from PXA IDP to Ramses
++ * 
++ */
++
++
++/*
++ * Note: this file must be safe to include in assembly files
++ */
++
++#define RAMSES_FLASH_PHYS     (PXA_CS0_PHYS)
++#define RAMSES_ALT_FLASH_PHYS (PXA_CS1_PHYS)
++#define RAMSES_MEDIAQ_PHYS    (PXA_CS3_PHYS)
++#define RAMSES_CONTROL_PHYS   (PXA_CS4_PHYS)
++#define RAMSES_IDE_PHYS               (PXA_CS5_PHYS + 0x03000000)
++#define RAMSES_ETH_PHYS               (PXA_CS5_PHYS + 0x03400000)
++#define RAMSES_COREVOLT_PHYS  (PXA_CS5_PHYS + 0x03800000)
++#define RAMSES_CPLD_PHYS      (PXA_CS5_PHYS + 0x03C00000)
++
++/*
++ * virtual memory map
++ */
++
++#define RAMSES_IDE_BASE               (0xf0000000)
++#define RAMSES_IDE_SIZE               (1*1024*1024)
++#define RAMSES_ETH_BASE               (RAMSES_IDE_BASE + RAMSES_IDE_SIZE)
++#define RAMSES_ETH_SIZE               (1*1024*1024)
++#define RAMSES_COREVOLT_BASE  (RAMSES_ETH_BASE + RAMSES_ETH_SIZE)
++#define RAMSES_COREVOLT_SIZE  (1*1024*1024)
++#define RAMSES_CPLD_BASE      (RAMSES_COREVOLT_BASE + RAMSES_COREVOLT_SIZE)
++#define RAMSES_CPLD_SIZE      (1*1024*1024)
++#define RAMSES_CONTROL_BASE   (RAMSES_CPLD_BASE + RAMSES_CPLD_SIZE)
++#define RAMSES_CONTROL_SIZE   (1*1024*1024)
++
++#if (RAMSES_CONTROL_BASE + RAMSES_CONTROL_SIZE) > 0xfc000000
++#error Your custom IO space is getting a bit large !!
++#endif
++
++#define CPLD_P2V(x)           ((x) - RAMSES_CPLD_PHYS + RAMSES_CPLD_BASE)
++#define CPLD_V2P(x)           ((x) - RAMSES_CPLD_BASE + RAMSES_CPLD_PHYS)
++#define CTRL_P2V(x)           ((x) - RAMSES_CONTROL_PHYS + RAMSES_CONTROL_BASE)
++#define CTRL_V2P(x)           ((x) - RAMSES_CONTROL_BASE + RAMSES_CONTROL_PHYS)
++#define CORE_P2V(x)           ((x) - RAMSES_COREVOLT_PHYS + RAMSES_COREVOLT_BASE)
++#define CORE_V2P(x)           ((x) - RAMSES_COREVOLT_BASE + RAMSES_COREVOLT_PHYS)
++
++//smc91111 driver compatibility issue
++#define ETH_BASE              RAMSES_ETH_BASE
++
++#ifndef __ASSEMBLY__
++#  define __CPLD_REG(x)               (*((volatile unsigned long *)CPLD_P2V(x)))
++#  define __CTRL_REG(x)         (*((volatile unsigned long *)CTRL_P2V(x)))
++#  define __CORE_REG(x)         (*((volatile unsigned long *)CORE_P2V(x)))
++#else
++#  define __CPLD_REG(x)               CPLD_P2V(x)
++#  define __CTRL_REG(x)               CTRL_P2V(x)
++#  define __CORE_REG(x)               CORE_P2V(x)
++#endif
++
++/* CPLD addresses */
++
++#define RAMSES_CPLD_PERIPH_PWR_               (RAMSES_CPLD_PHYS + 0x04)
++#define RAMSES_CPLD_PERIPH_PWR                __CPLD_REG(RAMSES_CPLD_PERIPH_PWR_)
++#define PER_RESET                     (1 << 4)
++#define PER_PWR_EN                    (1 << 3)
++#define USB_HOST_PWR_EN                       (1 << 2)
++#define CORE_VAR_EN                   (1 << 0)
++
++#define RAMSES_CPLD_LED_CONTROL_      (RAMSES_CPLD_PHYS + 0x08)
++#define RAMSES_CPLD_LED_CONTROL               __CPLD_REG(RAMSES_CPLD_LED_CONTROL_)
++#define CPLD_LED2                     (1 << 6)
++#define CPLD_LED1                     (1 << 5)
++#define GSM_ACTIVE                    (1 << 4)
++
++#define RAMSES_CPLD_KB_COL_HIGH_      (RAMSES_CPLD_PHYS + 0x0C)
++#define RAMSES_CPLD_KB_COL_HIGH               __CPLD_REG(RAMSES_CPLD_KB_COL_HIGH_)
++// kbch(7)..kbch(13) on bit 0..6
++
++#define RAMSES_CPLD_KB_COL_LOW_               (RAMSES_CPLD_PHYS + 0x10)
++#define RAMSES_CPLD_KB_COL_LOW                __CPLD_REG(RAMSES_CPLD_KB_COL_LOW_)
++// kbcl(0)..kbch(6) on bit 0..6
++
++#define RAMSES_CPLD_PCCARD_EN_                (RAMSES_CPLD_PHYS + 0x14)
++#define RAMSES_CPLD_PCCARD_EN         __CPLD_REG(RAMSES_CPLD_PCCARD_EN_)
++#define PCC1_RESET                    (1 << 7)
++#define PCC0_RESET                    (1 << 6)
++#define PCC1_ENABLE                   (1 << 1)
++#define PCC0_ENABLE                   (1 << 0)
++
++#define RAMSES_CPLD_PCCARD_PWR_               (RAMSES_CPLD_PHYS + 0x28)
++#define RAMSES_CPLD_PCCARD_PWR                __CPLD_REG(RAMSES_CPLD_PCCARD_PWR_)
++#define PCC1_PWR3                     (1 << 7)
++#define PCC1_PWR2                     (1 << 6)
++#define PCC1_PWR1                     (1 << 5)
++#define PCC1_PWR0                     (1 << 4)
++#define PCC0_PWR3                     (1 << 3)
++#define PCC0_PWR2                     (1 << 2)
++#define PCC0_PWR1                     (1 << 1)
++#define PCC0_PWR0                     (1 << 0)
++
++#define RAMSES_CPLD_MISC_CTRL_                (RAMSES_CPLD_PHYS + 0x2C)
++#define RAMSES_CPLD_MISC_CTRL         __CPLD_REG(RAMSES_CPLD_MISC_CTRL_)
++#define RAMSES_IRDA_MD1                       (1 << 5)
++#define RAMSES_IRDA_MD0                       (1 << 4)
++#define RAMSES_FIR                    (1 << 3)
++
++#define RAMSES_CPLD_LCD_              (RAMSES_CPLD_PHYS + 0x30)
++#define RAMSES_CPLD_LCD                       __CPLD_REG(RAMSES_CPLD_LCD_)
++#define RAMSES_LCD_PINC                       (1 << 7)
++#define RAMSES_LCD_PUP                        (1 << 6)
++#define RAMSES_LCD_PCS                        (1 << 5)
++#define RAMSES_LCD_DISPOFF            (1 << 2)
++#define RAMSES_LCD_VCC                        (1 << 0)
++
++#define RAMSES_CPLD_FLASH_WE_         (RAMSES_CPLD_PHYS + 0x34)
++#define RAMSES_CPLD_FLASH_WE          __CPLD_REG(RAMSES_CPLD_FLASH_WE_)
++#define RAMSES_FLASH_WE                       (1 << 0)
++
++/* Read-Only registers */
++
++#define RAMSES_CPLD_KB_ROW_           (RAMSES_CPLD_PHYS + 0x50)
++#define RAMSES_CPLD_KB_ROW            __CPLD_REG(RAMSES_CPLD_KB_ROW_)
++// kbr(0)..kbr(6) on bits 0..6
++
++#define RAMSES_CPLD_PCCARD0_STATUS_   (RAMSES_CPLD_PHYS + 0x54)
++#define RAMSES_CPLD_PCCARD0_STATUS    __CPLD_REG(RAMSES_CPLD_PCCARD0_STATUS_)
++#define RAMSES_CPLD_PCCARD1_STATUS_   (RAMSES_CPLD_PHYS + 0x58)
++#define RAMSES_CPLD_PCCARD1_STATUS    __CPLD_REG(RAMSES_CPLD_PCCARD1_STATUS_) 
++#define _PCC_WRPROT                   (1 << 7)
++#define _PCC_S16                      (1 << 7)
++#define _PCC_RESET                    (1 << 6)
++#define _PCC_IRQ                      (1 << 5)
++#define _PCC_INPACK                   (1 << 4)
++#define PCC_BVD2                      (1 << 3)
++#define PCC_BVD1                      (1 << 2)
++#define PCC_VS2                               (1 << 1)
++#define PCC_VS1                               (1 << 0)
++
++#define RAMSES_CPLD_MISC_STATUS_      (RAMSES_CPLD_PHYS + 0x5C)
++#define RAMSES_CPLD_MISC_STATUS               __CPLD_REG(RAMSES_CPLD_MISC_STATUS_)
++#define RAMSES_MMC_WRPROT             (1 << 7)
++#define RAMSES_USB_OVERCURR           (1 << 4)
++#define RAMSES_CHG_STS                        (1 << 2)
++#define RAMSES_WALL_IN                        (1 << 1)
++#define RAMSES_USB_D_CON              (1 << 0)
++
++#define RAMSES_CPLD_YEAR_             (RAMSES_CPLD_PHYS + 0x60)
++#define RAMSES_CPLD_YEAR              __CPLD_REG(RAMSES_CPLD_YEAR_)
++
++#define RAMSES_CPLD_MONTH_            (RAMSES_CPLD_PHYS + 0x64)
++#define RAMSES_CPLD_MONTH             __CPLD_REG(RAMSES_CPLD_MONTH_)
++
++#define RAMSES_CPLD_DAY_              (RAMSES_CPLD_PHYS + 0x68)
++#define RAMSES_CPLD_DAY                       __CPLD_REG(RAMSES_CPLD_DAY_)
++
++#define RAMSES_CPLD_REV_              (RAMSES_CPLD_PHYS + 0x6C)
++#define RAMSES_CPLD_REV                       __CPLD_REG(RAMSES_CPLD_REV_)
++
++#define RAMSES_CPLD_VSTAT_            (RAMSES_CPLD_PHYS + 0x7C)
++#define RAMSES_CPLD_VSTAT             __CPLD_REG(RAMSES_CPLD_VSTAT_)
++#define RAMSES_BWE                    (1 << 1)
++
++
++/* Flags for ramses_flags */
++
++#define RAMSES_FLAGS_LCD_FBTURN               (1<<0)
++/* MUST stay bit 0 */
++#define RAMSES_FLAGS_SCANNER_BEAM     (1<<1)
++#define RAMSES_FLAGS_KEY_SCAN         (1<<2)
++#define RAMSES_FLAGS_KEY_SUSPEND      (1<<3)
++#define RAMSES_FLAGS_KEY_OFF          (1<<4)
++
++
++/* Offset in SMC EEPROM for LCD type */
++#define RAMSES_LCD_TYPE_OFFSET                0x23
++
++
++/* The control register on the I/O board */
++
++#define RAMSES_CONTROL_                 (RAMSES_CONTROL_PHYS + 0)
++#define RAMSES_CONTROL                  __CTRL_REG(RAMSES_CONTROL_)
++// 5c00 = 0101 1100 0000 0000
++#define RAMSES_CONTROL_SCANNER_TRIG_  (1 << 15)
++#define RAMSES_CONTROL_SCANNER_WAKE_  (1 << 14)
++#define RAMSES_CONTROL_SCANNER_PWR    (1 << 13)
++#define RAMSES_CONTROL_LED_BLUE_      (1 << 12)
++
++#define RAMSES_CONTROL_LED_ORANGE_    (1 << 11)
++#define RAMSES_CONTROL_GSM_RESET      (1 << 10)
++#define RAMSES_CONTROL_GSM_BOOT               (1 << 9)
++#define RAMSES_CONTROL_GSM_PWR                (1 << 8)
++
++#define RAMSES_CONTROL_POWEROFF               (1 << 7)
++#define       RAMSES_CONTROL_USB_INTERN       (1 << 6)
++#define RAMSES_CONTROL_MMC_PWR                (1 << 5)
++#define RAMSES_CONTROL_UART_PWR               (1 << 4)
++
++#define RAMSES_CONTROL_LCD_BLIGHT     (1 << 3)
++#define RAMSES_CONTROL_USB            (1 << 2)
++
++#define RAMSES_POWER_OFF()        { ramses_control_shadow |=  RAMSES_CONTROL_POWEROFF;      RAMSES_CONTROL = ramses_control_shadow; }
++
++// Active low
++#define RAMSES_SCANNER_TRIG_ON()  { ramses_control_shadow &= ~RAMSES_CONTROL_SCANNER_TRIG_; RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_SCANNER_TRIG_OFF() { ramses_control_shadow |=  RAMSES_CONTROL_SCANNER_TRIG_; RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_SCANNER_WAKE_ON()  { ramses_control_shadow &= ~RAMSES_CONTROL_SCANNER_WAKE_; RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_SCANNER_WAKE_OFF() { ramses_control_shadow |=  RAMSES_CONTROL_SCANNER_WAKE_; RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_LED_BLUE_ON()      { ramses_control_shadow &= ~RAMSES_CONTROL_LED_BLUE_;     RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_LED_BLUE_OFF()     { ramses_control_shadow |=  RAMSES_CONTROL_LED_BLUE_;     RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_LED_ORANGE_ON()    { ramses_control_shadow &= ~RAMSES_CONTROL_LED_ORANGE_;   RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_LED_ORANGE_OFF()   { ramses_control_shadow |=  RAMSES_CONTROL_LED_ORANGE_;   RAMSES_CONTROL = ramses_control_shadow; }
++
++// Active high
++#define RAMSES_SCANNER_ON()       { ramses_control_shadow |=  RAMSES_CONTROL_SCANNER_PWR;   RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_SCANNER_OFF()      { ramses_control_shadow &= ~RAMSES_CONTROL_SCANNER_PWR;   RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_GSM_RESET_ON()     { ramses_control_shadow |=  RAMSES_CONTROL_GSM_RESET;     RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_GSM_RESET_OFF()    { ramses_control_shadow &= ~RAMSES_CONTROL_GSM_RESET;     RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_GSM_BOOT_ON()      { ramses_control_shadow |=  RAMSES_CONTROL_GSM_BOOT;      RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_GSM_BOOT_OFF()     { ramses_control_shadow &= ~RAMSES_CONTROL_GSM_BOOT;      RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_GSM_ON()           { ramses_control_shadow |=  RAMSES_CONTROL_GSM_PWR;       RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_GSM_OFF()          { ramses_control_shadow &= ~RAMSES_CONTROL_GSM_PWR;       RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_USB_INTERN()       { ramses_control_shadow |=  RAMSES_CONTROL_USB_INTERN;    RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_USB_EXTERN()       { ramses_control_shadow &= ~RAMSES_CONTROL_USB_INTERN;    RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_UART_ON()          { ramses_control_shadow |=  RAMSES_CONTROL_UART_PWR;      RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_UART_OFF()         { ramses_control_shadow &= ~RAMSES_CONTROL_UART_PWR;      RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_MMC_ON()           { ramses_control_shadow |=  RAMSES_CONTROL_MMC_PWR;       RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_MMC_OFF()          { ramses_control_shadow &= ~RAMSES_CONTROL_MMC_PWR;       RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_LCD_BLIGHT_ON()    { ramses_control_shadow |=  RAMSES_CONTROL_LCD_BLIGHT;    RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_LCD_BLIGHT_OFF()   { ramses_control_shadow &= ~RAMSES_CONTROL_LCD_BLIGHT;    RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_USB_BUS_ON()       { ramses_control_shadow |=  RAMSES_CONTROL_USB;           RAMSES_CONTROL = ramses_control_shadow; }
++#define RAMSES_USB_BUS_OFF()      { ramses_control_shadow &= ~RAMSES_CONTROL_USB;           RAMSES_CONTROL = ramses_control_shadow; }
++
++// Corevolt settings
++#define RAMSES_COREVOLT_          (RAMSES_COREVOLT_PHYS)
++#define RAMSES_COREVOLT           __CORE_REG(RAMSES_COREVOLT_)
++
++// Battery protocol
++#define HDQ_TMP               0x02
++#define HDQ_LMD               0x05
++#define HDQ_VSB               0x0b
++#define HDQ_CACT      0x0d
++#define HDQ_SAEH      0x0f
++#define HDQ_SAEL      0x10
++#define HDQ_RCAC      0x11
++#define HDQ_DCR               0x18
++
++
++#ifndef __ASSEMBLY__
++
++/* Ramses specific functions */
++void ramses_lcd_power_on(void);
++void ramses_lcd_power_off(void);
++void ramses_lcd_backlight_on(void);
++void ramses_lcd_backlight_off(void);
++void ramses_lcd_set_intensity(int i);
++#ifdef OLDCODE
++void ramses_lcd_set_pwm1(int p);
++#endif
++void ramses_lcd_set_brightness(int b);
++void ramses_lcd_set_contrast(int c);
++int ramses_lcd_get_intensity(void);
++int ramses_lcd_get_brightness(void);
++int ramses_lcd_get_contrast(void);
++int ramses_hdq_get_reg(unsigned char reg);
++void ramses_shut_off(void);
++void ramses_set_corevolt(int volt);
++
++
++/* shadow registers for write only registers */
++extern u16 ramses_control_shadow;
++extern int ramses_corevolt_shadow;
++extern u16 ramses_lcd_type;
++extern int ramses_lcd_pwm1_shadow;
++
++
++/* flag register for various settings */
++extern unsigned int ramses_flags;
++
++/* 
++ * macros to write to write only register
++ *
++ * none of these macros are protected from 
++ * multiple drivers using them in interrupt context.
++ */
++
++#define WRITE_RAMSES_CONTROL(value, mask) \
++{\
++      ramses_control_shadow = ((value & mask) | (ramses_control_shadow & ~mask));\
++      RAMSES_CONTROL = ramses_control_shadow;\
++}
++#endif
++
++/*
++ *  USB Host
++ *
++ *  The SL811HS is selected with nCS3 and some address bits:
++ *
++ *                               12    8    4
++ *  nA14, nCS[3], address mask 1011 1111 1111 0000 = xBf00
++ */
++#define SL811HS_PHYS (PXA_CS3_PHYS+0xBFF0)
++#define SL811HS_DATA (PXA_CS3_PHYS+0xBFF4)
++
++
++
++
++
++
++
++#define PCC_DETECT(x) (GPLR(7 + (x)) & GPIO_bit(7 + (x)))
++
++
++
++
++
++/* A listing of interrupts used by external hardware devices */
++
++#define TOUCH_PANEL_IRQ                       IRQ_GPIO(21)
++#define TOUCH_PANEL_IRQ_EDGE          GPIO_FALLING_EDGE
++
++#define ETHERNET_IRQ                  IRQ_GPIO(4)
++#define ETHERNET_IRQ_EDGE             GPIO_RISING_EDGE
++
++#define CFCARD_CD_VALID                       IRQ_GPIO(8)
++#define CFCARD_CD_VALID_EDGE          GPIO_BOTH_EDGES
++
++#define CFCARD_RDYINT                 IRQ_GPIO(22)
++
++#define RAMSES_KEYBOARD_IRQ           IRQ_GPIO(3)
++#define RAMSES_KEYBOARD_IRQ_EDGE      GPIO_FALLING_EDGE
++
++#define SL811HS_IRQ                   IRQ_GPIO(32)
++#define SL811HS_IRQ_EDGE              GPIO_RISING_EDGE
++
++/*
++ * Macros for LED Driver
++ */
++
++/* leds 0 = ON */
++#define RAMSES_HB_LED (1<<5)  
++#define RAMSES_BUSY_LED       (1<<6)
++
++#define RAMSES_LEDS_MASK              (RAMSES_HB_LED | RAMSES_BUSY_LED)
++
++#define RAMSES_WRITE_LEDS(value)      (RAMSES_CPLD_LED_CONTROL = ((RAMSES_CPLD_LED_CONTROL & ~(RAMSES_LEDS_MASK)) | value))
++
++/*
++ * macros for MTD driver
++ */
++
++#define FLASH_WRITE_PROTECT_DISABLE() ((RAMSES_CPLD_FLASH_WE) &= ~(0x1))
++#define FLASH_WRITE_PROTECT_ENABLE()  ((RAMSES_CPLD_FLASH_WE) |= (0x1))
++
++
+--- linux-2.4.21/include/asm-arm/arch-pxa/time.h~pxa-timerint
++++ linux-2.4.21/include/asm-arm/arch-pxa/time.h
+@@ -33,7 +33,7 @@
+ /* IRQs are disabled before entering here from do_gettimeofday() */
+ static unsigned long pxa_gettimeoffset (void)
+ {
+-      unsigned long ticks_to_match, elapsed, usec;
++      long ticks_to_match, elapsed, usec;
+       /* Get ticks before next timer match */
+       ticks_to_match = OSMR0 - OSCR;
+@@ -41,6 +41,10 @@
+       /* We need elapsed ticks since last match */
+       elapsed = LATCH - ticks_to_match;
++      /* don't get fooled by the workaround in pxa_timer_interrupt() */
++      if (elapsed <= 0)
++              return 0;
++
+       /* Now convert them to usec */
+       usec = (unsigned long)(elapsed*tick)/LATCH;
+@@ -59,6 +63,15 @@
+        * IRQs are disabled inside the loop to ensure coherence between
+        * lost_ticks (updated in do_timer()) and the match reg value, so we
+        * can use do_gettimeofday() from interrupt handlers.
++       *
++       * HACK ALERT: it seems that the PXA timer regs aren't updated right
++       * away in all cases when a write occurs.  We therefore compare with
++       * 8 instead of 0 in the while() condition below to avoid missing a
++       * match if OSCR has already reached the next OSMR value.
++       * Experience has shown that up to 6 ticks are needed to work around
++       * this problem, but let's use 8 to be conservative.  Note that this
++       * affect things only when the timer IRQ has been delayed by nearly
++       * exactly one tick period which should be a pretty rare event. 
+        */
+       do {
+               do_leds();
+@@ -68,7 +81,7 @@
+               OSSR = OSSR_M0;  /* Clear match on timer 0 */
+               next_match = (OSMR0 += LATCH);
+               restore_flags( flags );
+-      } while( (signed long)(next_match - OSCR) <= 0 );
++      } while( (signed long)(next_match - OSCR) <= 8 );
+ }
+ extern inline void setup_timer (void)
+--- /dev/null
++++ linux-2.4.21/include/asm-arm/sl811-hw.h
+@@ -0,0 +1,202 @@
++/*
++File: include/asm-arm/sl811-hw.h
++
++19.09.2003 hne@ist1.de
++Use Kernel 2.4.20 and this source from 2.4.22
++Splitt hardware depens into file sl811-x86.h and sl811-arm.h.
++Functions as inline.
++
++23.09.2003 hne
++Move Hardware depend header sl811-arm.h into include/asm-arm/sl811-hw.h.
++GPRD as parameter.
++
++24.09.2003 hne
++Use Offset from ADDR to DATA instand of direct io.
++
++03.10.2003 hne
++Low level only for port io into hardware-include.
++*/
++
++#ifndef __LINUX_SL811_HW_H
++#define __LINUX_SL811_HW_H
++
++#ifdef CONFIG_X86
++#define MAX_CONTROLERS                1       /* Max number of sl811 controllers */
++                                      /* Always 1 for this architecture! */
++
++#define SIZEOF_IO_REGION      1       /* Size for request/release region */
++
++#define OFFSET_DATA_REG data_off      /* Offset from ADDR_IO to DATA_IO (future) */
++                                      /* Can change by arg */
++
++static int io = 0xf100000e;   /* Base addr_io */
++static int data_off = 1;      /* Offset from addr_io to addr_io */
++static int irq = 44;          /* also change gprd !!! */
++static int gprd = 23;         /* also change irq  !!! */
++
++MODULE_PARM(io,"i");
++MODULE_PARM_DESC(io,"sl811 address io port 0xf100000e");
++MODULE_PARM(data_off,"i");
++MODULE_PARM_DESC(data_off,"sl811 data io port offset from address port (default 1)");
++MODULE_PARM(irq,"i");
++MODULE_PARM_DESC(irq,"sl811 irq 44(default)");
++MODULE_PARM(gprd,"i");
++MODULE_PARM_DESC(gprd,"sl811 GPRD port 23(default)");
++#endif
++
++#ifdef CONFIG_ARCH_RAMSES
++#define SIZEOF_IO_REGION        8       /* Size for request/release region */
++static void *ramses_sl811hs;            /* dynamically assign virtual address */
++#endif
++
++
++/*
++ * Low level: Read from Data port [arm]
++ */
++static __u8 inline sl811_read_data (struct sl811_hc *hc)
++{
++      __u8 data;
++      data = readb(hc->data_io);
++      rmb();
++//printk("%s: in  %08p %02x\n", __FUNCTION__, hc->data_io, data);
++      return data;
++}
++
++/*
++ * Low level: Write to index register [arm]
++ */
++static void inline sl811_write_index (struct sl811_hc *hc, __u8 index)
++{
++//printk("%s: out %08p %02x\n", __FUNCTION__, hc->addr_io, index);
++      writeb(index, hc->addr_io);
++      wmb();
++}
++
++/*
++ * Low level: Write to Data port [arm]
++ */
++static void inline sl811_write_data (struct sl811_hc *hc, __u8 data)
++{
++//printk("%s: out %08p %02x\n", __FUNCTION__, hc->data_io, data);
++      writeb(data, hc->data_io);
++      wmb();
++}
++
++/*
++ * Low level: Write to index register and data port [arm]
++ */
++static void inline sl811_write_index_data (struct sl811_hc *hc, __u8 index, __u8 data)
++{
++      writeb(index, hc->addr_io);
++//printk("%s: out %08p %02x\n", __FUNCTION__, hc->addr_io, index);
++      writeb(data, hc->data_io);
++//printk("%s: out %08p %02x\n", __FUNCTION__, hc->data_io, data);
++      wmb();
++}
++
++
++/*
++ * This       function is board specific.  It sets up the interrupt to
++ * be an edge trigger and trigger on the rising       edge
++ */
++static void inline sl811_init_irq(void)
++{
++#ifdef CONFIG_X86
++      GPDR &= ~(1<<gprd);
++      set_GPIO_IRQ_edge(1<<gprd, GPIO_RISING_EDGE);
++#endif
++#ifdef CONFIG_ARCH_PXA
++      int irq_gpio_pin = IRQ_TO_GPIO_2_80(SL811HS_IRQ);
++      GPDR(irq_gpio_pin) &= ~GPIO_bit(irq_gpio_pin);
++      set_GPIO_IRQ_edge(irq_gpio_pin, SL811HS_IRQ_EDGE);
++#endif
++}
++
++/*****************************************************************
++ *
++ * Function Name: release_regions [arm]
++ *
++ * This function is board specific. It release all io address
++ * from memory (if can).
++ *
++ * Input: struct sl811_hc * *
++ *
++ * Return value  : 0 = OK
++ *
++ *****************************************************************/
++static void inline sl811_release_regions(struct sl811_hc *hc)
++{
++#ifdef CONFIG_X86
++      if (hc->addr_io)
++              release_region(hc->addr_io, SIZEOF_IO_REGION);
++      hc->addr_io = 0;
++
++      if (hc->data_io)
++              release_region(hc->data_io, SIZEOF_IO_REGION);
++      hc->data_io = 0;
++#endif
++#ifdef CONFIG_ARCH_RAMSES
++      if (ramses_sl811hs) {
++              iounmap(ramses_sl811hs);
++              release_mem_region(SL811HS_PHYS, SIZEOF_IO_REGION);
++      }
++      hc->addr_io = 0;
++      hc->data_io = 0;
++      RAMSES_CPLD_PERIPH_PWR &= ~USB_HOST_PWR_EN;
++      RAMSES_USB_BUS_OFF();
++#endif
++}
++
++/*****************************************************************
++ *
++ * Function Name: request_regions [arm]
++ *
++ * This function is board specific. It request all io address and
++ * maps into memory (if can).
++ *
++ * Input: struct sl811_hc *
++ *
++ * Return value  : 0 = OK
++ *
++ *****************************************************************/
++static int inline sl811_request_regions (struct sl811_hc *hc, int addr_io, int data_io, const char *name)
++{
++#ifdef CONFIG_X86
++      if (!request_region(addr_io, SIZEOF_IO_REGION, name)) {
++              PDEBUG(3, "request address %d failed", addr_io);
++              return -EBUSY;
++      }
++      hc->addr_io =   addr_io;
++
++      if (!request_region(data_io, SIZEOF_IO_REGION, MODNAME)) {
++              PDEBUG(3, "request address %d failed", data_io);
++              /* release_region(hc->addr_io, SIZEOF_IO_REGION); */
++              return -EBUSY;
++      }
++      hc->data_io =   data_io;
++#endif
++#ifdef CONFIG_ARCH_RAMSES
++      RAMSES_USB_BUS_ON();
++      RAMSES_CPLD_PERIPH_PWR |= USB_HOST_PWR_EN;
++      mdelay(300);
++
++        if (!request_mem_region(SL811HS_PHYS, SIZEOF_IO_REGION, name)) {
++                printk(KERN_ERR "unable to reserve region\n");
++                return -EBUSY;
++        } else {
++                ramses_sl811hs = ioremap_nocache(SL811HS_PHYS, SIZEOF_IO_REGION);
++              dbg("phys %p -> virt %p\n", SL811HS_PHYS, ramses_sl811hs);
++                if (!ramses_sl811hs) {
++                        printk(KERN_ERR "unable to map region\n");
++                        release_mem_region(SL811HS_PHYS, SIZEOF_IO_REGION);
++                        return -EBUSY;
++                }
++        }
++        hc->addr_io = (unsigned long) ramses_sl811hs;
++        hc->data_io = (unsigned long) ramses_sl811hs+4;
++#endif
++
++      return 0;
++}
++
++#endif // __LINUX_SL811_HW_H
+--- linux-2.4.21/include/linux/apm_bios.h~pm
++++ linux-2.4.21/include/linux/apm_bios.h
+@@ -16,6 +16,8 @@
+  * General Public License for more details.
+  */
++#include <linux/pm-devices.h>
++
+ typedef unsigned short        apm_event_t;
+ typedef unsigned short        apm_eventinfo_t;
+@@ -59,6 +61,16 @@
+ };
+ /*
++ * Allow device specific code to register function which
++ * gets the battery power status (see arch/arm/mach-pxa/apm.c).
++ */
++extern void apm_register_get_power_status( int (*fn)(u_char *ac_line_status,
++                              u_char *battery_status,
++                              u_char *battery_flag,
++                              u_char *battery_percentage,
++                              u_short *battery_life));
++
++/*
+  * The APM function codes
+  */
+ #define       APM_FUNC_INST_CHECK     0x5300
+@@ -168,6 +180,7 @@
+ /*
+  * APM Device IDs
+  */
++#ifdef _i386_
+ #define APM_DEVICE_BIOS               0x0000
+ #define APM_DEVICE_ALL                0x0001
+ #define APM_DEVICE_DISPLAY    0x0100
+@@ -181,6 +194,21 @@
+ #define APM_DEVICE_OLD_ALL    0xffff
+ #define APM_DEVICE_CLASS      0x00ff
+ #define APM_DEVICE_MASK               0xff00
++#endif
++
++/*
++ *  APM devices IDs for non-x86
++ */
++#define APM_DEVICE_ALL                PM_SYS_DEV
++#define APM_DEVICE_DISPLAY    PM_DISPLAY_DEV
++#define APM_DEVICE_STORAGE    PM_STORAGE_DEV
++#define APM_DEVICE_PARALLEL   PM_PARALLEL_DEV
++#define APM_DEVICE_SERIAL     PM_SERIAL_DEV
++#define APM_DEVICE_NETWORK    PM_NETWORK_DEV
++#define APM_DEVICE_PCMCIA     PM_PCMCIA_DEV
++#define APM_DEVICE_BATTERY    PM_BATTERY_DEV
++#define APM_DEVICE_TPANEL     PM_TPANEL_DEV
++
+ #ifdef __KERNEL__
+ /*
+@@ -214,5 +242,6 @@
+ #define APM_IOC_STANDBY               _IO('A', 1)
+ #define APM_IOC_SUSPEND               _IO('A', 2)
++#define APM_IOC_SET_WAKEUP    _IO('A', 3)
+ #endif        /* LINUX_APM_H */
+--- linux-2.4.21/include/linux/i2c-id.h~i2c-ds1337
++++ linux-2.4.21/include/linux/i2c-id.h
+@@ -95,13 +95,14 @@
+ #define I2C_DRIVERID_ADV717x  48     /* ADV 7175/7176 video encoder   */
+ #define I2C_DRIVERID_ZR36067  49     /* Zoran 36067 video encoder     */
+ #define I2C_DRIVERID_ZR36120  50     /* Zoran 36120 video encoder     */
+-#define I2C_DRIVERID_24LC32A  51              /* Microchip 24LC32A 32k EEPROM */
++#define I2C_DRIVERID_24LC32A  51     /* Microchip 24LC32A 32k EEPROM  */
++#define I2C_DRIVERID_DS1337     52     /* DS1337 real time clock        */
+-#define I2C_DRIVERID_DS1307   46      /* real time clock: DS1307      */
+-#define I2C_DRIVERID_24LC64   47      /* EEprom 24LC64                */
+-#define I2C_DRIVERID_FM24CLB4 48      /* EEprom FM24CLB4              */
++//#define I2C_DRIVERID_DS1307 46      /* real time clock: DS1307      */
++//#define I2C_DRIVERID_24LC64 47      /* EEprom 24LC64                */
++//#define I2C_DRIVERID_FM24CLB4       48      /* EEprom FM24CLB4              */
+ #define I2C_DRIVERID_EXP0     0xF0    /* experimental use id's        */
+ #define I2C_DRIVERID_EXP1     0xF1
+--- /dev/null
++++ linux-2.4.21/include/linux/pm-devices.h
+@@ -0,0 +1,41 @@
++#ifndef _LINUX_PM_DEV_H
++#define _LINUX_PM_DEV_H
++
++/*
++ * Copyright 2002 Montavista Software (mlocke@mvista.com)
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2, 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.
++ */
++
++
++
++/*
++ * Device types
++ */
++enum
++{
++        PM_UNKNOWN_DEV = 0, /* generic */
++        PM_SYS_DEV,         /* system device (fan, KB controller, ...) */
++        PM_PCI_DEV,         /* PCI device */
++        PM_USB_DEV,         /* USB device */
++        PM_SCSI_DEV,        /* SCSI device */
++        PM_ISA_DEV,         /* ISA device */
++        PM_MTD_DEV,         /* Memory Technology Device */
++      PM_TPANEL_DEV,      /* Memory Technology Device */
++        PM_STORAGE_DEV,      /* Memory Technology Device */
++        PM_NETWORK_DEV,      /* Memory Technology Device */
++        PM_PCMCIA_DEV,      /* Memory Technology Device */
++        PM_DISPLAY_DEV,      /* Memory Technology Device */
++        PM_SERIAL_DEV,      /* Memory Technology Device */
++        PM_BATTERY_DEV,      /* Memory Technology Device */
++};
++
++#endif
+--- linux-2.4.21/include/linux/pm.h~pm
++++ linux-2.4.21/include/linux/pm.h
+@@ -24,6 +24,7 @@
+ #ifdef __KERNEL__
+ #include <linux/config.h>
++#include <linux/pm-devices.h>
+ #include <linux/list.h>
+ /*
+@@ -49,20 +50,6 @@
+ };
+ typedef int pm_request_t;
+-
+-/*
+- * Device types
+- */
+-enum
+-{
+-      PM_UNKNOWN_DEV = 0, /* generic */
+-      PM_SYS_DEV,         /* system device (fan, KB controller, ...) */
+-      PM_PCI_DEV,         /* PCI device */
+-      PM_USB_DEV,         /* USB device */
+-      PM_SCSI_DEV,        /* SCSI device */
+-      PM_ISA_DEV,         /* ISA device */
+-      PM_MTD_DEV,         /* Memory Technology Device */
+-};
+ typedef int pm_dev_t;
+--- linux-2.4.21/include/linux/soundcard.h~ucb1x00
++++ linux-2.4.21/include/linux/soundcard.h
+@@ -811,6 +811,7 @@
+ #define SOUND_MIXER_STEREODEVS        0xfb    /* Mixer channels supporting stereo */
+ #define SOUND_MIXER_OUTSRC    0xfa    /* Arg contains a bit for each input source to output */
+ #define SOUND_MIXER_OUTMASK   0xf9    /* Arg contains a bit for each supported input source to output */
++#define SOUND_MIXER_AC97      0xf8    /* directly access ac97 registers */
+ /*    Device mask bits        */
+@@ -874,6 +875,7 @@
+ #define SOUND_MIXER_READ_RECMASK      MIXER_READ(SOUND_MIXER_RECMASK)
+ #define SOUND_MIXER_READ_STEREODEVS   MIXER_READ(SOUND_MIXER_STEREODEVS)
+ #define SOUND_MIXER_READ_CAPS         MIXER_READ(SOUND_MIXER_CAPS)
++#define SOUND_MIXER_READ_AC97         MIXER_READ(SOUND_MIXER_AC97)
+ #define MIXER_WRITE(dev)              _SIOWR('M', dev, int)
+ #define SOUND_MIXER_WRITE_VOLUME      MIXER_WRITE(SOUND_MIXER_VOLUME)
+@@ -900,6 +902,7 @@
+ #define SOUND_MIXER_WRITE_LOUD                MIXER_WRITE(SOUND_MIXER_LOUD)
+ #define SOUND_MIXER_WRITE_RECSRC      MIXER_WRITE(SOUND_MIXER_RECSRC)
++#define SOUND_MIXER_WRITE_AC97                MIXER_WRITE(SOUND_MIXER_AC97)
+ typedef struct mixer_info
+ {
+--- linux-2.4.21/include/linux/tty.h~ramses-lcd
++++ linux-2.4.21/include/linux/tty.h
+@@ -10,8 +10,8 @@
+  * resizing).
+  */
+ #define MIN_NR_CONSOLES 1       /* must be at least 1 */
+-#define MAX_NR_CONSOLES       63      /* serial lines start at 64 */
+-#define MAX_NR_USER_CONSOLES 63       /* must be root to allocate above this */
++#define MAX_NR_CONSOLES       3       /* serial lines start at 64 */
++#define MAX_NR_USER_CONSOLES 3        /* must be root to allocate above this */
+               /* Note: the ioctl VT_GETSTATE does not work for
+                  consoles 16 and higher (since it returns a short) */
+--- linux-2.4.21/include/linux/usb.h~ramses-usb
++++ linux-2.4.21/include/linux/usb.h
+@@ -1079,7 +1079,7 @@
+ void usb_show_string(struct usb_device *dev, char *id, int index);
+ #ifdef DEBUG
+-#define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg)
++#define dbg(format, arg...) printk(__FILE__ ": " format "\n" , ## arg)
+ #else
+ #define dbg(format, arg...) do {} while (0)
+ #endif
+--- linux-2.4.21/include/linux/wireless.h~linux-iw241_we16-6
++++ linux-2.4.21/include/linux/wireless.h
+@@ -1,7 +1,7 @@
+ /*
+  * This file define a set of standard wireless extensions
+  *
+- * Version :  15      12.7.02
++ * Version :  16      2.4.03
+  *
+  * Authors :  Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+  * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
+@@ -69,6 +69,8 @@
+ /***************************** INCLUDES *****************************/
++/* To minimise problems in user space, I might remove those headers
++ * at some point. Jean II */
+ #include <linux/types.h>              /* for "caddr_t" et al          */
+ #include <linux/socket.h>             /* for "struct sockaddr" et al  */
+ #include <linux/if.h>                 /* for IFNAMSIZ and co... */
+@@ -80,7 +82,7 @@
+  * (there is some stuff that will be added in the future...)
+  * I just plan to increment with each new version.
+  */
+-#define WIRELESS_EXT  15
++#define WIRELESS_EXT  16
+ /*
+  * Changes :
+@@ -163,6 +165,16 @@
+  *    - Add IW_TXPOW_RANGE for range of Tx Powers
+  *    - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
+  *    - Add IW_MODE_MONITOR for passive monitor
++ *
++ * V15 to V16
++ * ----------
++ *    - Increase the number of bitrates in iw_range to 32 (for 802.11g)
++ *    - Increase the number of frequencies in iw_range to 32 (for 802.11b+a)
++ *    - Reshuffle struct iw_range for increases, add filler
++ *    - Increase IW_MAX_AP to 64 for driver returning a lot of addresses
++ *    - Remove IW_MAX_GET_SPY because conflict with enhanced spy support
++ *    - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
++ *    - Add IW_ENCODE_TEMP and iw_range->encoding_login_index
+  */
+ /**************************** CONSTANTS ****************************/
+@@ -196,9 +208,11 @@
+ /* SIOCGIWSTATS is strictly used between user space and the kernel, and
+  * is never passed to the driver (i.e. the driver will never see it). */
+-/* Mobile IP support (statistics per MAC address) */
++/* Spy support (statistics per MAC address - used for Mobile IP support) */
+ #define SIOCSIWSPY    0x8B10          /* set spy addresses */
+ #define SIOCGIWSPY    0x8B11          /* get spy info (quality of link) */
++#define SIOCSIWTHRSPY 0x8B12          /* set spy threshold (spy event) */
++#define SIOCGIWTHRSPY 0x8B13          /* get spy threshold */
+ /* Access Point manipulation */
+ #define SIOCSIWAP     0x8B14          /* set access point MAC addresses */
+@@ -294,7 +308,7 @@
+ #define IW_PRIV_TYPE_FLOAT    0x5000  /* struct iw_freq */
+ #define IW_PRIV_TYPE_ADDR     0x6000  /* struct sockaddr */
+-#define IW_PRIV_SIZE_FIXED    0x0800  /* Variable or fixed nuber of args */
++#define IW_PRIV_SIZE_FIXED    0x0800  /* Variable or fixed number of args */
+ #define IW_PRIV_SIZE_MASK     0x07FF  /* Max number of those args */
+@@ -306,13 +320,13 @@
+ /* ----------------------- OTHER CONSTANTS ----------------------- */
+ /* Maximum frequencies in the range struct */
+-#define IW_MAX_FREQUENCIES    16
++#define IW_MAX_FREQUENCIES    32
+ /* Note : if you have something like 80 frequencies,
+  * don't increase this constant and don't fill the frequency list.
+  * The user will be able to set by channel anyway... */
+ /* Maximum bit rates in the range struct */
+-#define IW_MAX_BITRATES               8
++#define IW_MAX_BITRATES               32
+ /* Maximum tx powers in the range struct */
+ #define IW_MAX_TXPOWER                8
+@@ -320,8 +334,7 @@
+  * a few of them in the struct iw_range. */
+ /* Maximum of address that you may set with SPY */
+-#define IW_MAX_SPY            8       /* set */
+-#define IW_MAX_GET_SPY                64      /* get */
++#define IW_MAX_SPY            8
+ /* Maximum of address that you may get in the
+    list of access points in range */
+@@ -354,7 +367,8 @@
+ #define IW_ENCODE_ENABLED     0x0000  /* Encoding enabled */
+ #define IW_ENCODE_RESTRICTED  0x4000  /* Refuse non-encoded packets */
+ #define IW_ENCODE_OPEN                0x2000  /* Accept non-encoded packets */
+-#define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not present */
++#define IW_ENCODE_NOKEY               0x0800  /* Key is write only, so not present */
++#define IW_ENCODE_TEMP                0x0400  /* Temporary key */
+ /* Power management flags available (along with the value, if any) */
+ #define IW_POWER_ON           0x0000  /* No details... */
+@@ -482,6 +496,17 @@
+       __u32           beacon;         /* Missed beacons/superframe */
+ };
++/*
++ *    Quality range (for spy threshold)
++ */
++struct        iw_thrspy
++{
++      struct sockaddr         addr;           /* Source address (hw/mac) */
++      struct iw_quality       qual;           /* Quality of the link */
++      struct iw_quality       low;            /* Low threshold */
++      struct iw_quality       high;           /* High threshold */
++};
++
+ /* ------------------------ WIRELESS STATS ------------------------ */
+ /*
+  * Wireless statistics (used for /proc/net/wireless)
+@@ -534,7 +559,7 @@
+       struct iw_quality qual;         /* Quality part of statistics */
+       struct sockaddr ap_addr;        /* Access point address */
+-      struct sockaddr addr;           /* Destination address (hw) */
++      struct sockaddr addr;           /* Destination address (hw/mac) */
+       struct iw_param param;          /* Other small parameters */
+       struct iw_point data;           /* Other large parameters */
+@@ -582,17 +607,31 @@
+       __u32           min_nwid;       /* Minimal NWID we are able to set */
+       __u32           max_nwid;       /* Maximal NWID we are able to set */
+-      /* Frequency */
+-      __u16           num_channels;   /* Number of channels [0; num - 1] */
+-      __u8            num_frequency;  /* Number of entry in the list */
+-      struct iw_freq  freq[IW_MAX_FREQUENCIES];       /* list */
+-      /* Note : this frequency list doesn't need to fit channel numbers */
++      /* Old Frequency (backward compat - moved lower ) */
++      __u16           old_num_channels;
++      __u8            old_num_frequency;
++      /* Filler to keep "version" at the same offset */
++      __s32           old_freq[6];
+       /* signal level threshold range */
+       __s32   sensitivity;
+       /* Quality of link & SNR stuff */
++      /* Quality range (link, level, noise)
++       * If the quality is absolute, it will be in the range [0 ; max_qual],
++       * if the quality is dBm, it will be in the range [max_qual ; 0].
++       * Don't forget that we use 8 bit arithmetics... */
+       struct iw_quality       max_qual;       /* Quality of the link */
++      /* This should contain the average/typical values of the quality
++       * indicator. This should be the threshold between a "good" and
++       * a "bad" link (example : monitor going from green to orange).
++       * Currently, user space apps like quality monitors don't have any
++       * way to calibrate the measurement. With this, they can split
++       * the range between 0 and max_qual in different quality level
++       * (using a geometric subdivision centered on the average).
++       * I expect that people doing the user space apps will feedback
++       * us on which value we need to put in each driver... */
++      struct iw_quality       avg_qual;       /* Quality of the link */
+       /* Rates */
+       __u8            num_bitrates;   /* Number of entries in the list */
+@@ -619,6 +658,8 @@
+       __u16   encoding_size[IW_MAX_ENCODING_SIZES];   /* Different token sizes */
+       __u8    num_encoding_sizes;     /* Number of entry in the list */
+       __u8    max_encoding_tokens;    /* Max number of tokens */
++      /* For drivers that need a "login/passwd" form */
++      __u8    encoding_login_index;   /* token index for login token */
+       /* Transmit power */
+       __u16           txpower_capa;   /* What options are supported */
+@@ -638,18 +679,12 @@
+       __s32           min_r_time;     /* Minimal retry lifetime */
+       __s32           max_r_time;     /* Maximal retry lifetime */
+-      /* Average quality of link & SNR */
+-      struct iw_quality       avg_qual;       /* Quality of the link */
+-      /* This should contain the average/typical values of the quality
+-       * indicator. This should be the threshold between a "good" and
+-       * a "bad" link (example : monitor going from green to orange).
+-       * Currently, user space apps like quality monitors don't have any
+-       * way to calibrate the measurement. With this, they can split
+-       * the range between 0 and max_qual in different quality level
+-       * (using a geometric subdivision centered on the average).
+-       * I expect that people doing the user space apps will feedback
+-       * us on which value we need to put in each driver...
+-       */
++      /* Frequency */
++      __u16           num_channels;   /* Number of channels [0; num - 1] */
++      __u8            num_frequency;  /* Number of entry in the list */
++      struct iw_freq  freq[IW_MAX_FREQUENCIES];       /* list */
++      /* Note : this frequency list doesn't need to fit channel numbers,
++       * because each entry contain its channel index */
+ };
+ /*
+--- linux-2.4.21/include/net/iw_handler.h~linux-iw241_we16-6
++++ linux-2.4.21/include/net/iw_handler.h
+@@ -1,7 +1,7 @@
+ /*
+  * This file define the new driver API for Wireless Extensions
+  *
+- * Version :  4       21.6.02
++ * Version :  5       4.12.02
+  *
+  * Authors :  Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+  * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved.
+@@ -206,7 +206,7 @@
+  * will be needed...
+  * I just plan to increment with each new version.
+  */
+-#define IW_HANDLER_VERSION    4
++#define IW_HANDLER_VERSION    5
+ /*
+  * Changes :
+@@ -220,10 +220,18 @@
+  * V3 to V4
+  * --------
+  *    - Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes
++ *
++ * V4 to V5
++ * --------
++ *    - Add new spy support : struct iw_spy_data & prototypes
+  */
+ /**************************** CONSTANTS ****************************/
++/* Enable enhanced spy support. Disable to reduce footprint */
++#define IW_WIRELESS_SPY
++#define IW_WIRELESS_THRSPY
++
+ /* Special error message for the driver to indicate that we
+  * should do a commit after return from the iw_handler */
+ #define EIWCOMMIT     EINPROGRESS
+@@ -315,6 +323,9 @@
+        * We will automatically export that to user space... */
+       struct iw_priv_args *   private_args;
++      /* Driver enhanced spy support */
++      long                    spy_offset;     /* Spy data offset */
++
+       /* In the long term, get_wireless_stats will move from
+        * 'struct net_device' to here, to minimise bloat. */
+ };
+@@ -350,6 +361,33 @@
+ /* Need to think of short header translation table. Later. */
++/* --------------------- ENHANCED SPY SUPPORT --------------------- */
++/*
++ * In the old days, the driver was handling spy support all by itself.
++ * Now, the driver can delegate this task to Wireless Extensions.
++ * It needs to include this struct in its private part and use the
++ * standard spy iw_handler.
++ */
++
++/*
++ * Instance specific spy data, i.e. addresses spied and quality for them.
++ */
++struct iw_spy_data
++{
++#ifdef IW_WIRELESS_SPY
++      /* --- Standard spy support --- */
++      int                     spy_number;
++      u_char                  spy_address[IW_MAX_SPY][ETH_ALEN];
++      struct iw_quality       spy_stat[IW_MAX_SPY];
++#ifdef IW_WIRELESS_THRSPY
++      /* --- Enhanced spy support (event) */
++      struct iw_quality       spy_thr_low;    /* Low threshold */
++      struct iw_quality       spy_thr_high;   /* High threshold */
++      u_char                  spy_thr_under[IW_MAX_SPY];
++#endif /* IW_WIRELESS_THRSPY */
++#endif /* IW_WIRELESS_SPY */
++};
++
+ /**************************** PROTOTYPES ****************************/
+ /*
+  * Functions part of the Wireless Extensions (defined in net/core/wireless.c).
+@@ -375,6 +413,31 @@
+ /* We may need a function to send a stream of events to user space.
+  * More on that later... */
++
++/* Standard handler for SIOCSIWSPY */
++extern int iw_handler_set_spy(struct net_device *     dev,
++                            struct iw_request_info *  info,
++                            union iwreq_data *        wrqu,
++                            char *                    extra);
++/* Standard handler for SIOCGIWSPY */
++extern int iw_handler_get_spy(struct net_device *     dev,
++                            struct iw_request_info *  info,
++                            union iwreq_data *        wrqu,
++                            char *                    extra);
++/* Standard handler for SIOCSIWTHRSPY */
++extern int iw_handler_set_thrspy(struct net_device *  dev,
++                               struct iw_request_info *info,
++                               union iwreq_data *     wrqu,
++                               char *                 extra);
++/* Standard handler for SIOCGIWTHRSPY */
++extern int iw_handler_get_thrspy(struct net_device *  dev,
++                               struct iw_request_info *info,
++                               union iwreq_data *     wrqu,
++                               char *                 extra);
++/* Driver call to update spy records */
++extern void wireless_spy_update(struct net_device *   dev,
++                              unsigned char *         address,
++                              struct iw_quality *     wstats);
+ /************************* INLINE FUNTIONS *************************/
+ /*
+--- linux-2.4.21/init/do_mounts.c~small-nocramdisk
++++ linux-2.4.21/init/do_mounts.c
+@@ -16,8 +16,6 @@
+ #include <linux/ext2_fs.h>
+ #include <linux/romfs_fs.h>
+-#define BUILD_CRAMDISK
+-
+ extern int get_filesystem_list(char * buf);
+ extern asmlinkage long sys_mount(char *dev_name, char *dir_name, char *type,
+--- linux-2.4.21/kernel/ksyms.c~ramses
++++ linux-2.4.21/kernel/ksyms.c
+@@ -585,6 +585,11 @@
+ EXPORT_SYMBOL(tasklist_lock);
+ EXPORT_SYMBOL(pidhash);
++#ifdef CONFIG_ARCH_RAMSES
++#include <asm/arch/ramses.h>
++EXPORT_SYMBOL(ramses_control_shadow);
++EXPORT_SYMBOL(ramses_flags);
++#endif
+ /* debug */
+ EXPORT_SYMBOL(dump_stack);
+--- linux-2.4.21/kernel/pm.c~pm
++++ linux-2.4.21/kernel/pm.c
+@@ -234,7 +234,7 @@
+       struct list_head *entry;
+       
+       down(&pm_devs_lock);
+-      entry = pm_devs.next;
++      entry = (rqst==PM_RESUME) ? pm_devs.prev : pm_devs.next;
+       while (entry != &pm_devs) {
+               struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
+               if (dev->callback) {
+@@ -249,7 +249,7 @@
+                               return status;
+                       }
+               }
+-              entry = entry->next;
++              entry = (rqst==PM_RESUME) ? entry->prev : entry->next;
+       }
+       up(&pm_devs_lock);
+       return 0;
+--- linux-2.4.21/mm/swap.c~swap-performance
++++ linux-2.4.21/mm/swap.c
+@@ -28,7 +28,7 @@
+ int page_cluster;
+ pager_daemon_t pager_daemon = {
+-      512,    /* base number for calculating the number of tries */
++      128,    /* base number for calculating the number of tries */
+       SWAP_CLUSTER_MAX,       /* minimum number of tries */
+       8,      /* do swap I/O in clusters of this size */
+ };
+--- linux-2.4.21/mm/vmalloc.c~vmalloc
++++ linux-2.4.21/mm/vmalloc.c
+@@ -183,6 +183,9 @@
+               return NULL;
+       size += PAGE_SIZE;
++#ifdef VMALLOC_ALIGN
++      size = (size + VMALLOC_ALIGN - 1) & ~(VMALLOC_ALIGN - 1);
++#endif
+       if (!size) {
+               kfree (area);
+               return NULL;
+--- linux-2.4.21/net/core/wireless.c~linux-iw241_we16-6
++++ linux-2.4.21/net/core/wireless.c
+@@ -2,7 +2,7 @@
+  * This file implement the Wireless Extensions APIs.
+  *
+  * Authors :  Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+- * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
++ * Copyright (c) 1997-2003 Jean Tourrilhes, All Rights Reserved.
+  *
+  * (As all part of the Linux kernel, this file is GPL)
+  */
+@@ -43,6 +43,11 @@
+  *    o Turn on WE_STRICT_WRITE by default + kernel warning
+  *    o Fix WE_STRICT_WRITE in ioctl_export_private() (32 => iw_num)
+  *    o Fix off-by-one in test (extra_size <= IFNAMSIZ)
++ *
++ * v6 - 9.01.03 - Jean II
++ *    o Add common spy support : iw_handler_set_spy(), wireless_spy_update()
++ *    o Add enhanced spy support : iw_handler_set_thrspy() and event.
++ *    o Add WIRELESS_EXT version display in /proc/net/wireless
+  */
+ /***************************** INCLUDES *****************************/
+@@ -52,6 +57,7 @@
+ #include <linux/types.h>              /* off_t */
+ #include <linux/netdevice.h>          /* struct ifreq, dev_get_by_name() */
+ #include <linux/rtnetlink.h>          /* rtnetlink stuff */
++#include <linux/if_arp.h>             /* ARPHRD_ETHER */
+ #include <linux/wireless.h>           /* Pretty obvious */
+ #include <net/iw_handler.h>           /* New driver API */
+@@ -65,6 +71,7 @@
+ /* Debuging stuff */
+ #undef WE_IOCTL_DEBUG         /* Debug IOCTL API */
+ #undef WE_EVENT_DEBUG         /* Debug Event dispatcher */
++#undef WE_SPY_DEBUG           /* Debug enhanced spy support */
+ /* Options */
+ #define WE_EVENT_NETLINK      /* Propagate events using rtnetlink */
+@@ -72,7 +79,7 @@
+ /************************* GLOBAL VARIABLES *************************/
+ /*
+- * You should not use global variables, because or re-entrancy.
++ * You should not use global variables, because of re-entrancy.
+  * On our case, it's only const, so it's OK...
+  */
+ /*
+@@ -115,11 +122,11 @@
+       /* SIOCSIWSPY */
+       { IW_HEADER_TYPE_POINT, 0, sizeof(struct sockaddr), 0, IW_MAX_SPY, 0},
+       /* SIOCGIWSPY */
+-      { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_GET_SPY, 0},
+-      /* -- hole -- */
+-      { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
+-      /* -- hole -- */
+-      { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
++      { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_SPY, 0},
++      /* SIOCSIWTHRSPY */
++      { IW_HEADER_TYPE_POINT, 0, sizeof(struct iw_thrspy), 1, 1, 0},
++      /* SIOCGIWTHRSPY */
++      { IW_HEADER_TYPE_POINT, 0, sizeof(struct iw_thrspy), 1, 1, 0},
+       /* SIOCSIWAP */
+       { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
+       /* SIOCGIWAP */
+@@ -377,9 +384,9 @@
+       struct net_device *     dev;
+       size = sprintf(buffer,
+-                     "Inter-| sta-|   Quality        |   Discarded packets               | Missed\n"
+-                     " face | tus | link level noise |  nwid  crypt   frag  retry   misc | beacon\n"
+-                      );
++                     "Inter-| sta-|   Quality        |   Discarded packets               | Missed | WE\n"
++                     " face | tus | link level noise |  nwid  crypt   frag  retry   misc | beacon | %d\n",
++                     WIRELESS_EXT);
+       
+       pos += size;
+       len += size;
+@@ -1023,4 +1030,253 @@
+       kfree(event);
+       return;         /* Always success, I guess ;-) */
++}
++
++/********************** ENHANCED IWSPY SUPPORT **********************/
++/*
++ * In the old days, the driver was handling spy support all by itself.
++ * Now, the driver can delegate this task to Wireless Extensions.
++ * It needs to use those standard spy iw_handler in struct iw_handler_def,
++ * push data to us via XXX and include struct iw_spy_data in its
++ * private part.
++ * One of the main advantage of centralising spy support here is that
++ * it becomes much easier to improve and extend it without having to touch
++ * the drivers. One example is the addition of the Spy-Threshold events.
++ * Note : IW_WIRELESS_SPY is defined in iw_handler.h
++ */
++
++/*------------------------------------------------------------------*/
++/*
++ * Standard Wireless Handler : set Spy List
++ */
++int iw_handler_set_spy(struct net_device *    dev,
++                     struct iw_request_info * info,
++                     union iwreq_data *       wrqu,
++                     char *                   extra)
++{
++#ifdef IW_WIRELESS_SPY
++      struct iw_spy_data *    spydata = (dev->priv +
++                                         dev->wireless_handlers->spy_offset);
++      struct sockaddr *       address = (struct sockaddr *) extra;
++
++      /* Disable spy collection while we copy the addresses.
++       * As we don't disable interrupts, we need to do this to avoid races.
++       * As we are the only writer, this is good enough. */
++      spydata->spy_number = 0;
++
++      /* Are there are addresses to copy? */
++      if(wrqu->data.length > 0) {
++              int i;
++
++              /* Copy addresses */
++              for(i = 0; i < wrqu->data.length; i++)
++                      memcpy(spydata->spy_address[i], address[i].sa_data,
++                             ETH_ALEN);
++              /* Reset stats */
++              memset(spydata->spy_stat, 0,
++                     sizeof(struct iw_quality) * IW_MAX_SPY);
++
++#ifdef WE_SPY_DEBUG
++              printk(KERN_DEBUG "iw_handler_set_spy() :  offset %ld, spydata %p, num %d\n", dev->wireless_handlers->spy_offset, spydata, wrqu->data.length);
++              for (i = 0; i < wrqu->data.length; i++)
++                      printk(KERN_DEBUG
++                             "%02X:%02X:%02X:%02X:%02X:%02X \n",
++                             spydata->spy_address[i][0],
++                             spydata->spy_address[i][1],
++                             spydata->spy_address[i][2],
++                             spydata->spy_address[i][3],
++                             spydata->spy_address[i][4],
++                             spydata->spy_address[i][5]);
++#endif        /* WE_SPY_DEBUG */
++      }
++      /* Enable addresses */
++      spydata->spy_number = wrqu->data.length;
++
++      return 0;
++#else /* IW_WIRELESS_SPY */
++      return -EOPNOTSUPP;
++#endif /* IW_WIRELESS_SPY */
++}
++
++/*------------------------------------------------------------------*/
++/*
++ * Standard Wireless Handler : get Spy List
++ */
++int iw_handler_get_spy(struct net_device *    dev,
++                     struct iw_request_info * info,
++                     union iwreq_data *       wrqu,
++                     char *                   extra)
++{
++#ifdef IW_WIRELESS_SPY
++      struct iw_spy_data *    spydata = (dev->priv +
++                                         dev->wireless_handlers->spy_offset);
++      struct sockaddr *       address = (struct sockaddr *) extra;
++      int                     i;
++
++      wrqu->data.length = spydata->spy_number;
++
++      /* Copy addresses. */
++      for(i = 0; i < spydata->spy_number; i++)        {
++              memcpy(address[i].sa_data, spydata->spy_address[i], ETH_ALEN);
++              address[i].sa_family = AF_UNIX;
++      }
++      /* Copy stats to the user buffer (just after). */
++      if(spydata->spy_number > 0)
++              memcpy(extra  + (sizeof(struct sockaddr) *spydata->spy_number),
++                     spydata->spy_stat,
++                     sizeof(struct iw_quality) * spydata->spy_number);
++      /* Reset updated flags. */
++      for(i = 0; i < spydata->spy_number; i++)
++              spydata->spy_stat[i].updated = 0;
++      return 0;
++#else /* IW_WIRELESS_SPY */
++      return -EOPNOTSUPP;
++#endif /* IW_WIRELESS_SPY */
++}
++
++/*------------------------------------------------------------------*/
++/*
++ * Standard Wireless Handler : set spy threshold
++ */
++int iw_handler_set_thrspy(struct net_device * dev,
++                        struct iw_request_info *info,
++                        union iwreq_data *    wrqu,
++                        char *                extra)
++{
++#ifdef IW_WIRELESS_THRSPY
++      struct iw_spy_data *    spydata = (dev->priv +
++                                         dev->wireless_handlers->spy_offset);
++      struct iw_thrspy *      threshold = (struct iw_thrspy *) extra;
++
++      /* Just do it */
++      memcpy(&(spydata->spy_thr_low), &(threshold->low),
++             2 * sizeof(struct iw_quality));
++
++      /* Clear flag */
++      memset(spydata->spy_thr_under, '\0', sizeof(spydata->spy_thr_under));
++
++#ifdef WE_SPY_DEBUG
++      printk(KERN_DEBUG "iw_handler_set_thrspy() :  low %d ; high %d\n", spydata->spy_thr_low.level, spydata->spy_thr_high.level);
++#endif        /* WE_SPY_DEBUG */
++
++      return 0;
++#else /* IW_WIRELESS_THRSPY */
++      return -EOPNOTSUPP;
++#endif /* IW_WIRELESS_THRSPY */
++}
++
++/*------------------------------------------------------------------*/
++/*
++ * Standard Wireless Handler : get spy threshold
++ */
++int iw_handler_get_thrspy(struct net_device * dev,
++                        struct iw_request_info *info,
++                        union iwreq_data *    wrqu,
++                        char *                extra)
++{
++#ifdef IW_WIRELESS_THRSPY
++      struct iw_spy_data *    spydata = (dev->priv +
++                                         dev->wireless_handlers->spy_offset);
++      struct iw_thrspy *      threshold = (struct iw_thrspy *) extra;
++
++      /* Just do it */
++      memcpy(&(threshold->low), &(spydata->spy_thr_low),
++             2 * sizeof(struct iw_quality));
++
++      return 0;
++#else /* IW_WIRELESS_THRSPY */
++      return -EOPNOTSUPP;
++#endif /* IW_WIRELESS_THRSPY */
++}
++
++#ifdef IW_WIRELESS_THRSPY
++/*------------------------------------------------------------------*/
++/*
++ * Prepare and send a Spy Threshold event
++ */
++static void iw_send_thrspy_event(struct net_device *  dev,
++                               struct iw_spy_data *   spydata,
++                               unsigned char *        address,
++                               struct iw_quality *    wstats)
++{
++      union iwreq_data        wrqu;
++      struct iw_thrspy        threshold;
++
++      /* Init */
++      wrqu.data.length = 1;
++      wrqu.data.flags = 0;
++      /* Copy address */
++      memcpy(threshold.addr.sa_data, address, ETH_ALEN);
++      threshold.addr.sa_family = ARPHRD_ETHER;
++      /* Copy stats */
++      memcpy(&(threshold.qual), wstats, sizeof(struct iw_quality));
++      /* Copy also thresholds */
++      memcpy(&(threshold.low), &(spydata->spy_thr_low),
++             2 * sizeof(struct iw_quality));
++
++#ifdef WE_SPY_DEBUG
++      printk(KERN_DEBUG "iw_send_thrspy_event() : address %02X:%02X:%02X:%02X:%02X:%02X, level %d, up = %d\n",
++             threshold.addr.sa_data[0],
++             threshold.addr.sa_data[1],
++             threshold.addr.sa_data[2],
++             threshold.addr.sa_data[3],
++             threshold.addr.sa_data[4],
++             threshold.addr.sa_data[5], threshold.qual.level);
++#endif        /* WE_SPY_DEBUG */
++
++      /* Send event to user space */
++      wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold);
++}
++#endif /* IW_WIRELESS_THRSPY */
++
++/* ---------------------------------------------------------------- */
++/*
++ * Call for the driver to update the spy data.
++ * For now, the spy data is a simple array. As the size of the array is
++ * small, this is good enough. If we wanted to support larger number of
++ * spy addresses, we should use something more efficient...
++ */
++void wireless_spy_update(struct net_device *  dev,
++                       unsigned char *        address,
++                       struct iw_quality *    wstats)
++{
++#ifdef IW_WIRELESS_SPY
++      struct iw_spy_data *    spydata = (dev->priv +
++                                         dev->wireless_handlers->spy_offset);
++      int                     i;
++      int                     match = -1;
++
++#ifdef WE_SPY_DEBUG
++      printk(KERN_DEBUG "wireless_spy_update() :  offset %ld, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_handlers->spy_offset, spydata, address[0], address[1], address[2], address[3], address[4], address[5]);
++#endif        /* WE_SPY_DEBUG */
++
++      /* Update all records that match */
++      for(i = 0; i < spydata->spy_number; i++)
++              if(!memcmp(address, spydata->spy_address[i], ETH_ALEN)) {
++                      memcpy(&(spydata->spy_stat[i]), wstats,
++                             sizeof(struct iw_quality));
++                      match = i;
++              }
++#ifdef IW_WIRELESS_THRSPY
++      /* Generate an event if we cross the spy threshold.
++       * To avoid event storms, we have a simple hysteresis : we generate
++       * event only when we go under the low threshold or above the
++       * high threshold. */
++      if(match >= 0) {
++              if(spydata->spy_thr_under[match]) {
++                      if(wstats->level > spydata->spy_thr_high.level) {
++                              spydata->spy_thr_under[match] = 0;
++                              iw_send_thrspy_event(dev, spydata,
++                                                   address, wstats);
++                      }
++              } else {
++                      if(wstats->level < spydata->spy_thr_low.level) {
++                              spydata->spy_thr_under[match] = 1;
++                              iw_send_thrspy_event(dev, spydata,
++                                                   address, wstats);
++                      }
++              }
++      }
++#endif /* IW_WIRELESS_THRSPY */
++#endif /* IW_WIRELESS_SPY */
+ }
+--- linux-2.4.21/net/ipv4/ipconfig.c~net-dhcp-timeout
++++ linux-2.4.21/net/ipv4/ipconfig.c
+@@ -87,7 +87,7 @@
+ /* Define the timeout for waiting for a DHCP/BOOTP/RARP reply */
+ #define CONF_OPEN_RETRIES     2       /* (Re)open devices twice */
+-#define CONF_SEND_RETRIES     6       /* Send six requests per open */
++#define CONF_SEND_RETRIES     4       /* Send six requests per open */
+ #define CONF_INTER_TIMEOUT    (HZ/2)  /* Inter-device timeout: 1/2 second */
+ #define CONF_BASE_TIMEOUT     (HZ*2)  /* Initial timeout: 2 seconds */
+ #define CONF_TIMEOUT_RANDOM   (HZ)    /* Maximum amount of randomization */
+@@ -1238,9 +1238,11 @@
+ #endif
+                       if (--retries) {
++#ifndef CONFIG_ARCH_RAMSES
+                               printk(KERN_ERR 
+                                      "IP-Config: Reopening network devices...\n");
+                               goto try_try_again;
++#endif
+                       }
+                       /* Oh, well.  At least we tried. */
+--- linux-2.4.21/net/netsyms.c~linux-iw241_we16-6
++++ linux-2.4.21/net/netsyms.c
+@@ -601,6 +601,11 @@
+ #if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO)
+ #include <net/iw_handler.h>
+ EXPORT_SYMBOL(wireless_send_event);
++EXPORT_SYMBOL(iw_handler_set_spy);
++EXPORT_SYMBOL(iw_handler_get_spy);
++EXPORT_SYMBOL(iw_handler_set_thrspy);
++EXPORT_SYMBOL(iw_handler_get_thrspy);
++EXPORT_SYMBOL(wireless_spy_update);
+ #endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
+ #endif  /* CONFIG_NET */
index 143bc71..198ba2d 100644 (file)
@@ -4,7 +4,7 @@ LICENSE = "GPL"
 KV = "2.4.21"
 RMKV = "2"
 PXAV = "1"
-#PR = "r0"
+PR = "r1"
 
 SRC_URI = "ftp://ftp.kernel.org/pub/linux/kernel/v2.4/linux-${KV}.tar.bz2 \
           ftp://ftp.arm.linux.org.uk/pub/armlinux/source/kernel-patches/v2.4/patch-${KV}-rmk${RMKV}.gz;patch=1 \
@@ -62,3 +62,15 @@ kernel_do_install() {
        bzip2 -9 ${D}/boot/*
        install -d ${D}/etc/modutils
 }
+
+do_stage () {
+       rm -rf ${STAGING_INCDIR}/linux ${STAGING_INCDIR}/asm
+       mkdir -p ${STAGING_INCDIR}/linux ${STAGING_INCDIR}/asm
+       cp -a include/linux/* ${STAGING_INCDIR}/linux/
+       cp -a include/asm/* ${STAGING_INCDIR}/asm/
+       find ${STAGING_INCDIR}/linux -name "*~*" | xargs rm
+       find ${STAGING_INCDIR}/asm -name "*~*" | xargs rm
+
+       ln -sf ${STAGING_KERNEL_DIR}/include/linux/wireless.h ${STAGING_INCDIR}/linux/wireless.h
+       ln -sf ${STAGING_KERNEL_DIR}/include/linux/wireless.h ${CROSS_DIR}/${TARGET_SYS}/include/linux/wireless.h
+}
diff --git a/update-modules/update-modules-1.0/ramses/update-modules b/update-modules/update-modules-1.0/ramses/update-modules
new file mode 100644 (file)
index 0000000..e69de29