diff options
author | Holger Schurig <schurig@mn-solutions.de> | 2004-09-30 14:49:57 +0000 |
---|---|---|
committer | Holger Schurig <schurig@mn-solutions.de> | 2004-09-30 14:49:57 +0000 |
commit | 51a1649782b24ee9a6ec1e20a83b02f5e3b8f4dd (patch) | |
tree | 6654c56857a68f1ab6a70824e6996ebe19d6d4fa /linux | |
parent | 7d5b527f225ceb3c28a1942a065da143ea87f593 (diff) |
some MNCI "Ramses" related changes
BKrev: 415c1d15quLlMWHqQc8WEmYm8QzznA
Diffstat (limited to 'linux')
-rw-r--r-- | linux/mnci-ramses-2.4.21-rmk2-pxa1/mnci-combined.patch | 19914 | ||||
-rw-r--r-- | linux/mnci-ramses_2.4.21-rmk2-pxa1.oe | 14 |
2 files changed, 19927 insertions, 1 deletions
diff --git a/linux/mnci-ramses-2.4.21-rmk2-pxa1/mnci-combined.patch b/linux/mnci-ramses-2.4.21-rmk2-pxa1/mnci-combined.patch index e69de29bb2..55d91b9a36 100644 --- a/linux/mnci-ramses-2.4.21-rmk2-pxa1/mnci-combined.patch +++ b/linux/mnci-ramses-2.4.21-rmk2-pxa1/mnci-combined.patch @@ -0,0 +1,19914 @@ + +# 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 ++} ++ ++ ++ ++#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> ++ ++ ++ ++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 */ diff --git a/linux/mnci-ramses_2.4.21-rmk2-pxa1.oe b/linux/mnci-ramses_2.4.21-rmk2-pxa1.oe index 143bc71659..198ba2dcca 100644 --- a/linux/mnci-ramses_2.4.21-rmk2-pxa1.oe +++ b/linux/mnci-ramses_2.4.21-rmk2-pxa1.oe @@ -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 +} |